diff --git a/.editorconfig b/.editorconfig index 210d3ca8519b..198db6e8a17a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,42 @@ -[*.java] +[*] charset=utf-8 end_of_line=lf insert_final_newline=true indent_style=space indent_size=4 +ij_any_block_comment_add_space = false +ij_any_block_comment_at_first_column = false +ij_any_line_comment_at_first_column = false +ij_any_line_comment_add_space = true + +[*.tiny] +indent_style=tab + +[*.bat] +end_of_line=crlf + +[*.yml] +indent_size=2 + +[*.patch] +trim_trailing_whitespace=false + +[*.java] +ij_continuation_indent_size = 4 +ij_java_class_count_to_use_import_on_demand = 999999 +ij_java_insert_inner_class_imports = false +ij_java_names_count_to_use_import_on_demand = 999999 +ij_java_imports_layout = *,|,$* +ij_java_generate_final_locals = true +ij_java_generate_final_parameters = true +ij_java_method_parameters_new_line_after_left_paren = true +ij_java_method_parameters_right_paren_on_new_line = true + +[test-plugin/**/*.java] +ij_java_use_fq_class_names = false + +[Paper-Server/src/main/resources/data/**/*.json] +indent_size = 2 + +[paper-api-generator/generated/**/*.java] +ij_java_imports_layout = $*,|,* diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000000..2ebd41bdf8ec --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf + +*.sh text eol=lf +gradlew text eol=lf +*.bat text eol=crlf + +*.jar binary diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 32de7c702280..ef9fc1fe9408 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ -* @PaperMC/core-team @PaperMC/maintainers +* @PaperMC/paper-maintainers /.github/CODEOWNERS @PaperMC/core-team diff --git a/.github/DISCUSSION_TEMPLATE/ideas.yml b/.github/DISCUSSION_TEMPLATE/ideas.yml new file mode 100644 index 000000000000..a7e34717244d --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/ideas.yml @@ -0,0 +1,42 @@ +labels: ["status: needs triage"] +body: + - type: markdown + attributes: + value: | + Thank you for filling out a feature request for Paper! Please be as detailed as possible so that we may consider and review the request easier. + We ask that you search all the issues to avoid a duplicate feature request. If one exists, please reply if you have anything to add. + Before requesting a new feature, please make sure you are using the latest version and that the feature you are requesting is not already in Paper. + + - type: textarea + attributes: + label: Is your feature request related to a problem? + description: Please give some context for this request. Why do you want it added? + validations: + required: true + + - type: textarea + attributes: + label: Describe the solution you'd like. + description: A clear and concise description of what you want. + validations: + required: true + + - type: textarea + attributes: + label: Describe alternatives you've considered. + description: List any alternatives you might have tried to get the feature you want. + validations: + required: true + + - type: textarea + attributes: + label: Other + description: Add any other context or screenshots about the feature request below. + validations: + required: false + + - type: markdown + attributes: + value: | + Before submitting this feature request, please search our issue tracker to ensure your feature has not + already been requested. diff --git a/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml b/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml deleted file mode 100644 index 2a648e4e4436..000000000000 --- a/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Behavior Bug or Plugin Incompatibility -description: Report issues with plugin incompatbility or other behavior related issues. -body: - - type: markdown - attributes: - value: | - Before reporting a crash here, please make sure you are on the latest version of Paper. - Forks of Paper receive no support here. If you are using a fork, please make sure that this issue also happens when using Paper. - - - type: textarea - attributes: - label: Expected behavior - description: What you expected to see. - validations: - required: true - - type: textarea - attributes: - label: Observed/Actual behavior - description: What you actually saw. - validations: - required: true - - type: textarea - attributes: - label: Steps/models to reproduce - description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. - validations: - required: true - - type: textarea - attributes: - label: Plugin list - description: All plugins running on the server. - validations: - required: true - - type: textarea - attributes: - label: Paper version - description: | - Run `/version` on your server and **paste** the full, unmodified output here. - "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue. - Additionally, do NOT provide a screenshot, you MUST paste the entire output. -
- Example - - ``` - > version - [20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT) - [20:34:42 INFO]: Checking version, please wait... - [20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5) - [20:34:42 INFO]: You are running the latest version - ``` - -
- validations: - required: false - - - type: checkboxes - attributes: - label: Agreements - description: Please agree to the following. - options: - - label: I am running the latest version of Paper available from https://papermc.io/downloads. - required: true - - label: I have searched for and ensured there isn't already an open issue regarding this. - required: true - - label: My version of Minecraft is supported by Paper. - required: true - - - type: textarea - attributes: - label: Other - description: | - Please include other helpful information below. - The more information we receive, the quicker and more effective we can be at finding the solution to the issue. - validations: - required: false - diff --git a/.github/ISSUE_TEMPLATE/bug-or-incompatibility.yml b/.github/ISSUE_TEMPLATE/bug-or-incompatibility.yml new file mode 100644 index 000000000000..5f25e871c956 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-or-incompatibility.yml @@ -0,0 +1,79 @@ +name: "🐛 Bug or Incompatibility" +description: Report issues related to unexpected behavior or vanilla/plugin incompatibility. +type: "Bug" +labels: + - "status: needs triage" +body: + - type: markdown + attributes: + value: | + Before submitting this issue, please ensure the following: + + 1. You are using the latest version of Paper, available on our [our downloads page](https://papermc.io/downloads/paper). + 2. You have searched to confirm there isn’t [an existing open issue](https://github.com/PaperMC/Paper/issues?q=is%3Aissue%20state%3Aopen%20type%3ABug) on this topic. + 3. Your version of Minecraft is supported by Paper. + + If you're unsure whether you've encountered a bug, feel free to ask in the `#paper-help` channel on our + [Discord](https://discord.gg/papermc). + + - type: textarea + attributes: + label: Expected behavior + description: What you expected to see. + validations: + required: true + + - type: textarea + attributes: + label: Observed/Actual behavior + description: What you actually saw. + validations: + required: true + + - type: textarea + attributes: + label: Steps/models to reproduce + description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. + validations: + required: true + + - type: textarea + attributes: + label: Plugin and Datapack List + description: | + All plugins and datapacks running on your server. + To list plugins, run `/plugins`. For datapacks, run `/datapack list`. + validations: + required: true + + - type: textarea + attributes: + label: Paper version + description: | + Run `/version` on your server and **paste** the full, unmodified output here. + "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue. + Additionally, do NOT provide a screenshot, you MUST paste the entire output. +
+ Example + + ``` + > version + [20:34:42 INFO]: Checking version, please wait... + [20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT) + [20:34:42 INFO]: You are running the latest version + [20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21) + ``` + +
+ validations: + required: true + + - type: textarea + attributes: + label: Other + description: | + Please include other helpful information below. + The more information we receive, the quicker and more effective we can be at finding the solution to the issue. + validations: + required: false + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 5316ca71f49e..7cf5bb011b07 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,10 @@ blank_issues_enabled: false contact_links: - - name: PaperMC Discord + - name: "❗Exploits" url: https://discord.gg/papermc - about: If you are having issues with timings or have other minor issues, come ask us on our Discord server! + about: | + Since GitHub doesn’t currently support private issues, exploit reports are managed through our Discord. + To report an exploit, please visit the #paper-exploit-report channel. + - name: "🗨 Questions" + url: https://discord.gg/papermc + about: If you have questions or need help with any minor issues, feel free to ask us on our Discord server! diff --git a/.github/ISSUE_TEMPLATE/crash-or-stacktrace.yml b/.github/ISSUE_TEMPLATE/crash-or-stacktrace.yml new file mode 100644 index 000000000000..badab09bbf77 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/crash-or-stacktrace.yml @@ -0,0 +1,78 @@ +name: "💥 Crash or Stacktrace" +description: Report any server crashes or alarming stack traces. +type: "Bug" +labels: + - "status: needs triage" +body: + - type: markdown + attributes: + value: | + Before submitting this issue, please ensure the following: + + 1. You are running the latest version of Paper from [our downloads page](https://papermc.io/downloads/paper). + 2. Your version of Minecraft is supported by Paper. + + If your server crash log contains `DO NOT REPORT THIS TO PAPER`, please ask in our + [Discord](https://discord.gg/papermc) before opening this issue. These messages are informing you of server + lag and providing debug information. + + - type: textarea + attributes: + label: Stack trace + description: | + We need all of the stack trace! Do not cut off parts of it. Please do not use attachments. + If you prefer, you can use a paste site like https://mclo.gs. + value: | + ``` + paste your stack trace or a mclo.gs link here! + ``` + placeholder: Please don't remove the backticks; it makes your issue a lot harder to read! + validations: + required: true + + - type: textarea + attributes: + label: Plugin and Datapack List + description: | + All plugins and datapacks running on your server. + To list plugins, run `/plugins`. For datapacks, run `/datapack list`. + validations: + required: true + + - type: textarea + attributes: + label: Actions to reproduce (if known) + description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. Anything helps! + validations: + required: false + + - type: textarea + attributes: + label: Paper version + description: | + Run `/version` on your server and **paste** the full, unmodified output here. + "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue. + Additionally, do NOT provide a screenshot, you MUST paste the entire output. +
+ Example + + ``` + > version + [20:34:42 INFO]: Checking version, please wait... + [20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT) + [20:34:42 INFO]: You are running the latest version + [20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21) + ``` + +
+ validations: + required: true + + - type: textarea + attributes: + label: Other + description: | + Please include other helpful information below, if any. + The more information we receive, the quicker and more effective we can be at finding the solution to the issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml deleted file mode 100644 index db9e28daa741..000000000000 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Feature Request -description: Suggest an idea for Paper -body: - - type: markdown - attributes: - value: | - Thank you for filling out a feature request for Paper! Please be as detailed as possible so that we may consider and review the request easier. - We ask that you search all the issues to avoid a duplicate feature request. If one exists, please reply if you have anything to add. - Before requesting a new feature, please make sure you are using the latest version and that the feature you are requesting is not already in Paper. - - - type: textarea - attributes: - label: Is your feature request related to a problem? - description: Please give some context for this request. Why do you want it added? - validations: - required: true - - type: textarea - attributes: - label: Describe the solution you'd like. - description: A clear and concise description of what you want. - validations: - required: true - - type: textarea - attributes: - label: Describe alternatives you've considered. - description: List any alternatives you might have tried to get the feature you want. - validations: - required: true - - - type: checkboxes - attributes: - label: Agreements - description: Please agree to the following. - options: - - label: I have searched for and ensured there isn't already an open issue regarding this. - required: true - - label: I have ensured the feature I'm requesting isn't already in the latest supported Paper build. - required: true - - - type: textarea - attributes: - label: Other - description: Add any other context or screenshots about the feature request below. - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/new-feature.yml b/.github/ISSUE_TEMPLATE/new-feature.yml new file mode 100644 index 000000000000..731b4a2f534e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new-feature.yml @@ -0,0 +1,53 @@ +name: "💡 New Feature" +description: Propose a new idea for Paper. +type: "Feature" +labels: + - "status: needs triage" +body: + - type: markdown + attributes: + value: | + Thank you for submitting a feature request for Paper! Please be as detailed as possible to help us review and consider your request effectively. + Before submitting, please ensure the following: + + 1. You are using a supported version of Paper. + 2. The feature you’re requesting isn’t already included in the version you’re using. + 3. You’ve searched for and confirmed there isn’t already [an open request](https://github.com/PaperMC/Paper/issues?q=is%3Aissue%20is%3Aopen%20type%3AFeature) for this feature. + - If a similar request exists, feel free to add any additional details you think are helpful. + + If you have any questions, feel free to ask in the `#paper-help` or `#paper-dev` channels on our [Discord](https://discord.gg/papermc). + + - type: textarea + attributes: + label: Is your feature request related to a problem? + description: Please provide some context for this request. Why do you want it added? + validations: + required: true + + - type: textarea + attributes: + label: Describe the solution you'd like. + description: A clear and concise description of what you want. + validations: + required: true + + - type: textarea + attributes: + label: Describe alternatives you've considered. + description: List any alternatives you might have tried to get the feature you want. + validations: + required: true + + - type: textarea + attributes: + label: Other + description: Add any other context or screenshots about the feature request below. + validations: + required: false + + - type: markdown + attributes: + value: | + Before submitting this feature request, please search our issue tracker to ensure your feature has not + already been requested. + diff --git a/.github/ISSUE_TEMPLATE/performance-problem.yml b/.github/ISSUE_TEMPLATE/performance-problem.yml index e0d39def74c2..e13221132c9e 100644 --- a/.github/ISSUE_TEMPLATE/performance-problem.yml +++ b/.github/ISSUE_TEMPLATE/performance-problem.yml @@ -1,41 +1,64 @@ -name: Performance Problem -description: Report performance related problems or other areas of concern +name: "🐌 Performance Problem" +description: Report any performance issues. +type: "Bug" +labels: + - "scope: performance" + - "status: needs triage" body: - type: markdown attributes: value: | - Before reporting performance problems here, please make sure you are on the latest version of Paper. - Forks of Paper receive no support here. If you are using a fork, please make sure that this problem also affects Paper. + Before submitting this issue, please ensure the following: + + 1. You are running the latest version of Paper from [our downloads page](https://papermc.io/downloads/paper). + 2. You searched for and ensured there isn't already [an open issue](https://github.com/PaperMC/Paper/issues?q=is%3Aissue%20state%3Aopen%20type%3ABug) regarding this. + 3. Your version of Minecraft is supported by Paper. + + - type: markdown + attributes: + value: | + Before creating an issue regarding server performance, please consider reaching out for support in the + `#paper-help` channel of [our Discord](https://discord.gg/papermc)! + - type: input attributes: - label: Timings or Profile link - description: We ask that all timings/profiles are a link, not a screenshot. Screenshots inhibit our ability to figure out the real cause of the issue. - placeholder: "Example: https://timings.aikar.co/?id=6b48586fbbdd48e585ca0ebb07c59dd0" + label: Spark Profile + description: | + Please provide all profiles as links rather than screenshots. Screenshots limit our ability to investigate the root cause of the issue. + + For more information, see our [profiling documentation](https://docs.papermc.io/paper/profiling). + placeholder: "Example: https://spark.lucko.me/XsN0hxGfsi" validations: required: true + - type: textarea attributes: label: Description of issue description: If applicable, please describe your issue. validations: required: false + - type: textarea attributes: - label: Plugin list - description: All plugins running on the server. + label: Plugin and Datapack List + description: | + All plugins and datapacks running on your server. + To list plugins, run `/plugins`. For datapacks, run `/datapack list`. validations: required: true + - type: textarea attributes: label: Server config files - description: We need bukkit.yml, spigot.yml, paper.yml, and server.properties. You can paste it below or use a paste site like https://paste.gg. + description: We need bukkit.yml, spigot.yml, paper-global.yml, paper-world-defaults.yml and server.properties. If you use per-world Paper configs, make sure to include them. You can paste it below or use a paste site like https://mclo.gs. value: | ``` - Paste configs or paste.gg link here! + Paste configs or mclo.gs link here! ``` placeholder: Please don't remove the backticks; it makes your issue a lot harder to read! validations: required: true + - type: textarea attributes: label: Paper version @@ -48,27 +71,15 @@ body: ``` > version - [20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT) [20:34:42 INFO]: Checking version, please wait... - [20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5) + [20:34:42 INFO]: This server is running Paper version 1.21-105-master@7e91a2c (2024-07-20T21:04:31Z) (Implementing API version 1.21-R0.1-SNAPSHOT) [20:34:42 INFO]: You are running the latest version + [20:34:42 INFO]: Previous version: 1.21-103-aa3b356 (MC: 1.21) ``` validations: - required: false - - - type: checkboxes - attributes: - label: Agreements - description: Please agree to the following. - options: - - label: I am running the latest version of Paper available from https://papermc.io/downloads. - required: true - - label: I have searched for and ensured there isn't already an open issue regarding this. - required: true - - label: My version of Minecraft is supported by Paper. - required: true + required: true - type: textarea attributes: diff --git a/.github/ISSUE_TEMPLATE/server-crash-or-stacktrace.yml b/.github/ISSUE_TEMPLATE/server-crash-or-stacktrace.yml deleted file mode 100644 index 9958e717d253..000000000000 --- a/.github/ISSUE_TEMPLATE/server-crash-or-stacktrace.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Server crash or Stacktrace -description: Report server crashes or scary stacktraces -body: - - type: markdown - attributes: - value: | - Before reporting a crash here, please make sure you are on the latest version of Paper. - Forks of Paper receive no support here. If you are using a fork, please make sure that this crash also happens when using Paper. - Please do not make reports when the report says "DO NOT REPORT THIS TO PAPER". These are simply messages informing you of lag, to find what is causing it. Ask for tips on Discord or IRC instead. - - - type: textarea - attributes: - label: Stack trace - description: | - We need all of the stack trace! Do not cut off parts of it. Please do not use attachments. - If you prefer, you can use a paste site like https://paste.gg. - value: | - ``` - paste your stack trace or a paste.gg link here! - ``` - placeholder: Please don't remove the backticks; it makes your issue a lot harder to read! - validations: - required: true - - type: textarea - attributes: - label: Plugin list - description: All plugins running on the server. - validations: - required: true - - type: textarea - attributes: - label: Actions to reproduce (if known) - description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. Anything helps! - validations: - required: false - - type: textarea - attributes: - label: Paper version - description: | - Run `/version` on your server and **paste** the full, unmodified output here. - "latest" is *not* a version; we require the output of `/version` so we can adequately track down the issue. - Additionally, do NOT provide a screenshot, you MUST paste the entire output. -
- Example - - ``` - > version - [20:34:42 INFO]: This server is running Paper version git-Paper-540 (MC: 1.16.5) (Implementing API version 1.16.5-R0.1-SNAPSHOT) - [20:34:42 INFO]: Checking version, please wait... - [20:34:42 INFO]: Previous version: git-Paper-538 (MC: 1.16.5) - [20:34:42 INFO]: You are running the latest version - ``` - -
- validations: - required: false - - - type: checkboxes - attributes: - label: Agreements - description: Please agree to the following. - options: - - label: I am running the latest version of Paper available from https://papermc.io/downloads. - required: true - - label: I have searched for and ensured there isn't already an open issue regarding this. - required: true - - label: My version of Minecraft is supported by Paper. - required: true - - - type: textarea - attributes: - label: Other - description: | - Please include other helpful information below, if any. - The more information we receive, the quicker and more effective we can be at finding the solution to the issue. - validations: - required: false diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index b67a072020bb..000000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,18 +0,0 @@ -daysUntilStale: 60 -daysUntilClose: 7 -exemptLabels: - - "for: future" - - "type: bug" - - "status: accepted" - - "status: blocked" - - "status: in progress" - - "status: rebase required" -staleLabel: "resolution: stale" -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. -closeComment: > - This issue has been automatically closed because it has not had activity in - a long time. If the issue still applies to the most recent supported - version, please open a new issue referencing this original issue. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d20809707090..994ade949c05 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,38 +1,116 @@ # Here lie dragons! # -# Note that there is no artifact step in this script. We do not want Paperclip -# jars to be built for every push & PR; our CI handles pushes to branches, while -# PRs can themselves link to Paperclip jars if it is necessary. Official such -# PRs will take use of testing builds. +# This action either builds the server or +# builds a paperclip jar to be updated in the body +# of the PR relating to this action. name: Build Paper -on: [push, pull_request] +on: + push: + pull_request: + types: + - opened + - reopened + - synchronize + - labeled jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - java: [11, 8] - fail-fast: true - steps: - - uses: actions/checkout@v2 - - name: JDK ${{ matrix.java }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java }} - - name: Cache maven - uses: actions/cache@v2 - with: - path: | - ~/.m2/repository/ - work/Minecraft - key: ${{ runner.os }}-paper-2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-paper-2 - - name: Patch and build - run: | - git config --global user.email "no-reply@github.com" - git config --global user.name "Github Actions" - ./paper build - - name: Build javadocs - run: mvn -pl Paper-API,Paper-MojangAPI -am javadoc:javadoc + build: + # Run on all label events (won't be duplicated) or all push events or on PR syncs not from the same repo + if: (github.event_name == 'pull_request' && github.event.action == 'labeled') || github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name + runs-on: ubuntu-latest + strategy: + matrix: + java: [21] + fail-fast: true + steps: + - if: ${{ github.event_name == 'push' }} + uses: actions/checkout@v4 + - if: ${{ github.event_name == 'pull_request' }} + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: JDK ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java }} + distribution: 'zulu' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Configure Build + uses: actions/github-script@v7 + id: determine + env: + REF_NAME: "${{ github.ref_name }}" + REF_TYPE: "${{ github.ref_type }}" + EVENT: "${{ toJSON(github.event) }}" + EVENT_TYPE: "${{ github.event_name }}" + with: + script: | + const {owner, repo} = context.repo; + const event_name = `${process.env.EVENT_TYPE}`; + const event = JSON.parse(`${process.env.EVENT}`); + const ref_type = `${process.env.REF_TYPE}`; + const ref_name = `${process.env.REF_NAME}`; + const result = { + action: "build" + }; + + if (event_name === "push" && ref_type === "branch") { + const {data: pulls} = await github.rest.pulls.list({ owner, repo, head: `${owner}:${ref_name}`, state: "open" }); + const pull = pulls.find((pr) => !!pr.labels.find((l) => l.name === "build-pr-jar")); + if (pull) { + result["pr"] = pull.number; + result["action"] = "paperclip"; + core.notice(`This is a push action but to a branch with an open PR with the build paperclip label (${JSON.stringify(result)})`); + return result; + } + } else if (event_name === "pull_request" && event.pull_request.labels.find((l) => l.name === "build-pr-jar")) { + result["pr"] = event.pull_request.number; + result["action"] = "paperclip"; + core.notice(`This is a pull request action with a build paperclip label (${JSON.stringify(result)})`); + return result; + } + core.notice("This will not build a paperclip jar"); + return result; + + - name: Apply Patches + run: | + git config --global user.email "no-reply@github.com" + git config --global user.name "GitHub Actions" + ./gradlew applyPatches --stacktrace + + - name: Build + run: ./gradlew build --stacktrace + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (${{ matrix.java }}) + path: | + **/build/test-results/test/TEST-*.xml + + - name: Create Paperclip Jar + if: fromJSON(steps.determine.outputs.result).action == 'paperclip' + run: ./gradlew createMojmapPaperclipJar --stacktrace + + - name: Upload Paperclip Jar + if: fromJSON(steps.determine.outputs.result).action == 'paperclip' + uses: actions/upload-artifact@v4 + with: + name: paper-${{ fromJSON(steps.determine.outputs.result).pr }} + path: build/libs/paper-paperclip-*-mojmap.jar + event_file: + name: "Event File" + # Only run on PRs if the source branch is on someone else's repo + if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: Event File + path: ${{ github.event_path }} diff --git a/.github/workflows/close_invalid_prs.yml b/.github/workflows/close_invalid_prs.yml new file mode 100644 index 000000000000..ef572c25c8f8 --- /dev/null +++ b/.github/workflows/close_invalid_prs.yml @@ -0,0 +1,27 @@ +name: Close invalid PRs + +on: + pull_request_target: + types: [ opened ] + +jobs: + run: + if: | + github.repository != github.event.pull_request.head.repo.full_name && + ( + github.head_ref == 'master' || + github.event.pull_request.head.repo.owner.type != 'User' + ) + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + id: "master_branch" + if: github.head_ref == 'master' + with: + comment: "Please do not open pull requests from the `master` branch, create a new branch instead." + + - uses: superbrothers/close-pull-request@v3 + id: "org_account" + if: github.event.pull_request.head.repo.owner.type != 'User' && steps.master_branch.outcome == 'skipped' + with: + comment: "Please do not open pull requests from non-user accounts like organizations. Create a fork on a user account instead." diff --git a/.github/workflows/pr_comment.yml b/.github/workflows/pr_comment.yml new file mode 100644 index 000000000000..60bed3fd38e5 --- /dev/null +++ b/.github/workflows/pr_comment.yml @@ -0,0 +1,84 @@ +# This workflow run on the completion of the +# build workflow but only does anything if the +# triggering workflow uploaded an artifact. +# +# Do note that it is then the trigger workflow that +# determines if this will update the PR text body. All +# this workflow does is check if an uploaded artifact +# exists and there is a PR tied to the previous workflow. + +name: Comment on pull request +on: + workflow_run: + workflows: ['Build Paper'] + types: [completed] +jobs: + pr_comment: + if: github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + env: + BRANCH_NAME: "${{ github.event.workflow_run.head_branch }}" + PR_OWNER: "${{ github.event.workflow_run.head_repository.owner.login }}" + PR_SHA: "${{ github.event.workflow_run.head_sha }}" + RUN_ID: "${{ github.event.workflow_run.id }}" + REPO_ID: "${{ github.event.repository.id }}" + EVENT_TYPE: "${{ github.event.workflow_run.event}}" + PULL_REQUESTS: "${{ toJSON(github.event.workflow_run.pull_requests) }}" + with: + # This snippet is public-domain, taken from + # https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml + # Modified extensively by Machine_Maker + script: | + async function updatePR(owner, repo, issue_number, purpose, body) { + const { data } = await github.rest.issues.get({ owner, repo, issue_number }); + core.debug(JSON.stringify(data, null, 2)); + + const marker = ``; + + let new_body = data.body ? data.body.trim().split(marker)[0].trim() : ""; + new_body += `\n${marker}\n---\n${body}`; + + core.info(`Updating the text body of PR #${issue_number} in ${owner}/${repo}`); + await github.rest.issues.update({ owner, repo, issue_number, body: new_body }); + } + + const { owner, repo } = context.repo; + const run_id = `${process.env.RUN_ID}`; + const repo_id = `${process.env.REPO_ID}`; + + let pulls = []; + const event_type = `${process.env.EVENT_TYPE}`; + if (event_type === "push") { // if push, it's from the same repo which means `pull_requests` is populated + pulls = JSON.parse(`${process.env.PULL_REQUESTS}`); + } else { + const pr_branch = `${process.env.BRANCH_NAME}`; + const pr_sha = `${process.env.PR_SHA}`; + const pr_owner = `${process.env.PR_OWNER}`; + const { data } = await github.rest.pulls.list({ owner, repo, head: `${pr_owner}:${pr_branch}`, state: "open" }); + core.debug(JSON.stringify(data, null, 2)); + pulls = data.filter((pr) => pr.head.sha === pr_sha && pr.labels.find((l) => l.name === "build-pr-jar")); + } + + if (!pulls.length) { + return core.notice("This workflow doesn't have any pull requests!"); + } else if (pulls.length > 1) { + core.info(JSON.stringify(pulls, null, 2)); + return core.error("Found multiple matching PRs"); + } + const pull_request = pulls[0]; + + const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, { owner, repo, run_id }); + if (!artifacts.length) { + return core.info("Skipping comment due to no artifact found"); + } + const artifact = artifacts.find((art) => art.name === `paper-${pull_request.number}`); + if (!artifact) { + return core.info("Skipping comment to no matching artifact found"); + } + + const link = `https://nightly.link/${owner}/${repo}/actions/artifacts/${artifact.id}.zip`; + const body = `Download the paperclip jar for this pull request: [${artifact.name}.zip](${link})`; + core.info(`Adding a link to ${link}`); + await updatePR(owner, repo, pull_request.number, "paperclip-pr-build", body); diff --git a/.github/workflows/projects.yml b/.github/workflows/projects.yml new file mode 100644 index 000000000000..5a42cedc1046 --- /dev/null +++ b/.github/workflows/projects.yml @@ -0,0 +1,76 @@ +name: Update Projects + +on: + issues: + types: + - labeled + - unlabeled + - closed + - reopened + +jobs: + bugs: + if: "github.event_name == 'issues' && contains(github.event.*.labels.*.name, 'type: bug')" + concurrency: + group: update-bugs-project-${{ github.event.issue.number }} + cancel-in-progress: true + runs-on: ubuntu-latest + steps: + - name: "authenticate" + id: "authenticate" + uses: "tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92" # v1 + with: + app_id: "${{ secrets.PROJECTS_APP_ID }}" + installation_id: "36153445" + private_key: "${{ secrets.PROJECTS_PRIVATE_KEY }}" + + - uses: PaperMC/update-projects-action@v0.2.0 + name: Update open issue + if: github.event.issue.state == 'open' + with: + github-token: "${{ steps.authenticate.outputs.token }}" + project-url: https://github.com/orgs/PaperMC/projects/5/views/2 + column-field: Status + label-to-column-map: | + { + "resolution: awaiting response": "⌛ Awaiting Response", + "resolution: cannot reproduce": "Invalid", + "resolution: duplicate": "Invalid", + "resolution: incomplete": "Invalid", + "resolution: invalid": "Invalid", + "resolution: superseded": "Invalid", + "resolution: unsupported": "Invalid", + "resolution: won't fix": "Invalid", + "resolution: works as intended": "Invalid", + "status: accepted": "✅ Accepted", + "status: blocked": "Needs Work", + "status: defer upstream": "Needs Work", + "status: in progress": "Needs Work", + "status: input wanted": "Needs Work", + "status: needs triage": "🕑 Needs Triage", + "status: rebase required": "Needs Work", + "status: unlikely": "✅ Accepted" + } + + - uses: PaperMC/update-projects-action@v0.2.0 + name: Update closed issue + if: github.event.issue.state == 'closed' + with: + github-token: "${{ steps.authenticate.outputs.token }}" + project-url: https://github.com/orgs/PaperMC/projects/5/views/2 + column-field: Status + clear-on-no-match: false + # include "status: needs triage" below to catch any closed issues without setting a resolution + label-to-column-map: | + { + "resolution: cannot reproduce": "Invalid", + "resolution: duplicate": "Invalid", + "resolution: incomplete": "Invalid", + "resolution: invalid": "Invalid", + "resolution: superseded": "Invalid", + "resolution: unsupported": "Invalid", + "resolution: won't fix": "Invalid", + "resolution: works as intended": "Invalid", + "status: accepted": "Done", + "status: needs triage": "Invalid" + } diff --git a/.github/workflows/test_results.yml b/.github/workflows/test_results.yml new file mode 100644 index 000000000000..f3c63cf8fb87 --- /dev/null +++ b/.github/workflows/test_results.yml @@ -0,0 +1,32 @@ +name: Test Results + +on: + workflow_run: + workflows: [ "Build Paper" ] + types: + - completed +permissions: { } + +jobs: + test-results: + name: Test Results + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion != 'skipped' + permissions: + checks: write + # for downloading test result artifacts + actions: read + steps: + - name: Download and Extract Artifacts + uses: dawidd6/action-download-artifact@v6 + with: + run_id: ${{ github.event.workflow_run.id }} + path: artifacts + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + commit: ${{ github.event.workflow_run.head_sha }} + event_file: artifacts/Event File/event.json + event_name: ${{ github.event.workflow_run.event }} + files: "artifacts/**/*.xml" + comment_mode: off diff --git a/.gitignore b/.gitignore index b1e563f2233e..a2adff58b60b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.gradle/ +build/ + # Eclipse stuff .classpath .project @@ -21,7 +24,6 @@ dependency-reduced-pom.xml .*.sw[a-p] # various other potential build files -build/ bin/ dist/ manifest.mf @@ -51,11 +53,15 @@ work/ForgeFlower .idea/ out/ +# JetBrains Fleet +.fleet/ + # Linux temp files *~ # other stuff run/ +logs/ Paper-Server Paper-API @@ -63,3 +69,8 @@ Paperclip.jar paperclip.jar paperclip-*.jar paperclip.properties + +!gradle/wrapper/gradle-wrapper.jar + +test-plugin.settings.gradle.kts +paper-api-generator.settings.gradle.kts diff --git a/.gitmodules b/.gitmodules index 758536e06138..7280fb743dd4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,3 @@ [submodule "work/Spigot"] path = work/Spigot url = https://hub.spigotmc.org/stash/scm/spigot/spigot.git -[submodule "work/Paperclip"] - path = work/Paperclip - url = https://github.com/PaperMC/Paperclip.git diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f4503c5656c..32be536ebcea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,44 +4,11 @@ PaperMC is happy you're willing to contribute to our projects. We are usually very lenient with all submitted PRs, but there are still some guidelines you can follow to make the approval process go more smoothly. -**Table of contents:** - - - -* [Use a Personal Fork and not Organization](#use-a-personal-fork-and-not-organization) -* [Requirements](#requirements) -* [Understanding Patches](#understanding-patches) -* [Adding Patches](#adding-patches) -* [Modifying Patches](#modifying-patches) - * [Method 1](#method-1) - * [Using the Paper tool](#using-the-paper-tool) - * [Manual method: Stashing](#manual-method-stashing) - * [Method 2 - Fixup commits](#method-2---fixup-commits) - * [Manual method](#manual-method) - * [Automatic method](#automatic-method) -* [PR Policy](#pr-policy) -* [Rebasing PRs](#rebasing-prs) -* [Formatting](#formatting) -* [Patch Notes](#patch-notes) -* [Obfuscation Helpers](#obfuscation-helpers) -* [Configuration files](#configuration-files) - * [PaperConfig example](#paperconfig-example) - * [PaperWorldConfig example](#paperworldconfig-example) -* [Frequently Asked Questions](#frequently-asked-questions) - * [I can't find the NMS file I need!](#i-cant-find-the-nms-file-i-need) - * [Where can I learn how to name method/field?](#where-can-i-learn-how-to-name-methodfield) - * [My commit doesn't need a build, what do I do?](#my-commit-doesnt-need-a-build-what-do-i-do) - * [Patching and building is *really* slow, what can I do?](#patching-and-building-is-really-slow-what-can-i-do) - * [I wrote some API, how do I use it in Paper-Server?](#i-wrote-some-api-how-do-i-use-it-in-paper-server) - - - -## Use a Personal Fork and not Organization +## Use a Personal Fork and not an Organization Paper will routinely modify your PR, whether it's a quick rebase or to take care of any minor nitpicks we might have. Often, it's better for us to solve these -problems for you than make you go back and forth trying to fix it yourself. +problems for you than make you go back and forth trying to fix them yourself. Unfortunately, if you use an organization for your PR, it prevents Paper from modifying it. This requires us to manually merge your PR, resulting in us @@ -60,25 +27,26 @@ which can be obtained in (most) package managers such as `apt` (Debian / Ubuntu; you will most likely use this for WSL), `homebrew` (macOS / Linux), and more: - `git` (package `git` everywhere); -- `patch` (often package `patch`); -- A Java 8 or later JDK (packages vary, use Google/DuckDuckGo/etc.). -If you need one, you can find them on [AdoptOpenJDK](https://adoptopenjdk.net/). -- `maven` (often package `maven`; can be found on -[Apache's site](https://maven.apache.org/download.cgi) too); -- `curl` (package `curl` everywhere). +- A Java 21 or later JDK (packages vary, use Google/DuckDuckGo/etc.). + - [Adoptium](https://adoptium.net/) has builds for most operating systems. + - Paper requires JDK 21 to build, however, makes use of Gradle's + [Toolchains](https://docs.gradle.org/current/userguide/toolchains.html) + feature to allow building with only JRE 11 or later installed. (Gradle will + automatically provision JDK 21 for compilation if it cannot find an existing + install). If you're on Windows, check [the section on WSL](#patching-and-building-is-really-slow-what-can-i-do). -If you're compiling with Docker, you can use the -[`adoptopenjdk`](https://hub.docker.com/_/adoptopenjdk/) images like so: +If you're compiling with Docker, you can use Adoptium's +[`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/) images like so: ```console -# docker run -it -v "$(pwd)":/data --rm adoptopenjdk:8-jdk-hotspot bash +# docker run -it -v "$(pwd)":/data --rm eclipse-temurin:21.0.3_9-jdk bash Pulling image... root@abcdefg1234:/# javac -version -javac 1.8.0_252 +javac 21.0.3 ``` ## Understanding Patches @@ -88,8 +56,6 @@ split into different directories which target certain parts of the code. These directories are: - `Paper-API` - Modifications to `Spigot-API`/`Bukkit`; -- `Paper-MojangAPI` - An API for -[Mojang's Brigadier](https://github.com/Mojang/brigadier); - `Paper-Server` - Modifications to `Spigot`/`CraftBukkit`. Because the entire structure is based on patches and git, a basic understanding @@ -99,24 +65,18 @@ of how to use git is required. A basic tutorial can be found here: Assuming you have already forked the repository: 1. Clone your fork to your local machine; -1. Type `./paper patch` in a terminal to apply the changes from upstream; -1. cd into `Paper-Server` for server changes, and `Paper-API` for API changes. -You can also run `./paper server` or `./paper api` for these same directories +2. Type `./gradlew applyPatches` in a terminal to apply the changes from upstream. +On Windows, replace the `./` with `.\` at the beginning for all `gradlew` commands; +3. cd into `Paper-Server` for server changes, and `Paper-API` for API changes. + `Paper-Server` and `Paper-API` aren't git repositories in the traditional sense: -- Every single commit in `Paper-Server`/`Paper-API` is a patch; -- `origin/master` points to a directory similar to `Paper-Server`/`Paper-API` -but for Paper; -- Typing `git status` should show that we are 10 or 11 commits ahead of master, -meaning we have 10 or 11 patches Spigot and CraftBukkit don't. - - If it says something like `212 commits ahead, 207 commits behind`, - cd into the root directory of the cloned repository and type `git fetch` to - update your upstream. Setting up a remote for the upstream Paper repository - might be necessary. +- `base` points to the unmodified source before Paper patches have been applied. +- Each commit after `base` is a patch. ## Adding Patches @@ -125,7 +85,7 @@ Adding patches to Paper is very simple: 1. Modify `Paper-Server` and/or `Paper-API` with the appropriate changes; 1. Type `git add .` inside these directories to add your changes; 1. Run `git commit` with the desired patch message; -1. Run `./paper rebuild` in the main directory to convert your commit into a new +1. Run `./gradlew rebuildPatches` in the main directory to convert your commit into a new patch; 1. PR the generated patch file(s) back to this repository. @@ -136,7 +96,9 @@ Your commit will be converted into a patch that you can then PR into Paper. ## Modifying Patches -Modifying previous patches is a bit more complex: +Modifying previous patches is a bit more complex. +Similar to adding patches, the methods to modify a patch are applied inside +the `Paper-Server` and/or `Paper-API` folders. ### Method 1 @@ -146,38 +108,13 @@ edit it using `git rebase`. > ❗ While in the middle of an edit, you will not be able to compile unless you > *also* reset the opposing module(s) to a related commit. In the API's case, > you must reset the Server, and reset the API if you're editing the Server. - -#### Using the Paper tool - -The PaperMC build tool provides a handy command to automatically do this type of -patch modification. - -1. Type `./paper edit server` or `./paper edit api` depending on which project -you want to edit; - - It should show something like - [this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159) in - the text editor you get. - - If your editor does not have a "menu" at the bottom, you're using `vim`. - If you don't know how to use `vim` and don't want to - learn, enter `:q!` and press enter. Before redoing this step, do - `export EDITOR=nano` for an easier editor to use. -1. Replace `pick` with `edit` for the commit/patch you want to modify, and -"save" the changes; - - Only do this for **one** commit at a time. -1. Make the changes you want to make to the patch; -1. Type `./paper edit continue` in the root directory to finish and rebuild -patches; -1. PR your modified patch file(s) back to this repository. - -#### Manual method: Stashing - -In case you need something more complex or want more control, these step-by-step -instruction do exactly what the above slightly automated system above does. +> Note also that either module _may_ not compile when doing so. This is not +> ideal nor intentional, but it happens. Feel free to fix this in a PR to us! 1. If you have changes you are working on, type `git stash` to store them for later; - You can type `git stash pop` to get them back at any point. -1. Type `git rebase -i upstream/upstream`; +1. Type `git rebase -i base`; - It should show something like [this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159) in the text editor you get. @@ -194,7 +131,7 @@ later; - **Make sure to add `--amend`** or else a new patch will be created. - You can also modify the commit message and author here. 1. Type `git rebase --continue` to finish rebasing; -1. Type `./paper rebuild` in the root directory; +1. Type `./gradlew rebuildPatches` in the root directory; - This will modify the appropriate patches based on your commits. 1. PR your modified patch file(s) back to this repository. @@ -211,14 +148,14 @@ messing with your HEADs. 1. Make your change while at HEAD; 1. Make a temporary commit. You don't need to make a message for this; -1. Type `git rebase -i upstream/upstream`, move (cut) your temporary commit and +1. Type `git rebase -i base`, move (cut) your temporary commit and move it under the line of the patch you wish to modify; 1. Change the `pick` to the appropriate action: 1. `f`/`fixup`: Merge your changes into the patch without touching the message. 1. `s`/`squash`: Merge your changes into the patch and use your commit message and subject. -1. Type `./paper rebuild` in the root directory; +1. Type `./gradlew rebuildPatches` in the root directory; - This will modify the appropriate patches based on your commits. 1. PR your modified patch file(s) back to this repository. @@ -232,10 +169,10 @@ move it under the line of the patch you wish to modify; assist you too. - Alternatively, if you only know the name of the patch, you can do `git commit -a --fixup "Subject of Patch name"`. -1. Rebase with autosquash: `git rebase --autosquash -i upstream/upstream`. +1. Rebase with autosquash: `git rebase -i --autosquash base`. This will automatically move your fixup commit to the right place, and you just need to "save" the changes. -1. Type `./paper rebuild` in the root directory; +1. Type `./gradlew rebuildPatches` in the root directory; - This will modify the appropriate patches based on your commits. 1. PR your modified patch file(s) back to this repository. @@ -244,14 +181,17 @@ need to "save" the changes. Steps to rebase a PR to include the latest changes from `master`. These steps assume the `origin` remote is your fork of this repository and `upstream` is the official PaperMC repository. -1. Pull latest changes from upstream's master: `git checkout master && git pull upstream master`. +1. Pull the latest changes from upstreams master: `git checkout master && git pull upstream master`. 1. Checkout feature/fix branch and rebase on master: `git checkout patch-branch && git rebase master`. -1. Apply updated patches: `./paper patch`. +1. Apply updated patches: `./gradlew applyPatches`. 1. If there are conflicts, fix them. -1. If your PR creates new patches instead of modifying exist ones, in both the `Paper-Server` and `Paper-API` directories, ensure your newly-created patch is the last commit by either: - * Renaming the patch file with a large 4 digit number in front (e.g. 9999-Patch-to-add-some-new-stuff.patch) - * Run `git rebase --interactive upstream/upstream` and move the commits to the end. -1. Rebuild patches: `./paper rebuild`. + * If there are conflicts within `Paper-API`, after fixing them run `./gradlew rebuildApiPatches` before re-running `./gradlew applyPatches`. + * The API patches are applied first, so if there are conflicts in the API patches, the server patches will not be applied. +1. If your PR creates new patches instead of modifying existing ones, in both the `Paper-Server` and `Paper-API` directories, ensure your newly-created patch is the last commit by either: + * Renaming the patch file with a large 4-digit number in front (e.g. 9999-Patch-to-add-some-new-stuff.patch), and re-applying patches. + * Running `git rebase --interactive base` and moving the commits to the end. +1. Rebuild patches: `./gradlew rebuildPatches`. +1. Commit modified patches. 1. Force push changes: `git push --force`. ## PR Policy @@ -267,37 +207,100 @@ when making and submitting changes. ## Formatting -All modifications to non-Paper files should be marked. +All modifications to non-Paper files should be marked. The one exception to this is +when modifying javadoc comments, which should not have these markers. -- Multi-line changes start with `// Paper start` and end with `// Paper end`; -- You can put a comment with an explanation if it isn't obvious, like this: -`// Paper start - reason`. - - The comments should generally be about the reason the change was made, what - it was before, or what the change is. - - Multi-line messages should start with `// Paper start` and use `/* Multi - line message here */` for the message itself. -- One-line changes should have `// Paper` or `// Paper - reason`. +- You need to add a comment with a short and identifiable description of the patch: + `// Paper start - ` + - The comments should generally be about the reason the change was made, what + it was before, or what the change is. + - After the general commit description, you can add additional information either + after a `;` or in the next line. +- Multi-line changes start with `// Paper start - ` and end + with `// Paper end - `. +- One-line changes should have `// Paper - ` at the end of the line. Here's an example of how to mark changes by Paper: ```java -entity.getWorld().dontbeStupid(); // Paper - was beStupid() which is bad +entity.getWorld().dontBeStupid(); // Paper - Was beStupid(), which is bad entity.getFriends().forEach(Entity::explode); -entity.a(); -entity.b(); -// Paper start - use plugin-set spawn +entity.updateFriends(); + +// Paper start - Use plugin-set spawn // entity.getWorld().explode(entity.getWorld().getSpawn()); Location spawnLocation = ((CraftWorld)entity.getWorld()).getSpawnLocation(); entity.getWorld().explode(new BlockPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ())); -// Paper end +// Paper end - Use plugin-set spawn ``` -We generally follow usual Java style (aka. Oracle style), or what is programmed +We generally follow the usual Java style (aka. Oracle style), or what is programmed into most IDEs and formatters by default. There are a few notes, however: - It is fine to go over 80 lines as long as it doesn't hurt readability. There are exceptions, especially in Spigot-related files - When in doubt or the code around your change is in a clearly different style, use the same style as the surrounding code. +- Usage of the `var` keyword is heavily discouraged, as it makes reading patch files +a lot harder and can lead to confusion during updates due to changed return types. +The only exception to this is if a line would otherwise be way too long/filled with +hard to parse generics in a case where the base type itself is already obvious + +### Imports +When adding new imports to a class in a file not created by the current patch, use the fully qualified class name +instead of adding a new import to the top of the file. If you are using a type a significant number of times, you +can add an import with a comment. However, if its only used a couple of times, the FQN is preferred to prevent future +patch conflicts in the import section of the file. + +### Nullability annotations + +We are in the process of switching nullability annotation libraries, so you might need to use one or the other: + +**For classes we add**: Fields, method parameters and return types that are nullable should be marked via the +`@Nullable` annotation from `org.jspecify.annotations`. Whenever you create a new class, add `@NullMarked`, meaning types +are assumed to be non-null by default. For less obvious placing such as on generics or arrays, see the [JSpecify docs](https://jspecify.dev/docs/user-guide/). + +**For classes added by upstream**: Keep using both `@Nullable` and `@NotNull` from `org.jetbrains.annotations`. These +will be replaced later. + +```java +import org.bukkit.event.Event; +// don't add import here, use FQN like below + +public class SomeEvent extends Event { + public final org.bukkit.Location newLocation; // Paper - add location +} +``` + +## Access Transformers +Sometimes, vanilla or CraftBukkit code already contains a field, method, or type you want to access +but the visibility is too low (e.g. a private field in an entity class). Paper can use access transformers +to change the visibility or remove the final modifier from fields, methods, and classes. Inside the `build-data/paper.at` +file, you can add ATs that are applied when you `./gradlew applyPatches`. You can read about the format of ATs +[here](https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers). + +### Important +ATs should be included in the patch file which requires them within the commit message. Do not commit any changes to the +`build-data/paper.at` file, just use it to initially change the visibility of members until you have finalized what you +need. Then, in the commit message for the patch which requires the ATs, add a header at the bottom of the commit message +before any co-authors. It should look like the following after you `./gradlew rebuildPatches`. +``` +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 8 Jun 2022 22:20:16 -0700 +Subject: [PATCH] Paper config files + +This patch adds Paper configuration files. +Access transformers for this patch are below, but before the co-authors. + +== AT == +public org.spigotmc.SpigotWorldConfig getBoolean(Ljava/lang/String;Z)Z +public net.minecraft.world.level.NaturalSpawner SPAWNING_CATEGORIES + +Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> + +diff --git a/build.gradle.kts b/build.gradle.kts +... +``` ## Patch Notes @@ -334,7 +337,7 @@ Subject: [PATCH] revert serverside behavior of keepalives This patch intends to bump up the time that a client has to reply to the server back to 30 seconds as per pre 1.12.2, which allowed clients more than enough time to reply potentially allowing them to be less -tempermental due to lag spikes on the network thread, e.g. that caused +temperamental due to lag spikes on the network thread, e.g. that caused by plugins that are interacting with netty. We also add a system property to allow people to tweak how long the server @@ -352,31 +355,18 @@ index a92bf8967..d0ab87d0f 100644 ## Obfuscation Helpers -In an effort to make future updates easier on ourselves, Paper tries to use -obfuscation helpers whenever possible. The purpose of these helpers is to make -the code more readable and maintainable. These helpers should be be made as easy -to inline as possible by the JVM whenever possible. - -An obfuscation helper to access an obfuscated item may be as simple as something -like this: - -```java -public final int getStuckArrows() { return this.bY(); } // Paper - OBFHELPER -``` - -Or it may be as complex as forwarding an entire method so that it can be -overridden later: +While rarely needed, obfuscation helpers are sometimes useful when it comes +to unmapped local variables, or poorly named method parameters. In an effort +to make future updates easier on ourselves, Paper tries to use obfuscation +helpers wherever it makes sense. The purpose of these helpers is to make the +code more readable and maintainable. These helpers should be made easy to +inline by the JVM wherever possible. +An example of an obfuscation helper for a local variable: ```java -public boolean be() { - // Paper start - OBFHELPER - return this.pushedByWater(); -} - -public boolean pushedByWater() { - // Paper end - return true; -} +double d0 = entity.getX(); final double fromX = d0; // Paper - OBFHELPER +// ... +this.someMethod(fromX); // Paper ``` While they may not always be done in exactly the same way, the general goal is @@ -385,56 +375,83 @@ what fits best in your situation. ## Configuration files -To use a configurable value in your patch, add a new entry in either the -`PaperConfig` or `PaperWorldConfig` classes. Use `PaperConfig` if a value +To use a configurable value in your patch, add a new field in either the +`GlobalConfiguration` or `WorldConfiguration` classes (inside the +`io.papermc.paper.configuration` package). Use `GlobalConfiguration` if a value must remain the same throughout all worlds, or the latter if it can change between worlds. World-specific configuration options are preferred whenever possible. -### PaperConfig example - +### Example +This is adding a new miscellaneous setting that doesn't seem to fit in other categories. +Try to check and see if an existing category (inner class) exists that matches +whatever configuration option you are adding. ```java -public static boolean saveEmptyScoreboardTeams = false; -private static void saveEmptyScoreboardTeams() { - // This is called automatically! - // The name also doesn't matter. - saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); +public class GlobalConfiguration { + // other sections + public class Misc extends ConfigurationPart { + // other settings + public boolean lagCompensateBlockBreaking = true; + public boolean useDimensionTypeForCustomSpawners = false; + public int maxNumOfPlayers = 20; // This is the new setting + } } ``` - -Notice that the field is always public, but the setter is always private. This -is important to the way the configuration generation system works. To access -this value, reference it as you would any other static value: - +You set the type of the setting as the field type, and the default value is the +initial field value. The name of the setting defaults to the snake-case of the +field name, so in this case it would be `misc.max-num-of-players`. You can use +the `@Setting` annotation to override that, but generally just try to set the +field name to what you want the setting to be called. + +#### Accessing the value +If you added a new global config value, you can access it in the code just by +doing +```java +int maxPlayers = GlobalConfiguration.get().misc.maxNumOfPlayers; +``` +Generally for global config values you will use the fully qualified class name, +`io.papermc.paper.configuration.GlobalConfiguration` since it's not imported in +most places. +--- +If you are adding a new world config value, you must have access to an instance +of the `net.minecraft.world.level.Level` which you can then access the config by doing ```java -if (!PaperConfig.saveEmptyScoreboardTeams) { +int maxPlayers = level.paperConfig().misc.maxNumOfPlayers; ``` -It is often preferred that you use the fully qualified name for the -configuration class when accessing it, like so: -`com.destroystokyo.paper.PaperConfig.valueHere`. -If this is not done, a developer for Paper might fix that for you before -merging, but it's always nice if you make it a habit where you only need 1-2 -lines changed. +#### Committing changes +All changes to the `GlobalConfiguration` and `WorldConfiguration` files +should be done in the commit that created them. So do an interactive rebase +or fixup to apply just those changes to that commit, then add a new commit +that includes the logic that uses that option in the server somewhere. -### PaperWorldConfig example +## Testing API changes -```java -public boolean useInhabitedTime = true; -private void useInhabitedTime() { - // This is called automatically! - // The name also doesn't matter. - useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); -} -``` +### Using the Paper Test Plugin -Again, notice that the field is always public, but the setter is always private. -To access this value, you'll need an instance of the `net.minecraft.World` -object: +The Paper project has a `test-plugin` module for easily testing out API changes +and additions. To use the test plugin, enable it in `test-plugin.settings.gradle.kts`, +which will be generated after running Gradle at least once. After this, you can edit +the test plugin, and run a server with the plugin using `./gradlew runDev` (or any +of the other Paper run tasks). -```java -return this.world.paperConfig.useInhabitedTime ? this.w : 0; -``` +### Publishing to Maven local (use in external plugins) + +To build and install the Paper APIs and Server to your local Maven repository, do the following: + +- Run `./gradlew publishToMavenLocal` in the base directory. + +If you use Gradle to build your plugin: +- Add `mavenLocal()` as a repository. Gradle checks repositories in the order they are declared, + so if you also have the Paper repository added, put the local repository above Paper's. +- Make sure to remove `mavenLocal()` when you are done testing, see the [Gradle docs](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:case-for-maven-local) + for more details. + +If you use Maven to build your plugin: +- If you later need to use the Paper-API, you might want to remove the jar + from your local Maven repository. + If you use Windows and don't usually build using WSL, you might not need to + do this. ## Frequently Asked Questions @@ -449,39 +466,25 @@ patching process. progress will be lost if you do not; 1. Identify the name(s) of the file(s) you want to import. - A complete list of all possible file names can be found at - `./work/Minecraft/$MCVER/spigot/net/minecraft/server`. You might find - [MiniMappingViewer] very useful to find the file you need. -1. Open the file at `./scripts/importmcdev.sh` and add the name of your file to -the script. Skip to the 2nd last header and follow the instructions there; -1. Re-patch the server `./paper patch`; + `./Paper-Server/.gradle/caches/paperweight/mc-dev-sources/net/minecraft/`. You might find + [MappingViewer] useful if you need to translate between Mojang and Spigot mapped names. +1. Open the file at `./build-data/dev-imports.txt` and add the name of your file to +the script. Follow the instructions there; +1. Re-patch the server `./gradlew applyPatches`; 1. Edit away! > ❗ This change is temporary! **DO NOT COMMIT CHANGES TO THIS FILE!** > Once you have made your changes to the new file, and rebuilt patches, you may -> undo your changes to `importmcdev.sh`. +> undo your changes to `dev-imports.txt`. Any file modified in a patch file gets automatically imported, so you only need this temporarily to import it to create the first patch. -To undo your changes to the file, type `git checkout scripts/importmcdev.sh`. - -### Where can I learn how to name method/field? - -For most cases, it is preferred if you use [yarn], as their license works with -Paper's license. If you can't do that, [MiniMappingViewer] is always around to -provide you with more of a general idea, *but* you cannot use the Mojang names -for more than understanding the code. - -[yarn] is in general more thorough than Mojang's own mappings, as they include -method arguments as well, whereas Mojang's do not. If you need local variables -to understand the code, you might be more lucky with ModCoderPack. - -For more information on the Mojang name licensing issues, check this out: - +To undo your changes to the file, type `git checkout build-data/dev-imports.txt`. ### My commit doesn't need a build, what do I do? -Well, quite simple: You add `[CI-SKIP]` to the start of your commit subject. +Well, quite simple: You add `[ci skip]` to the start of your commit subject. This case most often applies to changes to files like `README.md`, this very file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth. @@ -489,16 +492,16 @@ file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth. ### Patching and building is *really* slow, what can I do? This only applies if you're running Windows. If you're running a prior Windows -release, either update to Windows 10 or move to macOS/Linux/BSD. +release, either update to Windows 10/11 or move to macOS/Linux/BSD. In order to speed up patching process on Windows, it's recommended you get WSL 2. This is available in Windows 10 v2004, build 19041 or higher. (You can check your version by running `winver` in the run window (Windows key + R)). If you're -out of date, update your system with the -[Windows Update Assistant](https://www.microsoft.com/en-us/software-download/windows10). +using an out of date version of Windows 10, update your system with the +[Windows 10 Update Assistant](https://www.microsoft.com/en-us/software-download/windows10) or [Windows 11 Update Assistant](https://www.microsoft.com/en-us/software-download/windows11). -To setup WSL 2, follow the information here: - +To set up WSL 2, follow the information here: + You will most likely want to use the Ubuntu apps. Once it's set up, install the required tools with `sudo apt-get update && sudo apt-get install $TOOL_NAMES @@ -508,26 +511,6 @@ everything like usual. > ❗ Do not use the `/mnt/` directory in WSL! Instead, mount the WSL directories > in Windows like described here: -> - -### I wrote some API, how do I use it in Paper-Server? - -To install the API to your local maven repository, do the following: - -- Enter the API directory by running `./paper api`; -- Run `mvn install`. - - If you are working on a patch without much care for whether the tests - pass, you can instead run `mvn install -DskipTests`. Do not PR changes - without running tests first. - - If a test failed, you have to identify the failing tests by scrolling up a - couple lines (i.e. around 50-200). You should find it fairly quickly. - - If you later need to use the Paper-API, you might want to remove the jar - from your local maven repository. - If you use Windows and don't usually build using WSL, you might not need to - do this. - -You can now use the API in your plugin to test it before PRing. You will also -need to do this to build the Server with the implemented API. +> -[MiniMappingViewer]: https://minidigger.github.io/MiniMappingViewer/ -[yarn]: https://github.com/FabricMC/yarn +[MappingViewer]: https://mappings.cephx.dev/ diff --git a/LICENSE.md b/LICENSE.md index 071cd357d42d..687fd815fe88 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -17,7 +17,6 @@ should submit a pull request to this project to add their name. ```text Zach Brown Daniel Ennis -Kyle Wood kashike Black Hole Mark Vainomaa @@ -29,7 +28,7 @@ chickeneer Minecrell Techcable BillyGalbreath -MiniDigger +MiniDigger Brokkonaut vemacs stonar96 @@ -41,11 +40,29 @@ rickyboy320 DoNotSpamPls <7570108+DoNotSpamPls@users.noreply.github.com> JRoy ysl3000 -KennyTV Machine_Maker Ivan Pekov Camotoy <20743703+Camotoy@users.noreply.github.com> -Bjarne Koll +Bjarne Koll MeFisto94 Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +LemonCaramel +Noah van der Aa +Doc +Nick Hensel +vytskalt +TheFruxz +Kieran Wallbanks +Denery +Jakubk15 +Redned +Luke Chambers +Emily +dawon +Ollie <69084614+olijeffers0n@users.noreply.github.com> +Oliwier Miodun +aerulion +Lukas Planz +granny +mja00 ``` diff --git a/Paper-MojangAPI/pom.xml b/Paper-MojangAPI/pom.xml deleted file mode 100644 index 7712a8723cdd..000000000000 --- a/Paper-MojangAPI/pom.xml +++ /dev/null @@ -1,204 +0,0 @@ - - - 4.0.0 - - com.destroystokyo.paper - paper-parent - dev-SNAPSHOT - - - com.destroystokyo.paper - paper-mojangapi - 1.16.5-R0.1-SNAPSHOT - jar - - Paper-MojangAPI - https://github.com/PaperMC/Paper - API additions that utilize Mojang Specific API's - - - - 1.8 - 1.8 - UTF-8 - - - - - spigotmc-public - https://hub.spigotmc.org/nexus/content/groups/public/ - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - - minecraft-libraries - Minecraft Libraries - https://libraries.minecraft.net - - - - - - spigotmc-public - https://hub.spigotmc.org/nexus/content/groups/public/ - - - - - - com.destroystokyo.paper - paper-api - ${project.version} - provided - - - - com.mojang - brigadier - 1.0.17 - compile - - - - it.unimi.dsi - fastutil - 8.2.2 - provided - - - - org.jetbrains - annotations - 18.0.0 - provided - - - - junit - junit - 4.13.1 - test - - - org.hamcrest - hamcrest-library - 1.3 - test - - - org.ow2.asm - asm-tree - 7.3.1 - test - - - - - clean install - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - - - org.codehaus.plexus - plexus-compiler-eclipse - 2.8.5-spigotmc - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - org.bukkit - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - - - ${project.build.directory}/dependency-reduced-pom.xml - - true - - - - - - - - development - - false - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.1.0 - - - process-classes - - check - - - - - checkstyle.xml - true - - - - com.puppycrawl.tools - checkstyle - 8.29 - - - - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.18 - - - process-classes - - check - - - - - - org.codehaus.mojo.signature - java18 - 1.0 - - - - - - - - diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java deleted file mode 100644 index 3848933b674a..000000000000 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.destroystokyo.paper.brigadier; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.suggestion.SuggestionProvider; - -import java.util.function.Predicate; - -public interface BukkitBrigadierCommand extends Command, Predicate, SuggestionProvider { -} diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java deleted file mode 100644 index 7a0e81658cc2..000000000000 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.destroystokyo.paper.brigadier; - -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Entity; -import org.jetbrains.annotations.Nullable; - -public interface BukkitBrigadierCommandSource { - - @Nullable - Entity getBukkitEntity(); - - @Nullable - World getBukkitWorld(); - - @Nullable - Location getBukkitLocation(); - - CommandSender getBukkitSender(); -} diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java deleted file mode 100644 index a275a85ad2dc..000000000000 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.destroystokyo.paper.event.brigadier; - -import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; -import com.mojang.brigadier.tree.RootCommandNode; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Fired any time a Brigadier RootCommandNode is generated for a player to inform the client of commands. - * You may manipulate this CommandNode to change what the client sees. - * - * This event may fire on login, world change, and permission rebuilds, by plugin request, and potentially future means. - * - * This event will fire before {@link org.bukkit.event.player.PlayerCommandSendEvent}, so no filtering has been done by - * other plugins yet. - * - * WARNING: This event will potentially (and most likely) fire twice! Once for Async, and once again for Sync. - * It is important that you check event.isAsynchronous() and event.hasFiredAsync() to ensure you only act once. - * If for some reason we are unable to send this asynchronously in the future, only the sync method will fire. - * - * Your logic should look like this: - * if (event.isAsynchronous() || !event.hasFiredAsync()) { do stuff } - * - * If your logic is not safe to run asynchronously, only react to the synchronous version. - * @deprecated Draft API - Subject to change until confirmed solves desired use cases - */ -public class AsyncPlayerSendCommandsEvent extends PlayerEvent { - - private static final HandlerList handlers = new HandlerList(); - private final RootCommandNode node; - private final boolean hasFiredAsync; - - public AsyncPlayerSendCommandsEvent(Player player, RootCommandNode node, boolean hasFiredAsync) { - super(player, !Bukkit.isPrimaryThread()); - this.node = node; - this.hasFiredAsync = hasFiredAsync; - } - - /** - * @return The full Root Command Node being sent to the client, which is mutable. - */ - public RootCommandNode getCommandNode() { - return node; - } - - /** - * @return If this event has already fired asynchronously. - */ - public boolean hasFiredAsync() { - return hasFiredAsync; - } - - @NotNull - public HandlerList getHandlers() { - return handlers; - } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java deleted file mode 100644 index 13819b618505..000000000000 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.destroystokyo.paper.event.brigadier; - -import com.mojang.brigadier.suggestion.Suggestions; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Called when sending Suggestions to the client. Will be called asynchronously if a plugin - * marks the AsyncTabComplete event handled asynchronously, otherwise called synchronously. - */ -public class AsyncPlayerSendSuggestionsEvent extends PlayerEvent implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled = false; - - private Suggestions suggestions; - private final String buffer; - - public AsyncPlayerSendSuggestionsEvent(Player player, Suggestions suggestions, String buffer) { - super(player, !Bukkit.isPrimaryThread()); - this.suggestions = suggestions; - this.buffer = buffer; - } - - /** - * @return The input buffer sent to request these suggestions - */ - public String getBuffer() { - return buffer; - } - - /** - * @return The suggestions being sent to client - */ - public Suggestions getSuggestions() { - return suggestions; - } - - /** - * @param suggestions The suggestions to be sent to client if need to change them - */ - public void setSuggestions(Suggestions suggestions) { - this.suggestions = suggestions; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isCancelled() { - return this.cancelled; - } - - /** - * Cancels sending suggestions to the client - * {@inheritDoc} - */ - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @NotNull - public HandlerList getHandlers() { - return handlers; - } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java b/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java deleted file mode 100644 index 92924622b5a0..000000000000 --- a/Paper-MojangAPI/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.destroystokyo.paper.event.brigadier; - -import com.destroystokyo.paper.brigadier.BukkitBrigadierCommand; -import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; -import com.mojang.brigadier.tree.ArgumentCommandNode; -import com.mojang.brigadier.tree.LiteralCommandNode; -import com.mojang.brigadier.tree.RootCommandNode; -import org.bukkit.command.Command; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.server.ServerEvent; -import org.jetbrains.annotations.NotNull; - -/** - * Fired anytime the server synchronizes Bukkit CommandMap to Brigadier. - * - * Allows a plugin to control the Literal and Argument nodes for this command to be - * sent to the client. - * This is done at Plugin Enable time after commands have been registered, but some - * plugins may use reflection to retrigger this rebuild during runtime. - * - * @deprecated Draft API - Subject to change until confirmed solves desired use cases - */ -public class CommandRegisteredEvent extends ServerEvent implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); - private final String commandLabel; - private final Command command; - private final BukkitBrigadierCommand brigadierCommand; - private final RootCommandNode root; - private final ArgumentCommandNode defaultArgs; - private LiteralCommandNode literal; - private boolean cancelled = false; - - public CommandRegisteredEvent(String commandLabel, BukkitBrigadierCommand brigadierCommand, Command command, RootCommandNode root, LiteralCommandNode literal, ArgumentCommandNode defaultArgs) { - this.commandLabel = commandLabel; - this.brigadierCommand = brigadierCommand; - this.command = command; - this.root = root; - this.literal = literal; - this.defaultArgs = defaultArgs; - } - - /** - * @return The command name being registered - */ - public String getCommandLabel() { - return commandLabel; - } - - /** - * @return The Bukkit API Brigadier Wrapped Command Object to handle executions and suggestions - */ - public BukkitBrigadierCommand getBrigadierCommand() { - return brigadierCommand; - } - - public Command getCommand() { - return command; - } - - /** - * @return Gets the root command node being used to register a command to. - */ - public RootCommandNode getRoot() { - return root; - } - - /** - * Returns the Bukkit API's default handling of Arguments, if you wish to reuse it. - * @return - */ - public ArgumentCommandNode getDefaultArgs() { - return defaultArgs; - } - - /** - * Returns the Bukkit API's default literal for this command, including the {@link #getDefaultArgs()} as a child already. - * @return - */ - public LiteralCommandNode getLiteral() { - return literal; - } - - /** - * Changes the literal used to register this command. The previous literable is mutable, so this is primarily if - * you want to completely replace the object. - * @param literal - */ - public void setLiteral(LiteralCommandNode literal) { - this.literal = literal; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isCancelled() { - return this.cancelled; - } - - /** - * Cancels registering this command to Brigadier, but will remain in Bukkit Command Map. Can be used to hide a - * command from all players. - * - * {@inheritDoc} - */ - @Override - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - - @NotNull - public HandlerList getHandlers() { - return handlers; - } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java deleted file mode 100644 index 1ed5a6d271b7..000000000000 --- a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.papermc.paper.brigadier; - -import com.mojang.brigadier.Message; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.ComponentLike; -import net.kyori.adventure.text.TextComponent; -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * Helper methods to bridge the gaps between Brigadier and Paper-MojangAPI. - */ -public final class PaperBrigadier { - private PaperBrigadier() { - throw new RuntimeException("PaperBrigadier is not to be instantiated!"); - } - - /** - * Create a new Brigadier {@link Message} from a {@link ComponentLike}. - * - *

Mostly useful for creating rich suggestion tooltips in combination with other Paper-MojangAPI APIs.

- * - * @param componentLike The {@link ComponentLike} to use for the {@link Message} contents - * @return A new Brigadier {@link Message} - */ - public static @NonNull Message message(final @NonNull ComponentLike componentLike) { - return PaperBrigadierProvider.instance().message(componentLike); - } - - /** - * Create a new {@link Component} from a Brigadier {@link Message}. - * - *

If the {@link Message} was created from a {@link Component}, it will simply be - * converted back, otherwise a new {@link TextComponent} will be created with the - * content of {@link Message#getString()}

- * - * @param message The {@link Message} to create a {@link Component} from - * @return The created {@link Component} - */ - public static @NonNull Component componentFromMessage(final @NonNull Message message) { - return PaperBrigadierProvider.instance().componentFromMessage(message); - } -} diff --git a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java deleted file mode 100644 index 7f248063843c..000000000000 --- a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.papermc.paper.brigadier; - -import com.mojang.brigadier.Message; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.ComponentLike; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.checkerframework.checker.nullness.qual.NonNull; - -import static java.util.Objects.requireNonNull; - -interface PaperBrigadierProvider { - final class Holder { - private static @MonotonicNonNull PaperBrigadierProvider INSTANCE; - } - - static @NonNull PaperBrigadierProvider instance() { - return requireNonNull(Holder.INSTANCE, "PaperBrigadierProvider has not yet been initialized!"); - } - - static void initialize(final @NonNull PaperBrigadierProvider instance) { - if (Holder.INSTANCE != null) { - throw new IllegalStateException("PaperBrigadierProvider has already been initialized!"); - } - Holder.INSTANCE = instance; - } - - @NonNull Message message(@NonNull ComponentLike componentLike); - - @NonNull Component componentFromMessage(@NonNull Message message); -} diff --git a/README.md b/README.md index f580b62708ef..e9e7033fd4db 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,101 @@ -Paper ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/PaperMC/Paper/Build%20Paper/master) +> [!CAUTION] +> **This branch will be deleted soon, please replace usage of it with the new `main` branch**. +> +> If you need history from before 1.21.4, please use the archive repo: https://github.com/PaperMC/Paper-archive + +Paper [![Paper Build Status](https://img.shields.io/github/actions/workflow/status/PaperMC/Paper/build.yml?branch=master)](https://github.com/PaperMC/Paper/actions) +[![Discord](https://img.shields.io/discord/289587909051416579.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/papermc) +[![GitHub Sponsors](https://img.shields.io/github/sponsors/papermc?label=GitHub%20Sponsors)](https://github.com/sponsors/PaperMC) +[![Open Collective](https://img.shields.io/opencollective/all/papermc?label=OpenCollective%20Sponsors)](https://opencollective.com/papermc) =========== -High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies. +The most widely used, high-performance Minecraft server that aims to fix gameplay and mechanics inconsistencies. **Support and Project Discussion:** - - [IRC](https://webchat.esper.net/?channels=paper) or [Discord](https://discord.gg/papermc) - +- [Our forums](https://forums.papermc.io/) or [Discord](https://discord.gg/papermc) How To (Server Admins) ------ Paperclip is a jar file that you can download and run just like a normal jar file. -Download Paper from our [downloads page](https://papermc.io/downloads). +Download Paper from our [downloads page](https://papermc.io/downloads/paper). Run the Paperclip jar directly from your server. Just like old times - * Documentation on using Paper: [paper.readthedocs.io](https://paper.readthedocs.io/) - * For a sneak peak on upcoming features, [see here](https://github.com/PaperMC/Paper/projects) +* Documentation on using Paper: [docs.papermc.io](https://docs.papermc.io) +* For a sneak peek at upcoming features, [see here](https://github.com/PaperMC/Paper/projects) How To (Plugin Developers) ------ - * See our API patches [here](Spigot-API-Patches) - * See upcoming, pending, and recently added API [here](https://github.com/PaperMC/Paper/projects/6) - * Paper API javadocs here: [papermc.io/javadocs](https://papermc.io/javadocs/) - * Maven Repo (for paper-api): +* See our API patches [here](patches/api) +* See upcoming, pending, and recently added API [here](https://github.com/orgs/PaperMC/projects/2/views/4) +* Paper API javadocs here: [papermc.io/javadocs](https://papermc.io/javadocs/) +#### Repository (for paper-api) +##### Maven + ```xml papermc - https://papermc.io/repo/repository/maven-public/ + https://repo.papermc.io/repository/maven-public/ ``` - * Artifact Information: + ```xml - com.destroystokyo.paper + io.papermc.paper paper-api - 1.16.5-R0.1-SNAPSHOT + 1.21.4-R0.1-SNAPSHOT provided - ``` - -**Or alternatively, with Gradle:** - - * Repository: -```groovy +``` +##### Gradle +```kotlin repositories { maven { - url 'https://papermc.io/repo/repository/maven-public/' + url = uri("https://repo.papermc.io/repository/maven-public/") } } -``` - * Artifact: -```groovy + dependencies { - compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } ``` How To (Compiling Jar From Source) ------ -To compile Paper, you need JDK 8, maven, and an internet connection. +To compile Paper, you need JDK 21 and an internet connection. -Clone this repo, run `./paper jar` from *bash*, get files. +Clone this repo, run `./gradlew applyPatches`, then `./gradlew createMojmapBundlerJar` from your terminal. You can find the compiled jar in the project root's `build/libs` directory. + +To get a full list of tasks, run `./gradlew tasks`. How To (Pull Request) ------ See [Contributing](CONTRIBUTING.md) +Support Us +------ +First of all, thank you for considering helping out, we really appreciate that! + +PaperMC has various recurring expenses, mostly related to infrastructure. Paper uses [Open Collective](https://opencollective.com/) via the [Open Source Collective fiscal host](https://opencollective.com/opensource) to manage expenses. Open Collective allows us to be extremely transparent, so you can always see how your donations are used. You can read more about financially supporting PaperMC [on our website](https://papermc.io/sponsors). + +You can find our collective [here](https://opencollective.com/papermc), or you can donate via GitHub Sponsors [here](https://github.com/sponsors/PaperMC), which will also go towards the collective. + Special Thanks To: ------------- -![YourKit-Logo](https://www.yourkit.com/images/yklogo.png) +[![YourKit-Logo](https://www.yourkit.com/images/yklogo.png)](https://www.yourkit.com/) [YourKit](https://www.yourkit.com/), makers of the outstanding java profiler, support open source projects of all kinds with their full featured [Java](https://www.yourkit.com/java/profiler) and [.NET](https://www.yourkit.com/.net/profiler) application profilers. We thank them for granting Paper an OSS license so that we can make our software the best it can be. + +[](https://www.jetbrains.com) + +[JetBrains](https://www.jetbrains.com/), creators of the IntelliJ IDEA, supports Paper with one of their [Open Source Licenses](https://www.jetbrains.com/opensource/). IntelliJ IDEA is the recommended IDE for working with Paper, and most of the Paper team uses it. + +All our sponsors! +[![Sponsor Image](https://raw.githubusercontent.com/PaperMC/papermc.io/data/sponsors.png)](https://papermc.io/sponsors) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000000..139ea872d543 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +We generally only fully support the latest version, the same applies to exploits such as server crashes and item +duplication bugs. In the transition period during larger Minecraft updates, we may still backport important fixes to the +last minor or major release. + +## Reporting a Vulnerability + +For any issues that are NOT duplication bugs, server/client crashes, or otherwise serious exploits, please open an issue +through the [Issues tab](https://github.com/PaperMC/Paper/issues). +For exploits, please [join our Discord](https://discord.gg/papermc) and see the [#paper-exploit-report channel](https://discord.com/channels/289587909051416579/1208749386348101682) for +further instructions. diff --git a/Spigot-API-Patches/0001-POM-changes.patch b/Spigot-API-Patches/0001-POM-changes.patch deleted file mode 100644 index 2cd563eafa89..000000000000 --- a/Spigot-API-Patches/0001-POM-changes.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 00:16:08 +0100 -Subject: [PATCH] POM changes - - -diff --git a/pom.xml b/pom.xml -index 0223e94c1243a58955f858c8bf6d5df4ca8cf0ec..fd663f5471516c3ebbab07c27197e5df48c481e6 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -2,33 +2,34 @@ - - 4.0.0 -+ -+ com.destroystokyo.paper -+ paper-parent -+ dev-SNAPSHOT -+ - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api - 1.16.5-R0.1-SNAPSHOT - jar - -- Spigot-API -- https://www.spigotmc.org/ -+ Paper-API -+ https://github.com/PaperMC/Paper - An enhanced plugin API for Minecraft servers. - - -- true -+ - 1.8 - 1.8 - UTF-8 - - -- -+ - -- spigotmc-releases -- https://hub.spigotmc.org/nexus/content/repositories/releases/ -+ sonatype -+ https://oss.sonatype.org/content/groups/public/ - -- -- spigotmc-snapshots -- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ -- -- -+ - - - -@@ -37,6 +38,20 @@ - 2.6 - compile - -+ -+ -+ com.google.code.findbugs -+ jsr305 -+ 1.3.9 -+ compile -+ -+ -+ -+ com.googlecode.json-simple -+ json-simple -+ 1.1.1 -+ compile -+ - - - com.google.guava -@@ -112,6 +127,7 @@ - - - -+ clean install - - - net.md-5 -@@ -130,10 +146,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -@@ -183,6 +195,7 @@ - - - -+ ${project.build.directory}/dependency-reduced-pom.xml - - true - diff --git a/Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch b/Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch deleted file mode 100644 index a5e6eda88d69..000000000000 --- a/Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 1 Apr 2016 00:02:47 -0400 -Subject: [PATCH] Add FastUtil to Bukkit - -Doesn't expose to plugins, just allows Paper-API to use it for optimization - -diff --git a/pom.xml b/pom.xml -index 61b8ee4e3e122dd2671f50ea3b432e4abd4600a2..12306d830c6889c2c9b12699abebe0411262aef6 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -32,6 +32,12 @@ - - - -+ -+ it.unimi.dsi -+ fastutil -+ 8.2.2 -+ provided -+ - - commons-lang - commons-lang diff --git a/Spigot-API-Patches/0003-Paper-Utils.patch b/Spigot-API-Patches/0003-Paper-Utils.patch deleted file mode 100644 index a647b698adaa..000000000000 --- a/Spigot-API-Patches/0003-Paper-Utils.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 Feb 2019 11:26:21 -0500 -Subject: [PATCH] Paper Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9db0056ab94145819628b3ad8d8d26130d117fcf ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java -@@ -0,0 +1,16 @@ -+package com.destroystokyo.paper.util; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public class SneakyThrow { -+ -+ public static void sneaky(@NotNull Throwable exception) { -+ SneakyThrow.throwSneaky(exception); -+ } -+ -+ @SuppressWarnings("unchecked") -+ private static void throwSneaky(@NotNull Throwable exception) throws T { -+ throw (T) exception; -+ } -+ -+} diff --git a/Spigot-API-Patches/0004-Timings-v2.patch b/Spigot-API-Patches/0004-Timings-v2.patch deleted file mode 100644 index 31dd6901957c..000000000000 --- a/Spigot-API-Patches/0004-Timings-v2.patch +++ /dev/null @@ -1,3759 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 18:48:17 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dfaa266ff53e43ad48dc5a5a5657fe70600f539a ---- /dev/null -+++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java -@@ -0,0 +1,85 @@ -+package co.aikar.timings; -+ -+import static co.aikar.timings.TimingsManager.*; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+public class FullServerTickHandler extends TimingHandler { -+ private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null); -+ final TimingData minuteData; -+ double avgFreeMemory = -1D; -+ double avgUsedMemory = -1D; -+ FullServerTickHandler() { -+ super(IDENTITY); -+ minuteData = new TimingData(id); -+ -+ TIMING_MAP.put(IDENTITY, this); -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ if (TimingsManager.needsFullReset) { -+ TimingsManager.resetTimings(); -+ } else if (TimingsManager.needsRecheckEnabled) { -+ TimingsManager.recheckEnabled(); -+ } -+ return super.startTiming(); -+ } -+ -+ @Override -+ public void stopTiming() { -+ super.stopTiming(); -+ if (!isEnabled() || Bukkit.isStopping()) { -+ return; -+ } -+ if (TimingHistory.timedTicks % 20 == 0) { -+ final Runtime runtime = Runtime.getRuntime(); -+ double usedMemory = runtime.totalMemory() - runtime.freeMemory(); -+ double freeMemory = runtime.maxMemory() - usedMemory; -+ if (this.avgFreeMemory == -1) { -+ this.avgFreeMemory = freeMemory; -+ } else { -+ this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D)); -+ } -+ -+ if (this.avgUsedMemory == -1) { -+ this.avgUsedMemory = usedMemory; -+ } else { -+ this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D)); -+ } -+ } -+ -+ long start = System.nanoTime(); -+ TimingsManager.tick(); -+ long diff = System.nanoTime() - start; -+ TIMINGS_TICK.addDiff(diff, null); -+ // addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick. -+ record.setCurTickCount(record.getCurTickCount()-1); -+ -+ minuteData.setCurTickTotal(record.getCurTickTotal()); -+ minuteData.setCurTickCount(1); -+ -+ boolean violated = isViolated(); -+ minuteData.processTick(violated); -+ TIMINGS_TICK.processTick(violated); -+ processTick(violated); -+ -+ -+ if (TimingHistory.timedTicks % 1200 == 0) { -+ MINUTE_REPORTS.add(new TimingHistory.MinuteReport()); -+ TimingHistory.resetTicks(false); -+ minuteData.reset(); -+ } -+ if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) { -+ TimingsManager.HISTORY.add(new TimingHistory()); -+ TimingsManager.resetTimings(); -+ } -+ Bukkit.getUnsafe().reportTimings(); -+ } -+ -+ boolean isViolated() { -+ return record.getCurTickTotal() > 50000000; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/NullTimingHandler.java b/src/main/java/co/aikar/timings/NullTimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9b45ce887b9172f30302b83fe24b99b76b16dac3 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/NullTimingHandler.java -@@ -0,0 +1,68 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public final class NullTimingHandler implements Timing { -+ public static final Timing NULL = new NullTimingHandler(); -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ return this; -+ } -+ -+ @Override -+ public void stopTiming() { -+ -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTimingIfSync() { -+ return this; -+ } -+ -+ @Override -+ public void stopTimingIfSync() { -+ -+ } -+ -+ @Override -+ public void abort() { -+ -+ } -+ -+ @Nullable -+ @Override -+ public TimingHandler getTimingHandler() { -+ return null; -+ } -+ -+ @Override -+ public void close() { -+ -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4e6e1b8e8aeb07e34536941d2cbfc25e5cfa6c27 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java -@@ -0,0 +1,83 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.bukkit.plugin.Plugin; -+ -+import java.lang.reflect.Method; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class TimedEventExecutor implements EventExecutor { -+ -+ private final EventExecutor executor; -+ private final Timing timings; -+ -+ /** -+ * Wraps an event executor and associates a timing handler to it. -+ * -+ * @param executor Executor to wrap -+ * @param plugin Owning plugin -+ * @param method EventHandler method -+ * @param eventClass Owning class -+ */ -+ public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class eventClass) { -+ this.executor = executor; -+ String id; -+ -+ if (method == null) { -+ if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you -+ method = executor.getClass().getEnclosingMethod(); -+ } -+ } -+ -+ if (method != null) { -+ id = method.getDeclaringClass().getName(); -+ } else { -+ id = executor.getClass().getName(); -+ } -+ -+ -+ final String eventName = eventClass.getSimpleName(); -+ boolean verbose = "BlockPhysicsEvent".equals(eventName); -+ this.timings = Timings.ofSafe(plugin, (verbose ? "## " : "") + -+ "Event: " + id + " (" + eventName + ")"); -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) { -+ executor.execute(listener, event); -+ return; -+ } -+ try (Timing ignored = timings.startTiming()){ -+ executor.execute(listener, event); -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a21e5ead5024fd0058c5e3302d8201dd249d32bc ---- /dev/null -+++ b/src/main/java/co/aikar/timings/Timing.java -@@ -0,0 +1,83 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Provides an ability to time sections of code within the Minecraft Server -+ */ -+public interface Timing extends AutoCloseable { -+ /** -+ * Starts timing the execution until {@link #stopTiming()} is called. -+ * -+ * @return Timing -+ */ -+ @NotNull -+ Timing startTiming(); -+ -+ /** -+ *

Stops timing and records the data. Propagates the data up to group handlers.

-+ * -+ * Will automatically be called when this Timing is used with try-with-resources -+ */ -+ void stopTiming(); -+ -+ /** -+ * Starts timing the execution until {@link #stopTiming()} is called. -+ * -+ * But only if we are on the primary thread. -+ * -+ * @return Timing -+ */ -+ @NotNull -+ Timing startTimingIfSync(); -+ -+ /** -+ *

Stops timing and records the data. Propagates the data up to group handlers.

-+ * -+ *

Will automatically be called when this Timing is used with try-with-resources

-+ * -+ * But only if we are on the primary thread. -+ */ -+ void stopTimingIfSync(); -+ -+ /** -+ * @deprecated Doesn't do anything - Removed -+ */ -+ @Deprecated -+ void abort(); -+ -+ /** -+ * Used internally to get the actual backing Handler in the case of delegated Handlers -+ * -+ * @return TimingHandler -+ */ -+ @Nullable -+ TimingHandler getTimingHandler(); -+ -+ @Override -+ void close(); -+} -diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a5d13a1e44edb861f45c83a9b4309fbf799d407d ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingData.java -@@ -0,0 +1,122 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+ -+import static co.aikar.util.JSONUtil.toArray; -+ -+/** -+ *

Lightweight object for tracking timing data

-+ * -+ * This is broken out to reduce memory usage -+ */ -+class TimingData { -+ private final int id; -+ private int count = 0; -+ private int lagCount = 0; -+ private long totalTime = 0; -+ private long lagTotalTime = 0; -+ private int curTickCount = 0; -+ private long curTickTotal = 0; -+ -+ TimingData(int id) { -+ this.id = id; -+ } -+ -+ private TimingData(TimingData data) { -+ this.id = data.id; -+ this.totalTime = data.totalTime; -+ this.lagTotalTime = data.lagTotalTime; -+ this.count = data.count; -+ this.lagCount = data.lagCount; -+ } -+ -+ void add(long diff) { -+ ++curTickCount; -+ curTickTotal += diff; -+ } -+ -+ void processTick(boolean violated) { -+ totalTime += curTickTotal; -+ count += curTickCount; -+ if (violated) { -+ lagTotalTime += curTickTotal; -+ lagCount += curTickCount; -+ } -+ curTickTotal = 0; -+ curTickCount = 0; -+ } -+ -+ void reset() { -+ count = 0; -+ lagCount = 0; -+ curTickTotal = 0; -+ curTickCount = 0; -+ totalTime = 0; -+ lagTotalTime = 0; -+ } -+ -+ protected TimingData clone() { -+ return new TimingData(this); -+ } -+ -+ @NotNull -+ List export() { -+ List list = toArray( -+ id, -+ count, -+ totalTime); -+ if (lagCount > 0) { -+ list.add(lagCount); -+ list.add(lagTotalTime); -+ } -+ return list; -+ } -+ -+ boolean hasData() { -+ return count > 0; -+ } -+ -+ long getTotalTime() { -+ return totalTime; -+ } -+ -+ int getCurTickCount() { -+ return curTickCount; -+ } -+ -+ void setCurTickCount(int curTickCount) { -+ this.curTickCount = curTickCount; -+ } -+ -+ long getCurTickTotal() { -+ return curTickTotal; -+ } -+ -+ void setCurTickTotal(long curTickTotal) { -+ this.curTickTotal = curTickTotal; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..199789d56d22fcb1b77ebd56805cc28aa5a5ab0a ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHandler.java -@@ -0,0 +1,226 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingIntMap; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -+ -+import java.util.ArrayDeque; -+import java.util.Deque; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+class TimingHandler implements Timing { -+ -+ private static AtomicInteger idPool = new AtomicInteger(1); -+ private static Deque TIMING_STACK = new ArrayDeque<>(); -+ final int id = idPool.getAndIncrement(); -+ -+ final TimingIdentifier identifier; -+ private final boolean verbose; -+ -+ private final Int2ObjectOpenHashMap children = new LoadingIntMap<>(TimingData::new); -+ -+ final TimingData record; -+ private TimingHandler startParent; -+ private final TimingHandler groupHandler; -+ -+ private long start = 0; -+ private int timingDepth = 0; -+ private boolean added; -+ private boolean timed; -+ private boolean enabled; -+ -+ TimingHandler(@NotNull TimingIdentifier id) { -+ this.identifier = id; -+ this.verbose = id.name.startsWith("##"); -+ this.record = new TimingData(this.id); -+ this.groupHandler = id.groupHandler; -+ -+ TimingIdentifier.getGroup(id.group).handlers.add(this); -+ checkEnabled(); -+ } -+ -+ final void checkEnabled() { -+ enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled); -+ } -+ -+ void processTick(boolean violated) { -+ if (timingDepth != 0 || record.getCurTickCount() == 0) { -+ timingDepth = 0; -+ start = 0; -+ return; -+ } -+ -+ record.processTick(violated); -+ for (TimingData handler : children.values()) { -+ handler.processTick(violated); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTimingIfSync() { -+ startTiming(); -+ return this; -+ } -+ -+ @Override -+ public void stopTimingIfSync() { -+ stopTiming(); -+ } -+ -+ @NotNull -+ public Timing startTiming() { -+ if (!enabled || !Bukkit.isPrimaryThread()) { -+ return this; -+ } -+ if (++timingDepth == 1) { -+ startParent = TIMING_STACK.peekLast(); -+ start = System.nanoTime(); -+ } -+ TIMING_STACK.addLast(this); -+ return this; -+ } -+ -+ public void stopTiming() { -+ if (!enabled || timingDepth <= 0 || start == 0 || !Bukkit.isPrimaryThread()) { -+ return; -+ } -+ -+ popTimingStack(); -+ if (--timingDepth == 0) { -+ addDiff(System.nanoTime() - start, startParent); -+ startParent = null; -+ start = 0; -+ } -+ } -+ -+ private void popTimingStack() { -+ TimingHandler last; -+ while ((last = TIMING_STACK.removeLast()) != this) { -+ last.timingDepth = 0; -+ if ("Minecraft".equalsIgnoreCase(last.identifier.group)) { -+ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Look above this for any errors and report this to Paper unless it has a plugin in the stack trace (" + last.identifier + " did not stopTiming)"); -+ } else { -+ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + last.identifier + " did not stopTiming)", new Throwable()); -+ } -+ -+ boolean found = TIMING_STACK.contains(this); -+ if (!found) { -+ // We aren't even in the stack... Don't pop everything -+ TIMING_STACK.addLast(last); -+ break; -+ } -+ } -+ } -+ -+ @Override -+ public final void abort() { -+ -+ } -+ -+ void addDiff(long diff, @Nullable TimingHandler parent) { -+ if (parent != null) { -+ parent.children.get(id).add(diff); -+ } -+ -+ record.add(diff); -+ if (!added) { -+ added = true; -+ timed = true; -+ TimingsManager.HANDLERS.add(this); -+ } -+ if (groupHandler != null) { -+ groupHandler.addDiff(diff, parent); -+ groupHandler.children.get(id).add(diff); -+ } -+ } -+ -+ /** -+ * Reset this timer, setting all values to zero. -+ */ -+ void reset(boolean full) { -+ record.reset(); -+ if (full) { -+ timed = false; -+ } -+ start = 0; -+ timingDepth = 0; -+ added = false; -+ children.clear(); -+ checkEnabled(); -+ } -+ -+ @NotNull -+ @Override -+ public TimingHandler getTimingHandler() { -+ return this; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ return (this == o); -+ } -+ -+ @Override -+ public int hashCode() { -+ return id; -+ } -+ -+ /** -+ * This is simply for the Closeable interface so it can be used with try-with-resources () -+ */ -+ @Override -+ public void close() { -+ stopTimingIfSync(); -+ } -+ -+ public boolean isSpecial() { -+ return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK; -+ } -+ -+ boolean isTimed() { -+ return timed; -+ } -+ -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @NotNull -+ TimingData[] cloneChildren() { -+ final TimingData[] clonedChildren = new TimingData[children.size()]; -+ int i = 0; -+ for (TimingData child : children.values()) { -+ clonedChildren[i++] = child.clone(); -+ } -+ return clonedChildren; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ddaed81275fcc12d1671b668697acf318e96888b ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHistory.java -@@ -0,0 +1,354 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.timings.TimingHistory.RegionData.RegionId; -+import com.google.common.base.Function; -+import com.google.common.collect.Sets; -+import org.bukkit.Bukkit; -+import org.bukkit.Chunk; -+import org.bukkit.Material; -+import org.bukkit.World; -+import org.bukkit.block.BlockState; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.EntityType; -+import org.bukkit.entity.Player; -+import co.aikar.util.LoadingMap; -+import co.aikar.util.MRUMapCache; -+ -+import java.lang.management.ManagementFactory; -+import java.util.Collection; -+import java.util.EnumMap; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK; -+import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; -+import static co.aikar.util.JSONUtil.*; -+ -+@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"}) -+public class TimingHistory { -+ public static long lastMinuteTime; -+ public static long timedTicks; -+ public static long playerTicks; -+ public static long entityTicks; -+ public static long tileEntityTicks; -+ public static long activatedEntityTicks; -+ private static int worldIdPool = 1; -+ static Map worldMap = LoadingMap.newHashMap(new Function() { -+ @NotNull -+ @Override -+ public Integer apply(@Nullable String input) { -+ return worldIdPool++; -+ } -+ }); -+ private final long endTime; -+ private final long startTime; -+ private final long totalTicks; -+ private final long totalTime; // Represents all time spent running the server this history -+ private final MinuteReport[] minuteReports; -+ -+ private final TimingHistoryEntry[] entries; -+ final Set tileEntityTypeSet = Sets.newHashSet(); -+ final Set entityTypeSet = Sets.newHashSet(); -+ private final Map worlds; -+ -+ TimingHistory() { -+ this.endTime = System.currentTimeMillis() / 1000; -+ this.startTime = TimingsManager.historyStart / 1000; -+ if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { -+ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); -+ this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); -+ } else { -+ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]); -+ } -+ long ticks = 0; -+ for (MinuteReport mp : this.minuteReports) { -+ ticks += mp.ticksRecord.timed; -+ } -+ this.totalTicks = ticks; -+ this.totalTime = FULL_SERVER_TICK.record.getTotalTime(); -+ this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()]; -+ -+ int i = 0; -+ for (TimingHandler handler : TimingsManager.HANDLERS) { -+ entries[i++] = new TimingHistoryEntry(handler); -+ } -+ -+ // Information about all loaded chunks/entities -+ //noinspection unchecked -+ this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function() { -+ @NotNull -+ @Override -+ public JSONPair apply(World world) { -+ Map regions = LoadingMap.newHashMap(RegionData.LOADER); -+ -+ for (Chunk chunk : world.getLoadedChunks()) { -+ RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ())); -+ -+ for (Entity entity : chunk.getEntities()) { -+ if (entity == null) { -+ Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); -+ continue; -+ } -+ -+ data.entityCounts.get(entity.getType()).increment(); -+ } -+ -+ for (BlockState tileEntity : chunk.getTileEntities()) { -+ if (tileEntity == null) { -+ Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); -+ continue; -+ } -+ -+ data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); -+ } -+ } -+ return pair( -+ worldMap.get(world.getName()), -+ toArrayMapper(regions.values(),new Function() { -+ @NotNull -+ @Override -+ public Object apply(RegionData input) { -+ return toArray( -+ input.regionId.x, -+ input.regionId.z, -+ toObjectMapper(input.entityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @NotNull -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ entityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().ordinal()), -+ entry.getValue().count() -+ ); -+ } -+ } -+ ), -+ toObjectMapper(input.tileEntityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @NotNull -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ tileEntityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().ordinal()), -+ entry.getValue().count() -+ ); -+ } -+ } -+ ) -+ ); -+ } -+ }) -+ ); -+ } -+ }); -+ } -+ static class RegionData { -+ final RegionId regionId; -+ @SuppressWarnings("Guava") -+ static Function LOADER = new Function() { -+ @NotNull -+ @Override -+ public RegionData apply(@NotNull RegionId id) { -+ return new RegionData(id); -+ } -+ }; -+ RegionData(@NotNull RegionId id) { -+ this.regionId = id; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ -+ RegionData that = (RegionData) o; -+ -+ return regionId.equals(that.regionId); -+ -+ } -+ -+ @Override -+ public int hashCode() { -+ return regionId.hashCode(); -+ } -+ -+ @SuppressWarnings("unchecked") -+ final Map entityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(EntityType.class), k -> new Counter() -+ )); -+ @SuppressWarnings("unchecked") -+ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(Material.class), k -> new Counter() -+ )); -+ -+ static class RegionId { -+ final int x, z; -+ final long regionId; -+ RegionId(int x, int z) { -+ this.x = x >> 5 << 5; -+ this.z = z >> 5 << 5; -+ this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ -+ RegionId regionId1 = (RegionId) o; -+ -+ return regionId == regionId1.regionId; -+ -+ } -+ -+ @Override -+ public int hashCode() { -+ return (int) (regionId ^ (regionId >>> 32)); -+ } -+ } -+ } -+ static void resetTicks(boolean fullReset) { -+ if (fullReset) { -+ // Non full is simply for 1 minute reports -+ timedTicks = 0; -+ } -+ lastMinuteTime = System.nanoTime(); -+ playerTicks = 0; -+ tileEntityTicks = 0; -+ entityTicks = 0; -+ activatedEntityTicks = 0; -+ } -+ -+ @NotNull -+ Object export() { -+ return createObject( -+ pair("s", startTime), -+ pair("e", endTime), -+ pair("tk", totalTicks), -+ pair("tm", totalTime), -+ pair("w", worlds), -+ pair("h", toArrayMapper(entries, new Function() { -+ @Nullable -+ @Override -+ public Object apply(TimingHistoryEntry entry) { -+ TimingData record = entry.data; -+ if (!record.hasData()) { -+ return null; -+ } -+ return entry.export(); -+ } -+ })), -+ pair("mp", toArrayMapper(minuteReports, new Function() { -+ @NotNull -+ @Override -+ public Object apply(MinuteReport input) { -+ return input.export(); -+ } -+ })) -+ ); -+ } -+ -+ static class MinuteReport { -+ final long time = System.currentTimeMillis() / 1000; -+ -+ final TicksRecord ticksRecord = new TicksRecord(); -+ final PingRecord pingRecord = new PingRecord(); -+ final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone(); -+ final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed; -+ final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory; -+ final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory; -+ final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); -+ -+ @NotNull -+ List export() { -+ return toArray( -+ time, -+ Math.round(tps * 100D) / 100D, -+ Math.round(pingRecord.avg * 100D) / 100D, -+ fst.export(), -+ toArray(ticksRecord.timed, -+ ticksRecord.player, -+ ticksRecord.entity, -+ ticksRecord.activatedEntity, -+ ticksRecord.tileEntity -+ ), -+ usedMemory, -+ freeMemory, -+ loadAvg -+ ); -+ } -+ } -+ -+ private static class TicksRecord { -+ final long timed; -+ final long player; -+ final long entity; -+ final long tileEntity; -+ final long activatedEntity; -+ -+ TicksRecord() { -+ timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200); -+ player = playerTicks; -+ entity = entityTicks; -+ tileEntity = tileEntityTicks; -+ activatedEntity = activatedEntityTicks; -+ } -+ -+ } -+ -+ private static class PingRecord { -+ final double avg; -+ -+ PingRecord() { -+ final Collection onlinePlayers = Bukkit.getOnlinePlayers(); -+ int totalPing = 0; -+ for (Player player : onlinePlayers) { -+ totalPing += player.spigot().getPing(); -+ } -+ avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size(); -+ } -+ } -+ -+ -+ private static class Counter { -+ private int count = 0; -+ public int increment() { -+ return ++count; -+ } -+ public int count() { -+ return count; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingHistoryEntry.java b/src/main/java/co/aikar/timings/TimingHistoryEntry.java -new file mode 100644 -index 0000000000000000000000000000000000000000..86d5ac6bd0d7d0003688761aceb3f3343575319f ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java -@@ -0,0 +1,58 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.base.Function; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+ -+import static co.aikar.util.JSONUtil.toArrayMapper; -+ -+class TimingHistoryEntry { -+ final TimingData data; -+ private final TimingData[] children; -+ -+ TimingHistoryEntry(@NotNull TimingHandler handler) { -+ this.data = handler.record.clone(); -+ children = handler.cloneChildren(); -+ } -+ -+ @NotNull -+ List export() { -+ List result = data.export(); -+ if (children.length > 0) { -+ result.add( -+ toArrayMapper(children, new Function() { -+ @NotNull -+ @Override -+ public Object apply(TimingData child) { -+ return child.export(); -+ } -+ }) -+ ); -+ } -+ return result; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java -new file mode 100644 -index 0000000000000000000000000000000000000000..df142a89b8c43acb81eb383eac0ef048a1f49a6e ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingIdentifier.java -@@ -0,0 +1,116 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingMap; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.Map; -+import java.util.Objects; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicInteger; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ *

Used as a basis for fast HashMap key comparisons for the Timing Map.

-+ * -+ * This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings -+ */ -+final class TimingIdentifier { -+ /** -+ * Holds all groups. Autoloads on request for a group by name. -+ */ -+ static final Map GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new); -+ private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft"); -+ final String group; -+ final String name; -+ final TimingHandler groupHandler; -+ private final int hashCode; -+ -+ TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) { -+ this.group = group != null ? group: DEFAULT_GROUP.name; -+ this.name = name; -+ this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null; -+ this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode(); -+ } -+ -+ @NotNull -+ static TimingGroup getGroup(@Nullable String groupName) { -+ if (groupName == null) { -+ //noinspection ConstantConditions -+ return DEFAULT_GROUP; -+ } -+ -+ return GROUP_MAP.get(groupName); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (o == null) { -+ return false; -+ } -+ -+ TimingIdentifier that = (TimingIdentifier) o; -+ return Objects.equals(group, that.group) && Objects.equals(name, that.name); -+ } -+ -+ @Override -+ public int hashCode() { -+ return hashCode; -+ } -+ -+ @Override -+ public String toString() { -+ return "TimingIdentifier{id=" + group + ":" + name +'}'; -+ } -+ -+ static class TimingGroup { -+ -+ private static AtomicInteger idPool = new AtomicInteger(1); -+ final int id = idPool.getAndIncrement(); -+ -+ final String name; -+ final List handlers = Collections.synchronizedList(new ArrayList<>(64)); -+ -+ private TimingGroup(String name) { -+ this.name = name; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ TimingGroup that = (TimingGroup) o; -+ return id == that.id; -+ } -+ -+ @Override -+ public int hashCode() { -+ return id; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..da76e1aaee1dee794e38ddd4e0a28e0071e90bbf ---- /dev/null -+++ b/src/main/java/co/aikar/timings/Timings.java -@@ -0,0 +1,296 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.base.Preconditions; -+import com.google.common.collect.EvictingQueue; -+import com.google.common.collect.Lists; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.List; -+import java.util.Queue; -+import java.util.logging.Level; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"}) -+public final class Timings { -+ -+ final static List requestingReport = Lists.newArrayList(); -+ private static final int MAX_HISTORY_FRAMES = 12; -+ public static final Timing NULL_HANDLER = new NullTimingHandler(); -+ static boolean timingsEnabled = false; -+ static boolean verboseEnabled = false; -+ private static int historyInterval = -1; -+ private static int historyLength = -1; -+ -+ private Timings() {} -+ -+ /** -+ * Returns a Timing for a plugin corresponding to a name. -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @return Handler -+ */ -+ @NotNull -+ public static Timing of(@NotNull Plugin plugin, @NotNull String name) { -+ Timing pluginHandler = null; -+ if (plugin != null) { -+ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); -+ } -+ return of(plugin, name, pluginHandler); -+ } -+ -+ /** -+ *

Returns a handler that has a groupHandler timer handler. Parent timers should not have their -+ * start/stop methods called directly, as the children will call it for you.

-+ * -+ * Parent Timers are used to group multiple subsections together and get a summary of them combined -+ * Parent Handler can not be changed after first call -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @param groupHandler Parent handler to mirror .start/stop calls to -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { -+ Preconditions.checkNotNull(plugin, "Plugin can not be null"); -+ return TimingsManager.getHandler(plugin.getName(), name, groupHandler); -+ } -+ -+ /** -+ * Returns a Timing object after starting it, useful for Java7 try-with-resources. -+ * -+ * try (Timing ignored = Timings.ofStart(plugin, someName)) { -+ * // timed section -+ * } -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) { -+ return ofStart(plugin, name, null); -+ } -+ -+ /** -+ * Returns a Timing object after starting it, useful for Java7 try-with-resources. -+ * -+ * try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) { -+ * // timed section -+ * } -+ * -+ * @param plugin Plugin to own the Timing -+ * @param name Name of Timing -+ * @param groupHandler Parent handler to mirror .start/stop calls to -+ * @return Timing Handler -+ */ -+ @NotNull -+ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { -+ Timing timing = of(plugin, name, groupHandler); -+ timing.startTiming(); -+ return timing; -+ } -+ -+ /** -+ * Gets whether or not the Spigot Timings system is enabled -+ * -+ * @return Enabled or not -+ */ -+ public static boolean isTimingsEnabled() { -+ return timingsEnabled; -+ } -+ -+ /** -+ *

Sets whether or not the Spigot Timings system should be enabled

-+ * -+ * Calling this will reset timing data. -+ * -+ * @param enabled Should timings be reported -+ */ -+ public static void setTimingsEnabled(boolean enabled) { -+ timingsEnabled = enabled; -+ reset(); -+ } -+ -+ /** -+ *

Sets whether or not the Timings should monitor at Verbose level.

-+ * -+ *

When Verbose is disabled, high-frequency timings will not be available.

-+ * -+ * @return Enabled or not -+ */ -+ public static boolean isVerboseTimingsEnabled() { -+ return verboseEnabled; -+ } -+ -+ /** -+ *

Sets whether or not the Timings should monitor at Verbose level.

-+ * -+ * When Verbose is disabled, high-frequency timings will not be available. -+ * Calling this will reset timing data. -+ * -+ * @param enabled Should high-frequency timings be reported -+ */ -+ public static void setVerboseTimingsEnabled(boolean enabled) { -+ verboseEnabled = enabled; -+ TimingsManager.needsRecheckEnabled = true; -+ } -+ -+ /** -+ *

Gets the interval between Timing History report generation.

-+ * -+ * Defaults to 5 minutes (6000 ticks) -+ * -+ * @return Interval in ticks -+ */ -+ public static int getHistoryInterval() { -+ return historyInterval; -+ } -+ -+ /** -+ *

Sets the interval between Timing History report generations.

-+ * -+ *

Defaults to 5 minutes (6000 ticks)

-+ * -+ * This will recheck your history length, so lowering this value will lower your -+ * history length if you need more than 60 history windows. -+ * -+ * @param interval Interval in ticks -+ */ -+ public static void setHistoryInterval(int interval) { -+ historyInterval = Math.max(20*60, interval); -+ // Recheck the history length with the new Interval -+ if (historyLength != -1) { -+ setHistoryLength(historyLength); -+ } -+ } -+ -+ /** -+ * Gets how long in ticks Timings history is kept for the server. -+ * -+ * Defaults to 1 hour (72000 ticks) -+ * -+ * @return Duration in Ticks -+ */ -+ public static int getHistoryLength() { -+ return historyLength; -+ } -+ -+ /** -+ * Sets how long Timing History reports are kept for the server. -+ * -+ * Defaults to 1 hours(72000 ticks) -+ * -+ * This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12) -+ * -+ * Will not reset Timing Data but may truncate old history if the new length is less than old length. -+ * -+ * @param length Duration in ticks -+ */ -+ public static void setHistoryLength(int length) { -+ // Cap at 12 History Frames, 1 hour at 5 minute frames. -+ int maxLength = historyInterval * MAX_HISTORY_FRAMES; -+ // For special cases of servers with special permission to bypass the max. -+ // This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side. -+ // Setting this will not help you bypass the max unless Aikar has added an exception on the API side. -+ if (System.getProperty("timings.bypassMax") != null) { -+ maxLength = Integer.MAX_VALUE; -+ } -+ historyLength = Math.max(Math.min(maxLength, length), historyInterval); -+ Queue oldQueue = TimingsManager.HISTORY; -+ int frames = (getHistoryLength() / getHistoryInterval()); -+ if (length > maxLength) { -+ Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length."); -+ } -+ TimingsManager.HISTORY = EvictingQueue.create(frames); -+ TimingsManager.HISTORY.addAll(oldQueue); -+ } -+ -+ /** -+ * Resets all Timing Data -+ */ -+ public static void reset() { -+ TimingsManager.reset(); -+ } -+ -+ /** -+ * Generates a report and sends it to the specified command sender. -+ * -+ * If sender is null, ConsoleCommandSender will be used. -+ * @param sender The sender to send to, or null to use the ConsoleCommandSender -+ */ -+ public static void generateReport(@Nullable CommandSender sender) { -+ if (sender == null) { -+ sender = Bukkit.getConsoleSender(); -+ } -+ requestingReport.add(sender); -+ } -+ -+ /** -+ * Generates a report and sends it to the specified listener. -+ * Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done! -+ * @param sender The listener to send responses too. -+ */ -+ public static void generateReport(@NotNull TimingsReportListener sender) { -+ Validate.notNull(sender); -+ requestingReport.add(sender); -+ } -+ -+ /* -+ ================= -+ Protected API: These are for internal use only in Bukkit/CraftBukkit -+ These do not have isPrimaryThread() checks in the startTiming/stopTiming -+ ================= -+ */ -+ @NotNull -+ static TimingHandler ofSafe(@NotNull String name) { -+ return ofSafe(null, name, null); -+ } -+ -+ @NotNull -+ static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) { -+ Timing pluginHandler = null; -+ if (plugin != null) { -+ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); -+ } -+ return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler); -+ } -+ -+ @NotNull -+ static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) { -+ return ofSafe(null, name, groupHandler); -+ } -+ -+ @NotNull -+ static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) { -+ return TimingsManager.getHandler(groupName, name, groupHandler); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7c2245a310a084367ff25db539b3c967d5cb141 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsCommand.java -@@ -0,0 +1,119 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.ImmutableList; -+import org.apache.commons.lang.Validate; -+import org.bukkit.ChatColor; -+import org.bukkit.command.CommandSender; -+import org.bukkit.command.defaults.BukkitCommand; -+import org.bukkit.util.StringUtil; -+ -+import java.util.ArrayList; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+ -+public class TimingsCommand extends BukkitCommand { -+ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff"); -+ private long lastResetAttempt = 0; -+ -+ public TimingsCommand(@NotNull String name) { -+ super(name); -+ this.description = "Manages Spigot Timings data to see performance of the server."; -+ this.usageMessage = "/timings "; -+ this.setPermission("bukkit.command.timings"); -+ } -+ -+ @Override -+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -+ if (!testPermission(sender)) { -+ return true; -+ } -+ if (args.length < 1) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return true; -+ } -+ final String arg = args[0]; -+ if ("on".equalsIgnoreCase(arg)) { -+ Timings.setTimingsEnabled(true); -+ sender.sendMessage("Enabled Timings & Reset"); -+ return true; -+ } else if ("off".equalsIgnoreCase(arg)) { -+ Timings.setTimingsEnabled(false); -+ sender.sendMessage("Disabled Timings"); -+ return true; -+ } -+ -+ if (!Timings.isTimingsEnabled()) { -+ sender.sendMessage("Please enable timings by typing /timings on"); -+ return true; -+ } -+ -+ long now = System.currentTimeMillis(); -+ if ("verbon".equalsIgnoreCase(arg)) { -+ Timings.setVerboseTimingsEnabled(true); -+ sender.sendMessage("Enabled Verbose Timings"); -+ return true; -+ } else if ("verboff".equalsIgnoreCase(arg)) { -+ Timings.setVerboseTimingsEnabled(false); -+ sender.sendMessage("Disabled Verbose Timings"); -+ return true; -+ } else if ("reset".equalsIgnoreCase(arg)) { -+ if (now - lastResetAttempt < 30000) { -+ TimingsManager.reset(); -+ sender.sendMessage(ChatColor.RED + "Timings reset. Please wait 5-10 minutes before using /timings report."); -+ } else { -+ lastResetAttempt = now; -+ sender.sendMessage(ChatColor.RED + "WARNING: Timings v2 should not be reset. If you are encountering lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds."); -+ } -+ } else if ( -+ "paste".equalsIgnoreCase(arg) || -+ "report".equalsIgnoreCase(arg) || -+ "get".equalsIgnoreCase(arg) || -+ "merged".equalsIgnoreCase(arg) || -+ "separate".equalsIgnoreCase(arg) -+ ) { -+ Timings.generateReport(sender); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ } -+ return true; -+ } -+ -+ @NotNull -+ @Override -+ public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { -+ Validate.notNull(sender, "Sender cannot be null"); -+ Validate.notNull(args, "Arguments cannot be null"); -+ Validate.notNull(alias, "Alias cannot be null"); -+ -+ if (args.length == 1) { -+ return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, -+ new ArrayList(TIMINGS_SUBCOMMANDS.size())); -+ } -+ return ImmutableList.of(); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ef824d701c97cad8b31e76ad98c94fc4367a7eda ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsManager.java -@@ -0,0 +1,188 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import co.aikar.util.LoadingMap; -+import com.google.common.collect.EvictingQueue; -+import org.bukkit.Bukkit; -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.plugin.java.PluginClassLoader; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.logging.Level; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public final class TimingsManager { -+ static final Map TIMING_MAP = LoadingMap.of( -+ new ConcurrentHashMap<>(4096, .5F), TimingHandler::new -+ ); -+ public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler(); -+ public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK); -+ public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins"); -+ public static List hiddenConfigs = new ArrayList(); -+ public static boolean privacy = false; -+ -+ static final List HANDLERS = new ArrayList<>(1024); -+ static final List MINUTE_REPORTS = new ArrayList<>(64); -+ -+ static EvictingQueue HISTORY = EvictingQueue.create(12); -+ static long timingStart = 0; -+ static long historyStart = 0; -+ static boolean needsFullReset = false; -+ static boolean needsRecheckEnabled = false; -+ -+ private TimingsManager() {} -+ -+ /** -+ * Resets all timing data on the next tick -+ */ -+ static void reset() { -+ needsFullReset = true; -+ } -+ -+ /** -+ * Ticked every tick by CraftBukkit to count the number of times a timer -+ * caused TPS loss. -+ */ -+ static void tick() { -+ if (Timings.timingsEnabled) { -+ boolean violated = FULL_SERVER_TICK.isViolated(); -+ -+ for (TimingHandler handler : HANDLERS) { -+ if (handler.isSpecial()) { -+ // We manually call this -+ continue; -+ } -+ handler.processTick(violated); -+ } -+ -+ TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size(); -+ TimingHistory.timedTicks++; -+ // Generate TPS/Ping/Tick reports every minute -+ } -+ } -+ static void stopServer() { -+ Timings.timingsEnabled = false; -+ recheckEnabled(); -+ } -+ static void recheckEnabled() { -+ synchronized (TIMING_MAP) { -+ for (TimingHandler timings : TIMING_MAP.values()) { -+ timings.checkEnabled(); -+ } -+ } -+ needsRecheckEnabled = false; -+ } -+ static void resetTimings() { -+ if (needsFullReset) { -+ // Full resets need to re-check every handlers enabled state -+ // Timing map can be modified from async so we must sync on it. -+ synchronized (TIMING_MAP) { -+ for (TimingHandler timings : TIMING_MAP.values()) { -+ timings.reset(true); -+ } -+ } -+ Bukkit.getLogger().log(Level.INFO, "Timings Reset"); -+ HISTORY.clear(); -+ needsFullReset = false; -+ needsRecheckEnabled = false; -+ timingStart = System.currentTimeMillis(); -+ } else { -+ // Soft resets only need to act on timings that have done something -+ // Handlers can only be modified on main thread. -+ for (TimingHandler timings : HANDLERS) { -+ timings.reset(false); -+ } -+ } -+ -+ HANDLERS.clear(); -+ MINUTE_REPORTS.clear(); -+ -+ TimingHistory.resetTicks(true); -+ historyStart = System.currentTimeMillis(); -+ } -+ -+ @NotNull -+ static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) { -+ return TIMING_MAP.get(new TimingIdentifier(group, name, parent)); -+ } -+ -+ -+ /** -+ *

Due to access restrictions, we need a helper method to get a Command TimingHandler with String group

-+ * -+ * Plugins should never call this -+ * -+ * @param pluginName Plugin this command is associated with -+ * @param command Command to get timings for -+ * @return TimingHandler -+ */ -+ @NotNull -+ public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) { -+ Plugin plugin = null; -+ final Server server = Bukkit.getServer(); -+ if (!( server == null || pluginName == null || -+ "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || -+ "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) -+ )) { -+ plugin = server.getPluginManager().getPlugin(pluginName); -+ } -+ if (plugin == null) { -+ // Plugin is passing custom fallback prefix, try to look up by class loader -+ plugin = getPluginByClassloader(command.getClass()); -+ } -+ if (plugin == null) { -+ return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName()); -+ } -+ -+ return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName()); -+ } -+ -+ /** -+ * Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the -+ * Plugin that created this class. -+ * -+ * @param clazz Class to check -+ * @return Plugin if created by a plugin -+ */ -+ @Nullable -+ public static Plugin getPluginByClassloader(@Nullable Class clazz) { -+ if (clazz == null) { -+ return null; -+ } -+ final ClassLoader classLoader = clazz.getClassLoader(); -+ if (classLoader instanceof PluginClassLoader) { -+ PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader; -+ return pluginClassLoader.getPlugin(); -+ } -+ return null; -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ef58a6c00f444bd498a2d8fc4e457236f393954f ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsReportListener.java -@@ -0,0 +1,77 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.Lists; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.command.ConsoleCommandSender; -+import org.bukkit.command.MessageCommandSender; -+import org.bukkit.command.RemoteConsoleCommandSender; -+ -+import java.util.List; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+@SuppressWarnings("WeakerAccess") -+public class TimingsReportListener implements MessageCommandSender { -+ private final List senders; -+ private final Runnable onDone; -+ private String timingsURL; -+ -+ public TimingsReportListener(@NotNull CommandSender senders) { -+ this(senders, null); -+ } -+ public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) { -+ this(Lists.newArrayList(sender), onDone); -+ } -+ public TimingsReportListener(@NotNull List senders) { -+ this(senders, null); -+ } -+ public TimingsReportListener(@NotNull List senders, @Nullable Runnable onDone) { -+ Validate.notNull(senders); -+ Validate.notEmpty(senders); -+ -+ this.senders = Lists.newArrayList(senders); -+ this.onDone = onDone; -+ } -+ -+ @Nullable -+ public String getTimingsURL() { -+ return timingsURL; -+ } -+ -+ public void done() { -+ done(null); -+ } -+ -+ public void done(@Nullable String url) { -+ this.timingsURL = url; -+ if (onDone != null) { -+ onDone.run(); -+ } -+ for (CommandSender sender : senders) { -+ if (sender instanceof TimingsReportListener) { -+ ((TimingsReportListener) sender).done(); -+ } -+ } -+ } -+ -+ @Override -+ public void sendMessage(@NotNull String message) { -+ senders.forEach((sender) -> sender.sendMessage(message)); -+ } -+ -+ public void addConsoleIfNeeded() { -+ boolean hasConsole = false; -+ for (CommandSender sender : this.senders) { -+ if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) { -+ hasConsole = true; -+ } -+ } -+ if (!hasConsole) { -+ this.senders.add(Bukkit.getConsoleSender()); -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/UnsafeTimingHandler.java b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..632c4961515f5052551f841cfa840e60bba7a257 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java -@@ -0,0 +1,53 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+class UnsafeTimingHandler extends TimingHandler { -+ -+ UnsafeTimingHandler(@NotNull TimingIdentifier id) { -+ super(id); -+ } -+ -+ private static void checkThread() { -+ if (!Bukkit.isPrimaryThread()) { -+ throw new IllegalStateException("Calling Timings from Async Operation"); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public Timing startTiming() { -+ checkThread(); -+ return super.startTiming(); -+ } -+ -+ @Override -+ public void stopTiming() { -+ checkThread(); -+ super.stopTiming(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/Counter.java b/src/main/java/co/aikar/util/Counter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..80155072d1004e34e04342d434cf7d75f0b7e29d ---- /dev/null -+++ b/src/main/java/co/aikar/util/Counter.java -@@ -0,0 +1,38 @@ -+package co.aikar.util; -+ -+import com.google.common.collect.ForwardingMap; -+ -+import java.util.HashMap; -+import java.util.Map; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class Counter extends ForwardingMap { -+ private final Map counts = new HashMap<>(); -+ -+ public long decrement(@Nullable T key) { -+ return increment(key, -1); -+ } -+ public long increment(@Nullable T key) { -+ return increment(key, 1); -+ } -+ public long decrement(@Nullable T key, long amount) { -+ return decrement(key, -amount); -+ } -+ public long increment(@Nullable T key, long amount) { -+ Long count = this.getCount(key); -+ count += amount; -+ this.counts.put(key, count); -+ return count; -+ } -+ -+ public long getCount(@Nullable T key) { -+ return this.counts.getOrDefault(key, 0L); -+ } -+ -+ @NotNull -+ @Override -+ protected Map delegate() { -+ return this.counts; -+ } -+} -diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..190bf0598442c89c2a1c93ad7c8c1a29797304ae ---- /dev/null -+++ b/src/main/java/co/aikar/util/JSONUtil.java -@@ -0,0 +1,140 @@ -+package co.aikar.util; -+ -+import com.google.common.base.Function; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashMap; -+import java.util.List; -+import java.util.Map; -+ -+/** -+ * Provides Utility methods that assist with generating JSON Objects -+ */ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public final class JSONUtil { -+ private JSONUtil() {} -+ -+ /** -+ * Creates a key/value "JSONPair" object -+ * -+ * @param key Key to use -+ * @param obj Value to use -+ * @return JSONPair -+ */ -+ @NotNull -+ public static JSONPair pair(@NotNull String key, @Nullable Object obj) { -+ return new JSONPair(key, obj); -+ } -+ -+ @NotNull -+ public static JSONPair pair(long key, @Nullable Object obj) { -+ return new JSONPair(String.valueOf(key), obj); -+ } -+ -+ /** -+ * Creates a new JSON object from multiple JSONPair key/value pairs -+ * -+ * @param data JSONPairs -+ * @return Map -+ */ -+ @NotNull -+ public static Map createObject(@NotNull JSONPair... data) { -+ return appendObjectData(new LinkedHashMap(), data); -+ } -+ -+ /** -+ * This appends multiple key/value Obj pairs into a JSON Object -+ * -+ * @param parent Map to be appended to -+ * @param data Data to append -+ * @return Map -+ */ -+ @NotNull -+ public static Map appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) { -+ for (JSONPair JSONPair : data) { -+ parent.put(JSONPair.key, JSONPair.val); -+ } -+ return parent; -+ } -+ -+ /** -+ * This builds a JSON array from a set of data -+ * -+ * @param data Data to build JSON array from -+ * @return List -+ */ -+ @NotNull -+ public static List toArray(@NotNull Object... data) { -+ return Lists.newArrayList(data); -+ } -+ -+ /** -+ * These help build a single JSON array using a mapper function -+ * -+ * @param collection Collection to apply to -+ * @param mapper Mapper to apply -+ * @param Element Type -+ * @return List -+ */ -+ @NotNull -+ public static List toArrayMapper(@NotNull E[] collection, @NotNull Function mapper) { -+ return toArrayMapper(Lists.newArrayList(collection), mapper); -+ } -+ -+ @NotNull -+ public static List toArrayMapper(@NotNull Iterable collection, @NotNull Function mapper) { -+ List array = Lists.newArrayList(); -+ for (E e : collection) { -+ Object object = mapper.apply(e); -+ if (object != null) { -+ array.add(object); -+ } -+ } -+ return array; -+ } -+ -+ /** -+ * These help build a single JSON Object from a collection, using a mapper function -+ * -+ * @param collection Collection to apply to -+ * @param mapper Mapper to apply -+ * @param Element Type -+ * @return Map -+ */ -+ @NotNull -+ public static Map toObjectMapper(@NotNull E[] collection, @NotNull Function mapper) { -+ return toObjectMapper(Lists.newArrayList(collection), mapper); -+ } -+ -+ @NotNull -+ public static Map toObjectMapper(@NotNull Iterable collection, @NotNull Function mapper) { -+ Map object = Maps.newLinkedHashMap(); -+ for (E e : collection) { -+ JSONPair JSONPair = mapper.apply(e); -+ if (JSONPair != null) { -+ object.put(JSONPair.key, JSONPair.val); -+ } -+ } -+ return object; -+ } -+ -+ /** -+ * Simply stores a key and a value, used internally by many methods below. -+ */ -+ @SuppressWarnings("PublicInnerClass") -+ public static class JSONPair { -+ final String key; -+ final Object val; -+ -+ JSONPair(@NotNull String key, @NotNull Object val) { -+ this.key = key; -+ this.val = val; -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/util/LoadingIntMap.java b/src/main/java/co/aikar/util/LoadingIntMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..63a899c7dbdb69daa4876a2ce2a7dfb734b5af9d ---- /dev/null -+++ b/src/main/java/co/aikar/util/LoadingIntMap.java -@@ -0,0 +1,76 @@ -+/* -+ * Copyright (c) 2015. Starlis LLC / dba Empire Minecraft -+ * -+ * This source code is proprietary software and must not be redistributed without Starlis LLC's approval -+ * -+ */ -+package co.aikar.util; -+ -+ -+import com.google.common.base.Function; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows you to pass a Loader function that when a key is accessed that doesn't exist, -+ * automatically loads the entry into the map by calling the loader Function. -+ * -+ * .get() Will only return null if the Loader can return null. -+ * -+ * You may pass any backing Map to use. -+ * -+ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. -+ * -+ * Do not wrap the backing map with Collections.synchronizedMap. -+ * -+ * @param Value -+ */ -+public class LoadingIntMap extends Int2ObjectOpenHashMap { -+ private final Function loader; -+ -+ public LoadingIntMap(@NotNull Function loader) { -+ super(); -+ this.loader = loader; -+ } -+ -+ public LoadingIntMap(int expectedSize, @NotNull Function loader) { -+ super(expectedSize); -+ this.loader = loader; -+ } -+ -+ public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function loader) { -+ super(expectedSize, loadFactor); -+ this.loader = loader; -+ } -+ -+ -+ @Nullable -+ @Override -+ public V get(int key) { -+ V res = super.get(key); -+ if (res == null) { -+ res = loader.apply(key); -+ if (res != null) { -+ put(key, res); -+ } -+ } -+ return res; -+ } -+ -+ /** -+ * Due to java stuff, you will need to cast it to (Function) for some cases -+ * -+ * @param Type -+ */ -+ public abstract static class Feeder implements Function { -+ @Nullable -+ @Override -+ public T apply(@Nullable Object input) { -+ return apply(); -+ } -+ -+ @Nullable -+ public abstract T apply(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aedbb03321886cb267879d7994653e447b485f6a ---- /dev/null -+++ b/src/main/java/co/aikar/util/LoadingMap.java -@@ -0,0 +1,368 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.util; -+ -+import com.google.common.base.Preconditions; -+import java.lang.reflect.Constructor; -+import java.util.AbstractMap; -+import java.util.Collection; -+import java.util.HashMap; -+import java.util.IdentityHashMap; -+import java.util.Map; -+import java.util.Set; -+import java.util.function.Function; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows you to pass a Loader function that when a key is accessed that doesn't exists, -+ * automatically loads the entry into the map by calling the loader Function. -+ * -+ * .get() Will only return null if the Loader can return null. -+ * -+ * You may pass any backing Map to use. -+ * -+ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. -+ * -+ * Do not wrap the backing map with Collections.synchronizedMap. -+ * -+ * @param Key -+ * @param Value -+ */ -+public class LoadingMap extends AbstractMap { -+ private final Map backingMap; -+ private final java.util.function.Function loader; -+ -+ /** -+ * Initializes an auto loading map using specified loader and backing map -+ * @param backingMap Map to wrap -+ * @param loader Loader -+ */ -+ public LoadingMap(@NotNull Map backingMap, @NotNull java.util.function.Function loader) { -+ this.backingMap = backingMap; -+ this.loader = loader; -+ } -+ -+ /** -+ * Creates a new LoadingMap with the specified map and loader -+ * -+ * @param backingMap Actual map being used. -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map of(@NotNull Map backingMap, @NotNull Function loader) { -+ return new LoadingMap<>(backingMap, loader); -+ } -+ -+ /** -+ * Creates a LoadingMap with an auto instantiating loader. -+ * -+ * Will auto construct class of of Value when not found -+ * -+ * Since this uses Reflection, It is more effecient to define your own static loader -+ * than using this helper, but if performance is not critical, this is easier. -+ * -+ * @param backingMap Actual map being used. -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newAutoMap(@NotNull Map backingMap, @Nullable final Class keyClass, -+ @NotNull final Class valueClass) { -+ return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass)); -+ } -+ /** -+ * Creates a LoadingMap with an auto instantiating loader. -+ * -+ * Will auto construct class of of Value when not found -+ * -+ * Since this uses Reflection, It is more effecient to define your own static loader -+ * than using this helper, but if performance is not critical, this is easier. -+ * -+ * @param backingMap Actual map being used. -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newAutoMap(@NotNull Map backingMap, -+ @NotNull final Class valueClass) { -+ return newAutoMap(backingMap, null, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass) { -+ return newAutoMap(new HashMap<>(), keyClass, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param valueClass Class used for the V generic -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@NotNull final Class valueClass) { -+ return newHashAutoMap(null, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param keyClass Class used for the K generic -+ * @param valueClass Class used for the V generic -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass, int initialCapacity, float loadFactor) { -+ return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass); -+ } -+ -+ /** -+ * @see #newAutoMap -+ * -+ * new Auto initializing map using a HashMap. -+ * -+ * @param valueClass Class used for the V generic -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map that auto instantiates on .get() -+ */ -+ @NotNull -+ public static Map newHashAutoMap(@NotNull final Class valueClass, int initialCapacity, float loadFactor) { -+ return newHashAutoMap(null, valueClass, initialCapacity, loadFactor); -+ } -+ -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader) { -+ return new LoadingMap<>(new HashMap<>(), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader, int initialCapacity) { -+ return new LoadingMap<>(new HashMap<>(initialCapacity), loader); -+ } -+ /** -+ * Initializes an auto loading map using a HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param loadFactor Load factor to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newHashMap(@NotNull Function loader, int initialCapacity, float loadFactor) { -+ return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using an Identity HashMap -+ * -+ * @param loader Loader to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newIdentityHashMap(@NotNull Function loader) { -+ return new LoadingMap<>(new IdentityHashMap<>(), loader); -+ } -+ -+ /** -+ * Initializes an auto loading map using an Identity HashMap -+ * -+ * @param loader Loader to use -+ * @param initialCapacity Initial capacity to use -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map newIdentityHashMap(@NotNull Function loader, int initialCapacity) { -+ return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader); -+ } -+ -+ @Override -+ public int size() {return backingMap.size();} -+ -+ @Override -+ public boolean isEmpty() {return backingMap.isEmpty();} -+ -+ @Override -+ public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);} -+ -+ @Override -+ public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);} -+ -+ @Nullable -+ @Override -+ public V get(@Nullable Object key) { -+ V v = backingMap.get(key); -+ if (v != null) { -+ return v; -+ } -+ return backingMap.computeIfAbsent((K) key, loader); -+ } -+ -+ @Nullable -+ public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);} -+ -+ @Nullable -+ @Override -+ public V remove(@Nullable Object key) {return backingMap.remove(key);} -+ -+ public void putAll(@NotNull Map m) {backingMap.putAll(m);} -+ -+ @Override -+ public void clear() {backingMap.clear();} -+ -+ @NotNull -+ @Override -+ public Set keySet() {return backingMap.keySet();} -+ -+ @NotNull -+ @Override -+ public Collection values() {return backingMap.values();} -+ -+ @Override -+ public boolean equals(@Nullable Object o) {return backingMap.equals(o);} -+ -+ @Override -+ public int hashCode() {return backingMap.hashCode();} -+ -+ @NotNull -+ @Override -+ public Set> entrySet() { -+ return backingMap.entrySet(); -+ } -+ -+ @NotNull -+ public LoadingMap clone() { -+ return new LoadingMap<>(backingMap, loader); -+ } -+ -+ private static class AutoInstantiatingLoader implements Function { -+ final Constructor constructor; -+ private final Class valueClass; -+ -+ AutoInstantiatingLoader(@Nullable Class keyClass, @NotNull Class valueClass) { -+ try { -+ this.valueClass = valueClass; -+ if (keyClass != null) { -+ constructor = valueClass.getConstructor(keyClass); -+ } else { -+ constructor = null; -+ } -+ } catch (NoSuchMethodException e) { -+ throw new IllegalStateException( -+ valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null)); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public V apply(@Nullable K input) { -+ try { -+ return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance()); -+ } catch (Exception e) { -+ throw new ExceptionInInitializerError(e); -+ } -+ } -+ -+ @Override -+ public int hashCode() { -+ return super.hashCode(); -+ } -+ -+ @Override -+ public boolean equals(Object object) { -+ return false; -+ } -+ } -+ -+ /** -+ * Due to java stuff, you will need to cast it to (Function) for some cases -+ * -+ * @param Type -+ */ -+ public abstract static class Feeder implements Function { -+ @Nullable -+ @Override -+ public T apply(@Nullable Object input) { -+ return apply(); -+ } -+ -+ @Nullable -+ public abstract T apply(); -+ } -+} -diff --git a/src/main/java/co/aikar/util/MRUMapCache.java b/src/main/java/co/aikar/util/MRUMapCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5989ee21297935651b0edd44b8239e655eaef1d9 ---- /dev/null -+++ b/src/main/java/co/aikar/util/MRUMapCache.java -@@ -0,0 +1,111 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.util; -+ -+import java.util.AbstractMap; -+import java.util.Collection; -+import java.util.Map; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result. -+ * -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ */ -+public class MRUMapCache extends AbstractMap { -+ final Map backingMap; -+ Object cacheKey; -+ V cacheValue; -+ public MRUMapCache(@NotNull final Map backingMap) { -+ this.backingMap = backingMap; -+ } -+ -+ public int size() {return backingMap.size();} -+ -+ public boolean isEmpty() {return backingMap.isEmpty();} -+ -+ public boolean containsKey(@Nullable Object key) { -+ return key != null && key.equals(cacheKey) || backingMap.containsKey(key); -+ } -+ -+ public boolean containsValue(@Nullable Object value) { -+ return value != null && value == cacheValue || backingMap.containsValue(value); -+ } -+ -+ @Nullable -+ public V get(@Nullable Object key) { -+ if (cacheKey != null && cacheKey.equals(key)) { -+ return cacheValue; -+ } -+ cacheKey = key; -+ return cacheValue = backingMap.get(key); -+ } -+ -+ @Nullable -+ public V put(@Nullable K key, @Nullable V value) { -+ cacheKey = key; -+ return cacheValue = backingMap.put(key, value); -+ } -+ -+ @Nullable -+ public V remove(@Nullable Object key) { -+ if (key != null && key.equals(cacheKey)) { -+ cacheKey = null; -+ } -+ return backingMap.remove(key); -+ } -+ -+ public void putAll(@NotNull Map m) {backingMap.putAll(m);} -+ -+ public void clear() { -+ cacheKey = null; -+ cacheValue = null; -+ backingMap.clear(); -+ } -+ -+ @NotNull -+ public Set keySet() {return backingMap.keySet();} -+ -+ @NotNull -+ public Collection values() {return backingMap.values();} -+ -+ @NotNull -+ public Set> entrySet() {return backingMap.entrySet();} -+ -+ /** -+ * Wraps the specified map with a most recently used cache -+ * -+ * @param map Map to be wrapped -+ * @param Key Type of the Map -+ * @param Value Type of the Map -+ * @return Map -+ */ -+ @NotNull -+ public static Map of(@NotNull Map map) { -+ return new MRUMapCache(map); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7168dd083ee30a47b104ab32cabb3215815f7470..7c715fdc11ab7837552b1fe3ffd08b31cec0a63b 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -649,7 +649,6 @@ public final class Bukkit { - */ - public static void reload() { - server.reload(); -- org.spigotmc.CustomTimingsHandler.reload(); // Spigot - } - - /** -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 4ba8572f1beb3b9ad46620946eb4ee89ac91818e..a6b9e4f158583e5932bf8ca210d531857e9f5360 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1344,6 +1344,26 @@ public interface Server extends PluginMessageRecipient { - throw new UnsupportedOperationException("Not supported yet."); - } - -+ // Paper start -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig() -+ { -+ throw new UnsupportedOperationException( "Not supported yet." ); -+ } -+ -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig() -+ { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @NotNull -+ public org.bukkit.configuration.file.YamlConfiguration getPaperConfig() -+ { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end -+ - /** - * Sends the component to the player - * -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 247d194f86c00db11acbc58e7d163b2606db4f07..945b8b030d1b2a13afc0c4efad76997eb7bf00ba 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -18,6 +18,7 @@ import org.bukkit.plugin.PluginDescriptionFile; - @Deprecated - public interface UnsafeValues { - -+ void reportTimings(); // Paper - Material toLegacy(Material material); - - Material fromLegacy(Material material); -@@ -69,4 +70,12 @@ public interface UnsafeValues { - * @return true if a file matching this key was found and deleted - */ - boolean removeAdvancement(NamespacedKey key); -+ -+ // Paper start -+ /** -+ * Server name to report to timings v2 -+ * @return name -+ */ -+ String getTimingsServerName(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/BufferedCommandSender.java b/src/main/java/org/bukkit/command/BufferedCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f9a00aecca5ec41b460bf41dfe1c69694768cf98 ---- /dev/null -+++ b/src/main/java/org/bukkit/command/BufferedCommandSender.java -@@ -0,0 +1,21 @@ -+package org.bukkit.command; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public class BufferedCommandSender implements MessageCommandSender { -+ private final StringBuffer buffer = new StringBuffer(); -+ @Override -+ public void sendMessage(@NotNull String message) { -+ buffer.append(message); -+ buffer.append("\n"); -+ } -+ -+ @NotNull -+ public String getBuffer() { -+ return buffer.toString(); -+ } -+ -+ public void reset() { -+ this.buffer.setLength(0); -+ } -+} -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 4bfc214685164a38ba4261b2bae7faa8a3bd297e..03bdc1622791e1206406c87065978688d602e39e 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -33,7 +33,8 @@ public abstract class Command { - protected String usageMessage; - private String permission; - private String permissionMessage; -- public org.spigotmc.CustomTimingsHandler timings; // Spigot -+ public co.aikar.timings.Timing timings; // Paper -+ @NotNull public String getTimingName() {return getName();} // Paper - - protected Command(@NotNull String name) { - this(name, "", "/" + name, new ArrayList()); -@@ -47,7 +48,6 @@ public abstract class Command { - this.usageMessage = (usageMessage == null) ? "/" + name : usageMessage; - this.aliases = aliases; - this.activeAliases = new ArrayList(aliases); -- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot - } - - /** -@@ -245,7 +245,6 @@ public abstract class Command { - } - this.nextLabel = name; - if (!isRegistered()) { -- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot - this.label = name; - return true; - } -diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -index d6c8938b1e13b63116b7b0e074ea8ef5997f8dc3..a6ad94ef98a1df1d2842635d850bc990b0137849 100644 ---- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java -+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -@@ -9,6 +9,7 @@ public class FormattedCommandAlias extends Command { - - public FormattedCommandAlias(@NotNull String alias, @NotNull String[] formatStrings) { - super(alias); -+ timings = co.aikar.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot - this.formatStrings = formatStrings; - } - -@@ -113,6 +114,10 @@ public class FormattedCommandAlias extends Command { - return formatString; - } - -+ @NotNull -+ @Override // Paper -+ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Paper -+ - private static boolean inRange(int i, int j, int k) { - return i >= j && i <= k; - } -diff --git a/src/main/java/org/bukkit/command/MessageCommandSender.java b/src/main/java/org/bukkit/command/MessageCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a7ef1f51c2b96617a32e6e7b1723e8770ba8a6a8 ---- /dev/null -+++ b/src/main/java/org/bukkit/command/MessageCommandSender.java -@@ -0,0 +1,129 @@ -+package org.bukkit.command; -+ -+import org.apache.commons.lang.NotImplementedException; -+import org.bukkit.Bukkit; -+import org.bukkit.Server; -+import org.bukkit.permissions.Permission; -+import org.bukkit.permissions.PermissionAttachment; -+import org.bukkit.permissions.PermissionAttachmentInfo; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.Set; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * For when all you care about is just messaging -+ */ -+public interface MessageCommandSender extends CommandSender { -+ -+ @Override -+ default void sendMessage(@NotNull String[] messages) { -+ for (String message : messages) { -+ sendMessage(message); -+ } -+ } -+ -+ @Override -+ default void sendMessage(@Nullable UUID sender, @NotNull String message) { -+ sendMessage(message); -+ } -+ -+ @Override -+ default void sendMessage(@Nullable UUID sender, @NotNull String[] messages) { -+ for (String message : messages) { -+ sendMessage(message); -+ } -+ } -+ -+ @NotNull -+ @Override -+ default Server getServer() { -+ return Bukkit.getServer(); -+ } -+ -+ @NotNull -+ @Override -+ default String getName() { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isOp() { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void setOp(boolean value) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isPermissionSet(@NotNull String name) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean isPermissionSet(@NotNull Permission perm) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean hasPermission(@NotNull String name) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default boolean hasPermission(@NotNull Permission perm) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void removeAttachment(@NotNull PermissionAttachment attachment) { -+ throw new NotImplementedException(); -+ } -+ -+ @Override -+ default void recalculatePermissions() { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default Set getEffectivePermissions() { -+ throw new NotImplementedException(); -+ } -+ -+ @NotNull -+ @Override -+ default Spigot spigot() { -+ throw new NotImplementedException(); -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 81e4fa57337f5a40c4b673136dd5eb595cce4629..f020cb04eba27a2e70fc7cf799ebbfb434b9d974 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -15,7 +15,6 @@ import org.bukkit.command.defaults.BukkitCommand; - import org.bukkit.command.defaults.HelpCommand; - import org.bukkit.command.defaults.PluginsCommand; - import org.bukkit.command.defaults.ReloadCommand; --import org.bukkit.command.defaults.TimingsCommand; - import org.bukkit.command.defaults.VersionCommand; - import org.bukkit.entity.Player; - import org.bukkit.util.StringUtil; -@@ -35,7 +34,7 @@ public class SimpleCommandMap implements CommandMap { - register("bukkit", new VersionCommand("version")); - register("bukkit", new ReloadCommand("reload")); - register("bukkit", new PluginsCommand("plugins")); -- register("bukkit", new TimingsCommand("timings")); -+ register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper - } - - public void setFallbackCommands() { -@@ -67,6 +66,7 @@ public class SimpleCommandMap implements CommandMap { - */ - @Override - public boolean register(@NotNull String label, @NotNull String fallbackPrefix, @NotNull Command command) { -+ command.timings = co.aikar.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Paper - label = label.toLowerCase(java.util.Locale.ENGLISH).trim(); - fallbackPrefix = fallbackPrefix.toLowerCase(java.util.Locale.ENGLISH).trim(); - boolean registered = register(label, command, false, fallbackPrefix); -@@ -143,16 +143,22 @@ public class SimpleCommandMap implements CommandMap { - return false; - } - -+ // Paper start - Plugins do weird things to workaround normal registration -+ if (target.timings == null) { -+ target.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, target); -+ } -+ // Paper end -+ - try { -- target.timings.startTiming(); // Spigot -+ try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources - // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) - target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); -- target.timings.stopTiming(); // Spigot -+ } // target.timings.stopTiming(); // Spigot // Paper - } catch (CommandException ex) { -- target.timings.stopTiming(); // Spigot -+ //target.timings.stopTiming(); // Spigot // Paper - throw ex; - } catch (Throwable ex) { -- target.timings.stopTiming(); // Spigot -+ //target.timings.stopTiming(); // Spigot // Paper - throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); - } - -diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -deleted file mode 100644 -index 2a145d851ce30360aa39549745bd87590c034584..0000000000000000000000000000000000000000 ---- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -+++ /dev/null -@@ -1,250 +0,0 @@ --package org.bukkit.command.defaults; -- --import com.google.common.collect.ImmutableList; --import java.io.File; --import java.io.IOException; --import java.io.PrintStream; --import java.util.ArrayList; --import java.util.List; --import org.apache.commons.lang.Validate; --import org.bukkit.Bukkit; --import org.bukkit.ChatColor; --import org.bukkit.command.CommandSender; --import org.bukkit.event.Event; --import org.bukkit.event.HandlerList; --import org.bukkit.plugin.Plugin; --import org.bukkit.plugin.RegisteredListener; --import org.bukkit.plugin.TimedRegisteredListener; --import org.bukkit.util.StringUtil; --import org.jetbrains.annotations.NotNull; -- --// Spigot start --// CHECKSTYLE:OFF --import java.io.ByteArrayOutputStream; --import java.io.OutputStream; --import java.net.HttpURLConnection; --import java.net.URL; --import java.util.logging.Level; --import org.bukkit.command.RemoteConsoleCommandSender; --import org.bukkit.plugin.SimplePluginManager; --import org.spigotmc.CustomTimingsHandler; --// CHECKSTYLE:ON --// Spigot end -- --public class TimingsCommand extends BukkitCommand { -- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot -- public static long timingStart = 0; // Spigot -- -- public TimingsCommand(@NotNull String name) { -- super(name); -- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot -- this.usageMessage = "/timings "; // Spigot -- this.setPermission("bukkit.command.timings"); -- } -- -- // Spigot start - redesigned Timings Command -- public void executeSpigotTimings(@NotNull CommandSender sender, @NotNull String[] args) { -- if ("on".equals(args[0])) { -- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(true); -- CustomTimingsHandler.reload(); -- sender.sendMessage("Enabled Timings & Reset"); -- return; -- } else if ("off".equals(args[0])) { -- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(false); -- sender.sendMessage("Disabled Timings"); -- return; -- } -- -- if (!Bukkit.getPluginManager().useTimings()) { -- sender.sendMessage("Please enable timings by typing /timings on"); -- return; -- } -- -- boolean paste = "paste".equals(args[0]); -- if ("reset".equals(args[0])) { -- CustomTimingsHandler.reload(); -- sender.sendMessage("Timings reset"); -- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { -- long sampleTime = System.nanoTime() - timingStart; -- int index = 0; -- File timingFolder = new File("timings"); -- timingFolder.mkdirs(); -- File timings = new File(timingFolder, "timings.txt"); -- ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; -- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); -- PrintStream fileTimings = null; -- try { -- fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); -- -- CustomTimingsHandler.printTimings(fileTimings); -- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)"); -- -- fileTimings.println(""); -- fileTimings.println(Bukkit.spigot().getConfig().saveToString()); -- fileTimings.println(""); -- -- if (paste) { -- new PasteThread(sender, bout).start(); -- return; -- } -- -- sender.sendMessage("Timings written to " + timings.getPath()); -- sender.sendMessage("Paste contents of file into form at http://www.spigotmc.org/go/timings to read results."); -- -- } catch (IOException e) { -- } finally { -- if (fileTimings != null) { -- fileTimings.close(); -- } -- } -- } -- } -- // Spigot end -- -- @Override -- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -- if (!testPermission(sender)) return true; -- if (args.length < 1) { // Spigot -- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -- return false; -- } -- // Spigot start -- if (true) { -- executeSpigotTimings(sender, args); -- return true; -- } -- // Spigot end -- if (!sender.getServer().getPluginManager().useTimings()) { -- sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); -- return true; -- } -- -- boolean separate = "separate".equalsIgnoreCase(args[0]); -- if ("reset".equalsIgnoreCase(args[0])) { -- for (HandlerList handlerList : HandlerList.getHandlerLists()) { -- for (RegisteredListener listener : handlerList.getRegisteredListeners()) { -- if (listener instanceof TimedRegisteredListener) { -- ((TimedRegisteredListener) listener).reset(); -- } -- } -- } -- sender.sendMessage("Timings reset"); -- } else if ("merged".equalsIgnoreCase(args[0]) || separate) { -- -- int index = 0; -- int pluginIdx = 0; -- File timingFolder = new File("timings"); -- timingFolder.mkdirs(); -- File timings = new File(timingFolder, "timings.txt"); -- File names = null; -- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); -- PrintStream fileTimings = null; -- PrintStream fileNames = null; -- try { -- fileTimings = new PrintStream(timings); -- if (separate) { -- names = new File(timingFolder, "names" + index + ".txt"); -- fileNames = new PrintStream(names); -- } -- for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -- pluginIdx++; -- long totalTime = 0; -- if (separate) { -- fileNames.println(pluginIdx + " " + plugin.getDescription().getFullName()); -- fileTimings.println("Plugin " + pluginIdx); -- } else { -- fileTimings.println(plugin.getDescription().getFullName()); -- } -- for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { -- if (listener instanceof TimedRegisteredListener) { -- TimedRegisteredListener trl = (TimedRegisteredListener) listener; -- long time = trl.getTotalTime(); -- int count = trl.getCount(); -- if (count == 0) continue; -- long avg = time / count; -- totalTime += time; -- Class eventClass = trl.getEventClass(); -- if (count > 0 && eventClass != null) { -- fileTimings.println(" " + eventClass.getSimpleName() + (trl.hasMultiple() ? " (and sub-classes)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); -- } -- } -- } -- fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); -- } -- sender.sendMessage("Timings written to " + timings.getPath()); -- if (separate) sender.sendMessage("Names written to " + names.getPath()); -- } catch (IOException e) { -- } finally { -- if (fileTimings != null) { -- fileTimings.close(); -- } -- if (fileNames != null) { -- fileNames.close(); -- } -- } -- } else { -- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -- return false; -- } -- return true; -- } -- -- @NotNull -- @Override -- public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { -- Validate.notNull(sender, "Sender cannot be null"); -- Validate.notNull(args, "Arguments cannot be null"); -- Validate.notNull(alias, "Alias cannot be null"); -- -- if (args.length == 1) { -- return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, new ArrayList(TIMINGS_SUBCOMMANDS.size())); -- } -- return ImmutableList.of(); -- } -- -- // Spigot start -- private static class PasteThread extends Thread { -- -- private final CommandSender sender; -- private final ByteArrayOutputStream bout; -- -- public PasteThread(@NotNull CommandSender sender, @NotNull ByteArrayOutputStream bout) { -- super("Timings paste thread"); -- this.sender = sender; -- this.bout = bout; -- } -- -- @Override -- public synchronized void start() { -- if (sender instanceof RemoteConsoleCommandSender) { -- run(); -- } else { -- super.start(); -- } -- } -- -- @Override -- public void run() { -- try { -- HttpURLConnection con = (HttpURLConnection) new URL("https://timings.spigotmc.org/paste").openConnection(); -- con.setDoOutput(true); -- con.setRequestMethod("POST"); -- con.setInstanceFollowRedirects(false); -- -- OutputStream out = con.getOutputStream(); -- out.write(bout.toByteArray()); -- out.close(); -- -- com.google.gson.JsonObject location = new com.google.gson.Gson().fromJson(new java.io.InputStreamReader(con.getInputStream()), com.google.gson.JsonObject.class); -- con.getInputStream().close(); -- -- String pasteID = location.get("key").getAsString(); -- sender.sendMessage(ChatColor.GREEN + "Timings results can be viewed at https://www.spigotmc.org/go/timings?url=" + pasteID); -- } catch (IOException ex) { -- sender.sendMessage(ChatColor.RED + "Error pasting timings, check your console for more information"); -- Bukkit.getServer().getLogger().log(Level.WARNING, "Could not paste timings", ex); -- } -- } -- } -- // Spigot end --} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index da1b5b5253c0ac0abe1019096166e6c76a50e699..586fd9ebd02039ebd2c071cbbbf60f24879f96b9 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1368,7 +1368,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); -+ -+ } -+ -+ // Paper start -+ public int getPing() { -+ throw new UnsupportedOperationException( "Not supported yet." ); - } -+ // Paper end - } - - @NotNull -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 62d0017362204070465c8ff72e5c2ca07501f558..745eaa8f2f2ff83536301db8ca47a8af30df7a73 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -358,7 +358,6 @@ public final class SimplePluginManager implements PluginManager { - } - } - -- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot - return result.toArray(new Plugin[result.size()]); - } - -@@ -397,9 +396,9 @@ public final class SimplePluginManager implements PluginManager { - - if (result != null) { - plugins.add(result); -- lookupNames.put(result.getDescription().getName(), result); -+ lookupNames.put(result.getDescription().getName().toLowerCase(java.util.Locale.ENGLISH), result); // Paper - for (String provided : result.getDescription().getProvides()) { -- lookupNames.putIfAbsent(provided, result); -+ lookupNames.putIfAbsent(provided.toLowerCase(java.util.Locale.ENGLISH), result); // Paper - } - } - -@@ -428,7 +427,7 @@ public final class SimplePluginManager implements PluginManager { - @Override - @Nullable - public synchronized Plugin getPlugin(@NotNull String name) { -- return lookupNames.get(name.replace(' ', '_')); -+ return lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper - } - - @Override -@@ -646,7 +645,8 @@ public final class SimplePluginManager implements PluginManager { - throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); - } - -- if (useTimings) { -+ executor = new co.aikar.timings.TimedEventExecutor(executor, plugin, null, event); // Paper -+ if (false) { // Spigot - RL handles useTimings check now // Paper - getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); - } else { - getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); -@@ -860,7 +860,7 @@ public final class SimplePluginManager implements PluginManager { - - @Override - public boolean useTimings() { -- return useTimings; -+ return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot - } - - /** -@@ -869,6 +869,6 @@ public final class SimplePluginManager implements PluginManager { - * @param use True if per event timing code should be used - */ - public void useTimings(boolean use) { -- useTimings = use; -+ co.aikar.timings.Timings.setTimingsEnabled(use); // Paper - } - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index a09c3f71ca563b6f40a118ce1344d0eb273bed40..cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -54,7 +54,6 @@ public final class JavaPluginLoader implements PluginLoader { - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; - private final List loaders = new CopyOnWriteArrayList(); - private final LibraryLoader libraryLoader; -- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot - - /** - * This class was not meant to be constructed explicitly -@@ -292,27 +291,21 @@ public final class JavaPluginLoader implements PluginLoader { - } - } - -- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName() + "(" + eventClass.getSimpleName() + ")", pluginParentTimer); // Spigot -- EventExecutor executor = new EventExecutor() { -+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper - @Override -- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper - try { - if (!eventClass.isAssignableFrom(event.getClass())) { - return; - } -- // Spigot start -- boolean isAsync = event.isAsynchronous(); -- if (!isAsync) timings.startTiming(); - method.invoke(listener, event); -- if (!isAsync) timings.stopTiming(); -- // Spigot end - } catch (InvocationTargetException ex) { - throw new EventException(ex.getCause()); - } catch (Throwable t) { - throw new EventException(t); - } - } -- }; -+ }, plugin, method, eventClass); // Paper - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 6843e32438492f380e2e72bb40dd49d45fe675cb..5ffa98bb9c76d802a9d0ea6c572a704a2732c67c 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; - /** - * A ClassLoader for plugins, to allow shared classes across multiple plugins - */ --final class PluginClassLoader extends URLClassLoader { -+public final class PluginClassLoader extends URLClassLoader { // Spigot -+ public JavaPlugin getPlugin() { return plugin; } // Spigot - private final JavaPluginLoader loader; - private final Map> classes = new ConcurrentHashMap>(); - private final PluginDescriptionFile description; -diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java -index 5ca863b3692b2e1b58e7fb4d82f554a92cc4f01e..612958a331575d1da2715531ebdf6b1168f2e860 100644 ---- a/src/main/java/org/bukkit/util/CachedServerIcon.java -+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java -@@ -2,6 +2,7 @@ package org.bukkit.util; - - import org.bukkit.Server; - import org.bukkit.event.server.ServerListPingEvent; -+import org.jetbrains.annotations.Nullable; - - /** - * This is a cached version of a server-icon. It's internal representation -@@ -12,4 +13,9 @@ import org.bukkit.event.server.ServerListPingEvent; - * @see Server#loadServerIcon(java.io.File) - * @see ServerListPingEvent#setServerIcon(CachedServerIcon) - */ --public interface CachedServerIcon {} -+public interface CachedServerIcon { -+ -+ @Nullable -+ public String getData(); // Paper -+ -+} -diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java -index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..3cbe5c2bb55dead7968a6f165ef267e3e2931061 100644 ---- a/src/main/java/org/spigotmc/CustomTimingsHandler.java -+++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java -@@ -1,3 +1,26 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ - package org.spigotmc; - - import java.io.PrintStream; -@@ -5,133 +28,84 @@ import java.util.Queue; - import java.util.concurrent.ConcurrentLinkedQueue; - import org.bukkit.Bukkit; - import org.bukkit.World; --import org.bukkit.command.defaults.TimingsCommand; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -+import org.bukkit.plugin.AuthorNagException; -+import org.bukkit.plugin.Plugin; -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; -+ -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.util.logging.Level; - - /** -- * Provides custom timing sections for /timings merged. -+ * This is here for legacy purposes incase any plugin used it. -+ * -+ * If you use this, migrate ASAP as this will be removed in the future! -+ * -+ * @deprecated -+ * @see co.aikar.timings.Timings#of - */ --public class CustomTimingsHandler { -- -- private static Queue HANDLERS = new ConcurrentLinkedQueue(); -- /*========================================================================*/ -- private final String name; -- private final CustomTimingsHandler parent; -- private long count = 0; -- private long start = 0; -- private long timingDepth = 0; -- private long totalTime = 0; -- private long curTickTotal = 0; -- private long violations = 0; -+@Deprecated -+public final class CustomTimingsHandler { -+ private final Timing handler; -+ private static Boolean sunReflectAvailable; -+ private static Method getCallerClass; - - public CustomTimingsHandler(@NotNull String name) { -- this(name, null); -- } -+ if (sunReflectAvailable == null) { -+ String javaVer = System.getProperty("java.version"); -+ String[] elements = javaVer.split("\\."); - -- public CustomTimingsHandler(@NotNull String name, @Nullable CustomTimingsHandler parent) { -- this.name = name; -- this.parent = parent; -- HANDLERS.add(this); -- } -+ int major = Integer.parseInt(elements.length >= 2 ? elements[1] : javaVer); -+ if (major <= 8) { -+ sunReflectAvailable = true; - -- /** -- * Prints the timings and extra data to the given stream. -- * -- * @param printStream output stream -- */ -- public static void printTimings(@NotNull PrintStream printStream) { -- printStream.println("Minecraft"); -- for (CustomTimingsHandler timings : HANDLERS) { -- long time = timings.totalTime; -- long count = timings.count; -- if (count == 0) { -- continue; -+ try { -+ Class reflection = Class.forName("sun.reflect.Reflection"); -+ getCallerClass = reflection.getMethod("getCallerClass", int.class); -+ } catch (ClassNotFoundException | NoSuchMethodException ignored) { -+ } -+ } else { -+ sunReflectAvailable = false; - } -- long avg = time / count; -- -- printStream.println(" " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations); -- } -- printStream.println("# Version " + Bukkit.getVersion()); -- int entities = 0; -- int livingEntities = 0; -- for (World world : Bukkit.getWorlds()) { -- entities += world.getEntities().size(); -- livingEntities += world.getLivingEntities().size(); - } -- printStream.println("# Entities " + entities); -- printStream.println("# LivingEntities " + livingEntities); -- } - -- /** -- * Resets all timings. -- */ -- public static void reload() { -- if (Bukkit.getPluginManager().useTimings()) { -- for (CustomTimingsHandler timings : HANDLERS) { -- timings.reset(); -+ Class calling = null; -+ if (sunReflectAvailable) { -+ try { -+ calling = (Class) getCallerClass.invoke(null, 2); -+ } catch (IllegalAccessException | InvocationTargetException ignored) { - } - } -- TimingsCommand.timingStart = System.nanoTime(); -- } - -- /** -- * Ticked every tick by CraftBukkit to count the number of times a timer -- * caused TPS loss. -- */ -- public static void tick() { -- if (Bukkit.getPluginManager().useTimings()) { -- for (CustomTimingsHandler timings : HANDLERS) { -- if (timings.curTickTotal > 50000000) { -- timings.violations += Math.ceil(timings.curTickTotal / 50000000); -- } -- timings.curTickTotal = 0; -- timings.timingDepth = 0; // incase reset messes this up -- } -- } -- } -+ Timing timing; - -- /** -- * Starts timing to track a section of code. -- */ -- public void startTiming() { -- // If second condtion fails we are already timing -- if (Bukkit.getPluginManager().useTimings() && ++timingDepth == 1) { -- start = System.nanoTime(); -- if (parent != null && ++parent.timingDepth == 1) { -- parent.start = start; -- } -- } -- } -+ Plugin plugin = null; -+ try { -+ plugin = TimingsManager.getPluginByClassloader(calling); -+ } catch (Exception ignored) {} - -- /** -- * Stops timing a section of code. -- */ -- public void stopTiming() { -- if (Bukkit.getPluginManager().useTimings()) { -- if (--timingDepth != 0 || start == 0) { -- return; -- } -- long diff = System.nanoTime() - start; -- totalTime += diff; -- curTickTotal += diff; -- count++; -- start = 0; -- if (parent != null) { -- parent.stopTiming(); -+ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); -+ if (plugin != null) { -+ timing = Timings.of(plugin, "(Deprecated API) " + name); -+ } else { -+ try { -+ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); -+ ofSafe.setAccessible(true); -+ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); -+ timing = Timings.NULL_HANDLER; - } - } -+ handler = timing; - } - -- /** -- * Reset this timer, setting all values to zero. -- */ -- public void reset() { -- count = 0; -- violations = 0; -- curTickTotal = 0; -- totalTime = 0; -- start = 0; -- timingDepth = 0; -- } -+ public void startTiming() { handler.startTiming(); } -+ public void stopTiming() { handler.stopTiming(); } -+ - } diff --git a/Spigot-API-Patches/0005-Adventure.patch b/Spigot-API-Patches/0005-Adventure.patch deleted file mode 100644 index 67fbf872024d..000000000000 --- a/Spigot-API-Patches/0005-Adventure.patch +++ /dev/null @@ -1,3777 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:21:55 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/pom.xml b/pom.xml -index 9aafdcc49ed83b403abb96891008103e6d6a69fa..1ced7a212684cee8faf07fa9a083adcd47be7fcb 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -22,6 +22,7 @@ - 1.8 - 1.8 - UTF-8 -+ 4.7.0 - - - -@@ -31,7 +32,39 @@ - - - -+ -+ -+ -+ -+ net.kyori -+ adventure-bom -+ ${adventure.version} -+ pom -+ import -+ -+ -+ -+ -+ - -+ -+ -+ net.kyori -+ adventure-api -+ -+ -+ net.kyori -+ adventure-text-serializer-gson -+ -+ -+ net.kyori -+ adventure-text-serializer-legacy -+ -+ -+ net.kyori -+ adventure-text-serializer-plain -+ -+ - - it.unimi.dsi - fastutil -@@ -216,6 +249,12 @@ - https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ - https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ - https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ -+ -+ https://jd.adventure.kyori.net/api/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-gson/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-legacy/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-plain/${adventure.version}/ -+ - - - -diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java -index ef58a6c00f444bd498a2d8fc4e457236f393954f..ecd149157d4fb80444f34bf5633d74bcdb63dec5 100644 ---- a/src/main/java/co/aikar/timings/TimingsReportListener.java -+++ b/src/main/java/co/aikar/timings/TimingsReportListener.java -@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - - @SuppressWarnings("WeakerAccess") --public class TimingsReportListener implements MessageCommandSender { -+public class TimingsReportListener implements net.kyori.adventure.audience.ForwardingAudience, MessageCommandSender { // Paper - private final List senders; - private final Runnable onDone; - private String timingsURL; -@@ -74,4 +74,17 @@ public class TimingsReportListener implements MessageCommandSender { - this.senders.add(Bukkit.getConsoleSender()); - } - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ net.kyori.adventure.audience.ForwardingAudience.super.sendMessage(source, message, type); -+ } -+ -+ @NotNull -+ @Override -+ public Iterable audiences() { -+ return this.senders; -+ } -+ // Paper end - } -diff --git a/src/main/java/io/papermc/paper/chat/ChatComposer.java b/src/main/java/io/papermc/paper/chat/ChatComposer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1f03ce9ff40ed12a1825c8e24dabddbbef44d6af ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatComposer.java -@@ -0,0 +1,24 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat composer is responsible for composing chat messages sent by {@link Player}s to the server. -+ */ -+@FunctionalInterface -+public interface ChatComposer { -+ ChatComposer DEFAULT = (player, displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Composes a chat message. -+ * -+ * @param source the message source -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a composed chat message -+ */ -+ @NotNull -+ Component composeChat(final @NotNull Player source, final @NotNull Component displayName, final @NotNull Component message); -+} -diff --git a/src/main/java/io/papermc/paper/chat/ChatFormatter.java b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ae811175089009be6b1db6941e9c5a24b2b1f027 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -@@ -0,0 +1,28 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat formatter is responsible for the formatting of chat messages sent by {@link Player}s to the server. -+ * -+ * @deprecated in favour of {@link ChatComposer} -+ */ -+@Deprecated -+@FunctionalInterface -+public interface ChatFormatter { -+ @Deprecated -+ ChatFormatter DEFAULT = (displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Formats a chat message. -+ * -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a formatted chat message -+ */ -+ @Deprecated -+ @NotNull -+ Component chat(final @NotNull Component displayName, final @NotNull Component message); -+} -diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f77597786f201b57ac18e14099f7b84f1e4e4cf3 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java -@@ -0,0 +1,140 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.Set; -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.player.PlayerEvent; -+import org.checkerframework.checker.nullness.qual.Nullable; -+import org.jetbrains.annotations.NotNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+/** -+ * An abstract implementation of a chat event, handling shared logic. -+ */ -+public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable { -+ private final Set recipients; -+ private boolean cancelled = false; -+ private ChatComposer composer; -+ @Deprecated private @Nullable ChatFormatter formatter; -+ private Component message; -+ -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ this.composer = composer; -+ this.message = message; -+ } -+ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ this.formatter = formatter; -+ this.message = message; -+ } -+ -+ /** -+ * Gets a set of recipients that this chat message will be displayed to. -+ * -+ *

The set returned is not guaranteed to be mutable and may auto-populate -+ * on access. Any listener accessing the returned set should be aware that -+ * it may reduce performance for a lazy set implementation.

-+ * -+ *

Listeners should be aware that modifying the list may throw {@link -+ * UnsupportedOperationException} if the event caller provides an -+ * unmodifiable set.

-+ * -+ * @return a set of players who will receive the chat message -+ */ -+ @NotNull -+ public final Set recipients() { -+ return this.recipients; -+ } -+ -+ /** -+ * Gets the chat composer. -+ * -+ * @return the chat composer -+ */ -+ @NotNull -+ public final ChatComposer composer() { -+ if(this.composer == null) { -+ requireNonNull(this.formatter, "composer and formatter"); -+ this.composer = (source, displayName, message) -> this.formatter.chat(displayName, message); -+ } -+ return this.composer; -+ } -+ -+ /** -+ * Sets the chat composer. -+ * -+ * @param composer the chat composer -+ * @throws NullPointerException if {@code composer} is {@code null} -+ */ -+ public final void composer(final @NotNull ChatComposer composer) { -+ this.composer = requireNonNull(composer, "composer"); -+ this.formatter = null; -+ } -+ -+ /** -+ * Gets the chat formatter. -+ * -+ * @return the chat formatter -+ * @deprecated in favour of {@link #composer()} -+ */ -+ @Deprecated -+ @NotNull -+ public final ChatFormatter formatter() { -+ if(this.formatter == null) { -+ this.formatter = (displayName, message) -> this.composer.composeChat(this.player, displayName, message); -+ } -+ return this.formatter; -+ } -+ -+ /** -+ * Sets the chat formatter. -+ * -+ * @param formatter the chat formatter -+ * @throws NullPointerException if {@code formatter} is {@code null} -+ * @deprecated in favour of {@link #composer(ChatComposer)} -+ */ -+ @Deprecated -+ public final void formatter(final @NotNull ChatFormatter formatter) { -+ this.formatter = requireNonNull(formatter, "formatter"); -+ this.composer = (source, displayName, message) -> formatter.chat(displayName, message); -+ } -+ -+ /** -+ * Gets the user-supplied message. -+ * -+ * @return the user-supplied message -+ */ -+ @NotNull -+ public final Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Sets the user-supplied message. -+ * -+ * @param message the user-supplied message -+ * @throws NullPointerException if {@code message} is {@code null} -+ */ -+ public final void message(final @NotNull Component message) { -+ this.message = requireNonNull(message, "message"); -+ } -+ -+ @Override -+ public final boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ @Override -+ public final void setCancelled(final boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a0f748957f4472103dd27fc95a711a42de7fae89 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java -@@ -0,0 +1,39 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.Set; -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * An event fired when a {@link Player} sends a chat message to the server. -+ */ -+public final class AsyncChatEvent extends AbstractChatEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(async, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated use {@link #AsyncChatEvent(boolean, Player, Set, ChatComposer, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(async, player, recipients, formatter, message); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..13c5df5fb8ce1d0203d99e88dd691019146a8f52 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java -@@ -0,0 +1,44 @@ -+package io.papermc.paper.event.player; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.Set; -+import net.kyori.adventure.text.Component; -+import org.bukkit.Warning; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * An event fired when a {@link Player} sends a chat message to the server. -+ * -+ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link AsyncChatEvent} instead, wherever possible. -+ */ -+@Deprecated -+@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") -+public final class ChatEvent extends AbstractChatEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(false, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated use {@link #ChatEvent(Player, Set, ChatComposer, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(false, player, recipients, formatter, message); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/text/PaperComponents.java b/src/main/java/io/papermc/paper/text/PaperComponents.java -new file mode 100644 -index 0000000000000000000000000000000000000000..77db592d05b754f879f8d1790642e9d9bbd30a4e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/text/PaperComponents.java -@@ -0,0 +1,88 @@ -+package io.papermc.paper.text; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import org.bukkit.Bukkit; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Paper API-specific methods for working with {@link Component}s and related. -+ */ -+public final class PaperComponents { -+ private PaperComponents() { -+ throw new RuntimeException("PaperComponents is not to be instantiated!"); -+ } -+ -+ /** -+ * Return a component flattener that can use game data to resolve extra information about components. -+ * -+ * @return a component flattener -+ */ -+ public static @NonNull ComponentFlattener flattener() { -+ return Bukkit.getUnsafe().componentFlattener(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert components to -+ * a plain-text string. -+ * -+ *

Implementations may provide a serializer capable of processing any -+ * information that requires access to implementation details.

-+ * -+ * @return a serializer to plain text -+ */ -+ public static @NonNull PlainComponentSerializer plainSerializer() { -+ return Bukkit.getUnsafe().plainComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * standard JSON serialization format using Gson. -+ * -+ *

Implementations may provide a serializer capable of processing any -+ * information that requires implementation details, such as legacy -+ * (pre-1.16) hover events.

-+ * -+ * @return a json component serializer -+ */ -+ public static @NonNull GsonComponentSerializer gsonSerializer() { -+ return Bukkit.getUnsafe().gsonComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * standard JSON serialization format using Gson, downsampling any RGB colors -+ * to their nearest {@link NamedTextColor} counterpart. -+ * -+ *

Implementations may provide a serializer capable of processing any -+ * information that requires implementation details, such as legacy -+ * (pre-1.16) hover events.

-+ * -+ * @return a json component serializer -+ */ -+ public static @NonNull GsonComponentSerializer colorDownsamplingGsonSerializer() { -+ return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer(); -+ } -+ -+ /** -+ * Get a serializer for {@link Component}s that will convert to and from the -+ * legacy component format used by Bukkit. This serializer uses the -+ * {@link LegacyComponentSerializer.Builder#useUnusualXRepeatedCharacterHexFormat()} -+ * option to match upstream behavior. -+ * -+ *

This legacy serializer uses the standard section symbol to mark -+ * formatting characters.

-+ * -+ *

Implementations may provide a serializer capable of processing any -+ * information that requires access to implementation details.

-+ * -+ * @return a section serializer -+ */ -+ public static @NonNull LegacyComponentSerializer legacySectionSerializer() { -+ return Bukkit.getUnsafe().legacyComponentSerializer(); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7c715fdc11ab7837552b1fe3ffd08b31cec0a63b..426b1e83226e674ee4bf3ec05ddcd3ac4376b06d 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -278,7 +278,9 @@ public final class Bukkit { - * - * @param message the message - * @return the number of players -+ * @deprecated in favour of {@link Server#sendMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public static int broadcastMessage(@NotNull String message) { - return server.broadcastMessage(message); - } -@@ -836,6 +838,7 @@ public final class Bukkit { - server.shutdown(); - } - -+ // Paper start - /** - * Broadcasts the specified message to every user with the given - * permission name. -@@ -845,6 +848,21 @@ public final class Bukkit { - * permissibles} must have to receive the broadcast - * @return number of message recipients - */ -+ public static int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission) { -+ return server.broadcast(message, permission); -+ } -+ // Paper end -+ /** -+ * Broadcasts the specified message to every user with the given -+ * permission name. -+ * -+ * @param message message to broadcast -+ * @param permission the required permission {@link Permissible -+ * permissibles} must have to receive the broadcast -+ * @return number of message recipients -+ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} -+ */ -+ @Deprecated // Paper - public static int broadcast(@NotNull String message, @NotNull String permission) { - return server.broadcast(message, permission); - } -@@ -1044,6 +1062,7 @@ public final class Bukkit { - return server.createInventory(owner, type); - } - -+ // Paper start - /** - * Creates an empty inventory with the specified type and title. If the type - * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -@@ -1069,6 +1088,38 @@ public final class Bukkit { - * @see InventoryType#isCreatable() - */ - @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title) { -+ return server.createInventory(owner, type, title); -+ } -+ // Paper end -+ -+ /** -+ * Creates an empty inventory with the specified type and title. If the type -+ * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -+ * otherwise the new inventory has the normal size for its type.
-+ * It should be noted that some inventory types do not support titles and -+ * may not render with said titles on the Minecraft client. -+ *
-+ * {@link InventoryType#WORKBENCH} will not process crafting recipes if -+ * created with this method. Use -+ * {@link Player#openWorkbench(Location, boolean)} instead. -+ *
-+ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s -+ * for possible enchanting results. Use -+ * {@link Player#openEnchanting(Location, boolean)} instead. -+ * -+ * @param owner The holder of the inventory; can be null if there's no holder. -+ * @param type The type of inventory to create. -+ * @param title The title of the inventory, to be displayed when it is viewed. -+ * @return The new inventory. -+ * @throws IllegalArgumentException if the {@link InventoryType} cannot be -+ * viewed. -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ * -+ * @see InventoryType#isCreatable() -+ */ -+ @Deprecated // Paper -+ @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { - return server.createInventory(owner, type, title); - } -@@ -1087,6 +1138,7 @@ public final class Bukkit { - return server.createInventory(owner, size); - } - -+ // Paper start - /** - * Creates an empty inventory of type {@link InventoryType#CHEST} with the - * specified size and title. -@@ -1099,10 +1151,30 @@ public final class Bukkit { - * @throws IllegalArgumentException if the size is not a multiple of 9 - */ - @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ return server.createInventory(owner, size, title); -+ } -+ // Paper end -+ -+ /** -+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the -+ * specified size and title. -+ * -+ * @param owner the holder of the inventory, or null to indicate no holder -+ * @param size a multiple of 9 as the size of inventory to create -+ * @param title the title of the inventory, displayed when inventory is -+ * viewed -+ * @return a new inventory -+ * @throws IllegalArgumentException if the size is not a multiple of 9 -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ @NotNull - public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException { - return server.createInventory(owner, size, title); - } - -+ // Paper start - /** - * Creates an empty merchant. - * -@@ -1110,7 +1182,20 @@ public final class Bukkit { - * when the merchant inventory is viewed - * @return a new merchant - */ -+ public static @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title) { -+ return server.createMerchant(title); -+ } -+ // Paper start -+ /** -+ * Creates an empty merchant. -+ * -+ * @param title the title of the corresponding merchant inventory, displayed -+ * when the merchant inventory is viewed -+ * @return a new merchant -+ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} -+ */ - @NotNull -+ @Deprecated // Paper - public static Merchant createMerchant(@Nullable String title) { - return server.createMerchant(title); - } -@@ -1181,22 +1266,47 @@ public final class Bukkit { - return server.isPrimaryThread(); - } - -+ // Paper start -+ /** -+ * Gets the message that is displayed on the server list. -+ * -+ * @return the server's MOTD -+ */ -+ @NotNull public static net.kyori.adventure.text.Component motd() { -+ return server.motd(); -+ } -+ // Paper end -+ - /** - * Gets the message that is displayed on the server list. - * - * @return the servers MOTD -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - public static String getMotd() { - return server.getMotd(); - } - -+ // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ public static @Nullable net.kyori.adventure.text.Component shutdownMessage() { -+ return server.shutdownMessage(); -+ } -+ // Paper end - /** - * Gets the default message that is displayed when the server is stopped. - * - * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -+ @Deprecated // Paper - public static String getShutdownMessage() { - return server.getShutdownMessage(); - } -diff --git a/src/main/java/org/bukkit/Nameable.java b/src/main/java/org/bukkit/Nameable.java -index fee814e01a653d2b53c56e8b566383ca44aa5346..2acdf2a6d3955923c721222b9da784f3278f6418 100644 ---- a/src/main/java/org/bukkit/Nameable.java -+++ b/src/main/java/org/bukkit/Nameable.java -@@ -4,6 +4,30 @@ import org.jetbrains.annotations.Nullable; - - public interface Nameable { - -+ // Paper start -+ /** -+ * Gets the custom name. -+ * -+ *

This value has no effect on players, they will always use their real name.

-+ * -+ * @return the custom name -+ */ -+ @Nullable net.kyori.adventure.text.Component customName(); -+ -+ /** -+ * Sets the custom name. -+ * -+ *

This name will be used in death messages and can be sent to the client as a nameplate over the mob.

-+ * -+ *

Setting the name to {@code null} will clear it.

-+ * -+ *

This value has no effect on players, they will always use their real name.

-+ * -+ * @param customName the custom name to set -+ */ -+ void customName(final @Nullable net.kyori.adventure.text.Component customName); -+ // Paper end -+ - /** - * Gets the custom name on a mob or block. If there is no name this method - * will return null. -diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java -index 803fa0019869127ee8c7e4fb1777a59c43e66f8a..c65f0d6569c130b4920a9e71ad24af6427f1f030 100644 ---- a/src/main/java/org/bukkit/NamespacedKey.java -+++ b/src/main/java/org/bukkit/NamespacedKey.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; - * underscores, hyphens, and forward slashes. - * - */ --public final class NamespacedKey { -+public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key - - /** - * The namespace representing all inbuilt keys. -@@ -212,4 +212,24 @@ public final class NamespacedKey { - public static NamespacedKey fromString(@NotNull String key) { - return fromString(key, null); - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public String namespace() { -+ return this.getNamespace(); -+ } -+ -+ @NotNull -+ @Override -+ public String value() { -+ return this.getKey(); -+ } -+ -+ @NotNull -+ @Override -+ public String asString() { -+ return this.namespace + ':' + this.key; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a6b9e4f158583e5932bf8ca210d531857e9f5360..d9515a79dc7ed60c66960cd6c6bb4c108f206f3c 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -55,7 +55,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a server implementation. - */ --public interface Server extends PluginMessageRecipient { -+public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper - - /** - * Used for all administrative messages, such as an operator using a -@@ -229,7 +229,9 @@ public interface Server extends PluginMessageRecipient { - * - * @param message the message - * @return the number of players -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public int broadcastMessage(@NotNull String message); - - /** -@@ -703,8 +705,22 @@ public interface Server extends PluginMessageRecipient { - * @param permission the required permission {@link Permissible - * permissibles} must have to receive the broadcast - * @return number of message recipients -+ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} - */ -+ @Deprecated // Paper - public int broadcast(@NotNull String message, @NotNull String permission); -+ // Paper start -+ /** -+ * Broadcasts the specified message to every user with the given -+ * permission name. -+ * -+ * @param message message to broadcast -+ * @param permission the required permission {@link Permissible -+ * permissibles} must have to receive the broadcast -+ * @return number of message recipients -+ */ -+ int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission); -+ // Paper end - - /** - * Gets the player by the given name, regardless if they are offline or -@@ -869,6 +885,7 @@ public interface Server extends PluginMessageRecipient { - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type); - -+ // Paper start - /** - * Creates an empty inventory with the specified type and title. If the type - * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -@@ -894,6 +911,36 @@ public interface Server extends PluginMessageRecipient { - * @see InventoryType#isCreatable() - */ - @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title); -+ // Paper end -+ -+ /** -+ * Creates an empty inventory with the specified type and title. If the type -+ * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -+ * otherwise the new inventory has the normal size for its type.
-+ * It should be noted that some inventory types do not support titles and -+ * may not render with said titles on the Minecraft client. -+ *
-+ * {@link InventoryType#WORKBENCH} will not process crafting recipes if -+ * created with this method. Use -+ * {@link Player#openWorkbench(Location, boolean)} instead. -+ *
-+ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s -+ * for possible enchanting results. Use -+ * {@link Player#openEnchanting(Location, boolean)} instead. -+ * -+ * @param owner The holder of the inventory; can be null if there's no holder. -+ * @param type The type of inventory to create. -+ * @param title The title of the inventory, to be displayed when it is viewed. -+ * @return The new inventory. -+ * @throws IllegalArgumentException if the {@link InventoryType} cannot be -+ * viewed. -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} -+ * -+ * @see InventoryType#isCreatable() -+ */ -+ @Deprecated // Paper -+ @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); - - /** -@@ -908,6 +955,22 @@ public interface Server extends PluginMessageRecipient { - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the -+ * specified size and title. -+ * -+ * @param owner the holder of the inventory, or null to indicate no holder -+ * @param size a multiple of 9 as the size of inventory to create -+ * @param title the title of the inventory, displayed when inventory is -+ * viewed -+ * @return a new inventory -+ * @throws IllegalArgumentException if the size is not a multiple of 9 -+ */ -+ @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException; -+ // Paper end -+ - /** - * Creates an empty inventory of type {@link InventoryType#CHEST} with the - * specified size and title. -@@ -918,18 +981,32 @@ public interface Server extends PluginMessageRecipient { - * viewed - * @return a new inventory - * @throws IllegalArgumentException if the size is not a multiple of 9 -+ * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - @NotNull - Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Creates an empty merchant. -+ * -+ * @param title the title of the corresponding merchant inventory, displayed -+ * when the merchant inventory is viewed -+ * @return a new merchant -+ */ -+ @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title); -+ // Paper start - /** - * Creates an empty merchant. - * - * @param title the title of the corresponding merchant inventory, displayed - * when the merchant inventory is viewed - * @return a new merchant -+ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} - */ - @NotNull -+ @Deprecated // Paper - Merchant createMerchant(@Nullable String title); - - /** -@@ -986,20 +1063,41 @@ public interface Server extends PluginMessageRecipient { - */ - boolean isPrimaryThread(); - -+ // Paper start -+ /** -+ * Gets the message that is displayed on the server list. -+ * -+ * @return the server's MOTD -+ */ -+ @NotNull net.kyori.adventure.text.Component motd(); -+ // Paper end -+ - /** - * Gets the message that is displayed on the server list. - * - * @return the servers MOTD -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - String getMotd(); - -+ // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ @Nullable net.kyori.adventure.text.Component shutdownMessage(); -+ // Paper end - /** - * Gets the default message that is displayed when the server is stopped. - * - * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} - */ - @Nullable -+ @Deprecated // Paper - String getShutdownMessage(); - - /** -@@ -1368,7 +1466,9 @@ public interface Server extends PluginMessageRecipient { - * Sends the component to the player - * - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1377,7 +1477,9 @@ public interface Server extends PluginMessageRecipient { - * Sends an array of components as a single message to the player - * - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java -index 768f35c19c4557236bded5f4a85f48a2b2b2a9e6..d0ce64412276512cde133937a85a3340a70eea6d 100644 ---- a/src/main/java/org/bukkit/Sound.java -+++ b/src/main/java/org/bukkit/Sound.java -@@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; - * guarantee values will not be removed from this Enum. As such, you should not - * depend on the ordinal values of this class. - */ --public enum Sound implements Keyed { -+public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type - - AMBIENT_BASALT_DELTAS_ADDITIONS("ambient.basalt_deltas.additions"), - AMBIENT_BASALT_DELTAS_LOOP("ambient.basalt_deltas.loop"), -@@ -1016,4 +1016,12 @@ public enum Sound implements Keyed { - public NamespacedKey getKey() { - return key; - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.key.@org.checkerframework.checker.nullness.qual.NonNull Key key() { -+ return this.key; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 945b8b030d1b2a13afc0c4efad76997eb7bf00ba..207c656c0a11a3a630bc70491efcf433b2681e18 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -17,6 +17,13 @@ import org.bukkit.plugin.PluginDescriptionFile; - */ - @Deprecated - public interface UnsafeValues { -+ // Paper start -+ net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener(); -+ net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); -+ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer(); -+ net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer(); -+ net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer(); -+ // Paper end - - void reportTimings(); // Paper - Material toLegacy(Material material); -diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java -index efb97712cc9dc7c1e12a59f5b94e4f2ad7c6b7d8..3024468af4c073324e536c1cb26beffb1e09f3f4 100644 ---- a/src/main/java/org/bukkit/Warning.java -+++ b/src/main/java/org/bukkit/Warning.java -@@ -67,6 +67,7 @@ public @interface Warning { - * - */ - public boolean printFor(@Nullable Warning warning) { -+ if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper - if (this == DEFAULT) { - return warning == null || warning.value(); - } -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index bc4417d8ffa92a78f690bfa5705d3e42cdc11fd2..d3519fa5b99e2888a194c6382415537785fbeef0 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a world, which may contain entities, chunks and blocks - */ --public interface World extends PluginMessageRecipient, Metadatable { -+public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper - - /** - * Gets the {@link Block} at the given coordinates -@@ -640,6 +640,14 @@ public interface World extends PluginMessageRecipient, Metadatable { - @NotNull - public List getPlayers(); - -+ // Paper start -+ @NotNull -+ @Override -+ default Iterable audiences() { -+ return this.getPlayers(); -+ } -+ // Paper end -+ - /** - * Returns a list of entities within a bounding box centered around a - * Location. -diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java -index 7e3cf00e49c66023bf46c298ef46c00e8c3c2caf..6ea9b54d95d80070c01a612c0ce2ab37f0b4ad41 100644 ---- a/src/main/java/org/bukkit/block/Sign.java -+++ b/src/main/java/org/bukkit/block/Sign.java -@@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; - * Represents a captured state of either a SignPost or a WallSign. - */ - public interface Sign extends TileState, Colorable { -+ // Paper start -+ /** -+ * Gets all the lines of text currently on this sign. -+ * -+ * @return Array of Strings containing each line of text -+ */ -+ @NotNull -+ public java.util.List lines(); -+ -+ /** -+ * Gets the line of text at the specified index. -+ *

-+ * For example, getLine(0) will return the first line of text. -+ * -+ * @param index Line number to get the text from, starting at 0 -+ * @throws IndexOutOfBoundsException Thrown when the line does not exist -+ * @return Text on the given line -+ */ -+ @NotNull -+ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; -+ -+ /** -+ * Sets the line of text at the specified index. -+ *

-+ * For example, setLine(0, "Line One") will set the first line of text to -+ * "Line One". -+ * -+ * @param index Line number to set the text at, starting from 0 -+ * @param line New text to set at the specified index -+ * @throws IndexOutOfBoundsException If the index is out of the range 0..3 -+ */ -+ public void line(int index, @NotNull net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException; -+ // Paper end - - /** - * Gets all the lines of text currently on this sign. - * - * @return Array of Strings containing each line of text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines(); - - /** -@@ -24,8 +59,10 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to get the text from, starting at 0 - * @throws IndexOutOfBoundsException Thrown when the line does not exist - * @return Text on the given line -+ * @deprecated in favour of {@link #line(int)} - */ - @NotNull -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException; - - /** -@@ -37,7 +74,9 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to set the text at, starting from 0 - * @param line New text to set at the specified index - * @throws IndexOutOfBoundsException If the index is out of the range 0..3 -+ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; - - /** -diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java -index ac772bf349e0ffe9cab1df165d9460b387f2fe69..c88418c7aa19b4fecdfa9af3d18ff202a5dc5763 100644 ---- a/src/main/java/org/bukkit/command/CommandSender.java -+++ b/src/main/java/org/bukkit/command/CommandSender.java -@@ -6,12 +6,13 @@ import org.bukkit.permissions.Permissible; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - --public interface CommandSender extends Permissible { -+public interface CommandSender extends net.kyori.adventure.audience.Audience, Permissible { // Paper - - /** - * Sends this sender a message - * - * @param message Message to be displayed -+ * @see #sendMessage(net.kyori.adventure.text.Component) - */ - public void sendMessage(@NotNull String message); - -@@ -19,6 +20,7 @@ public interface CommandSender extends Permissible { - * Sends this sender multiple messages - * - * @param messages An array of messages to be displayed -+ * @see #sendMessage(net.kyori.adventure.text.Component) - */ - public void sendMessage(@NotNull String[] messages); - -@@ -27,6 +29,7 @@ public interface CommandSender extends Permissible { - * - * @param message Message to be displayed - * @param sender The sender of this message -+ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) - */ - public void sendMessage(@Nullable UUID sender, @NotNull String message); - -@@ -35,6 +38,7 @@ public interface CommandSender extends Permissible { - * - * @param messages An array of messages to be displayed - * @param sender The sender of this message -+ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) - */ - public void sendMessage(@Nullable UUID sender, @NotNull String[] messages); - -@@ -61,7 +65,9 @@ public interface CommandSender extends Permissible { - * Sends this sender a chat component. - * - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -70,7 +76,9 @@ public interface CommandSender extends Permissible { - * Sends an array of components as a single message to the sender. - * - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -80,7 +88,9 @@ public interface CommandSender extends Permissible { - * - * @param component the components to send - * @param sender the sender of the message -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -90,7 +100,9 @@ public interface CommandSender extends Permissible { - * - * @param components the components to send - * @param sender the sender of the message -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -99,4 +111,11 @@ public interface CommandSender extends Permissible { - @NotNull - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/ProxiedCommandSender.java b/src/main/java/org/bukkit/command/ProxiedCommandSender.java -index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302837f1ae3 100644 ---- a/src/main/java/org/bukkit/command/ProxiedCommandSender.java -+++ b/src/main/java/org/bukkit/command/ProxiedCommandSender.java -@@ -3,7 +3,7 @@ package org.bukkit.command; - - import org.jetbrains.annotations.NotNull; - --public interface ProxiedCommandSender extends CommandSender { -+public interface ProxiedCommandSender extends CommandSender, net.kyori.adventure.audience.ForwardingAudience.Single { // Paper - - /** - * Returns the CommandSender which triggered this proxied command -@@ -21,4 +21,16 @@ public interface ProxiedCommandSender extends CommandSender { - @NotNull - CommandSender getCallee(); - -+ // Paper start -+ @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { -+ net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type); -+ } -+ -+ @NotNull -+ @Override -+ default net.kyori.adventure.audience.Audience audience() { -+ return this.getCaller(); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index b833ef63fbe01271ceb2bd83a9eb4a84c9912761..8eb0497c81744874809ebc4bc2e28b128e66a926 100644 ---- a/src/main/java/org/bukkit/enchantments/Enchantment.java -+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java -@@ -294,6 +294,19 @@ public abstract class Enchantment implements Keyed { - * @return True if the enchantment may be applied, otherwise False - */ - public abstract boolean canEnchantItem(@NotNull ItemStack item); -+ // Paper start -+ /** -+ * Get the name of the enchantment with its applied level. -+ *

-+ * If the given {@code level} is either less than the {@link #getStartLevel()} or greater than the {@link #getMaxLevel()}, -+ * the level may not be shown in the numeral format one may otherwise expect. -+ *

-+ * -+ * @param level the level of the enchantment to show -+ * @return the name of the enchantment with {@code level} applied -+ */ -+ public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); -+ // Paper end - - @Override - public boolean equals(Object obj) { -diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13452322e0 100644 ---- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java -@@ -63,4 +63,11 @@ public class EnchantmentWrapper extends Enchantment { - public boolean conflictsWith(@NotNull Enchantment other) { - return getEnchantment().conflictsWith(other); - } -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return getEnchantment().displayName(level); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index b71530e94569f8ade829e655e3a89ec70215ea39..b21fe6c631d5a6cd52f133786270c8f5ad0dafc4 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a base entity in the world - */ --public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder { -+public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - - /** - * Gets the entity's current position -@@ -602,4 +602,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - @Override - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ @NotNull -+ @Override -+ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 586fd9ebd02039ebd2c071cbbbf60f24879f96b9..171e2663301f654258dbd772a57688b5a2f8469c 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -30,7 +30,28 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient { -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper -+ -+ // Paper start -+ @Override -+ default @NotNull net.kyori.adventure.identity.Identity identity() { -+ return net.kyori.adventure.identity.Identity.identity(this.getUniqueId()); -+ } -+ -+ /** -+ * Gets the "friendly" name to display of this player. -+ * -+ * @return the display name -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName(); -+ -+ /** -+ * Sets the "friendly" name to display of this player. -+ * -+ * @param displayName the display name to set -+ */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); -+ // Paper end - - /** - * Gets the "friendly" name to display of this player. This may include -@@ -40,7 +61,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * places defined by plugins. - * - * @return the friendly name -+ * @deprecated in favour of {@link #displayName()} - */ -+ @Deprecated // Paper - @NotNull - public String getDisplayName(); - -@@ -52,15 +75,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * places defined by plugins. - * - * @param name The new display name. -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setDisplayName(@Nullable String name); - -+ // Paper start -+ /** -+ * Sets the name that is shown on the in-game player list. -+ *

-+ * If the value is null, the name will be identical to {@link #getName()}. -+ * -+ * @param name new player list name -+ */ -+ void playerListName(@Nullable net.kyori.adventure.text.Component name); -+ -+ /** -+ * Gets the name that is shown on the in-game player list. -+ * -+ * @return the player list name -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListName(); -+ -+ /** -+ * Gets the currently displayed player list header for this player. -+ * -+ * @return player list header or null -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListHeader(); -+ -+ /** -+ * Gets the currently displayed player list footer for this player. -+ * -+ * @return player list footer or null -+ */ -+ @Nullable net.kyori.adventure.text.Component playerListFooter(); -+ // Paper end - /** - * Gets the name that is shown on the player list. - * - * @return the player list name -+ * @deprecated in favour of {@link #playerListName()} - */ - @NotNull -+ @Deprecated // Paper - public String getPlayerListName(); - - /** -@@ -69,14 +127,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * If the value is null, the name will be identical to {@link #getName()}. - * - * @param name new player list name -+ * @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListName(@Nullable String name); - - /** - * Gets the currently displayed player list header for this player. - * - * @return player list header or null -+ * @deprecated in favour of {@link #playerListHeader()} - */ -+ @Deprecated // Paper - @Nullable - public String getPlayerListHeader(); - -@@ -84,7 +146,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Gets the currently displayed player list footer for this player. - * - * @return player list header or null -+ * @deprecated in favour of {@link #playerListFooter()} - */ -+ @Deprecated // Paper - @Nullable - public String getPlayerListFooter(); - -@@ -92,14 +156,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Sets the currently displayed player list header for this player. - * - * @param header player list header, null for empty -+ * @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListHeader(@Nullable String header); - - /** - * Sets the currently displayed player list footer for this player. - * - * @param footer player list footer, null for empty -+ * @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListFooter(@Nullable String footer); - - /** -@@ -108,7 +176,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param header player list header, null for empty - * @param footer player list footer, null for empty -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); - - /** -@@ -146,9 +216,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Kicks player with custom kick message. - * - * @param message kick message -+ * @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void kickPlayer(@Nullable String message); - -+ // Paper start -+ /** -+ * Kicks player with custom kick message. -+ * -+ * @param message kick message -+ */ -+ void kick(final @Nullable net.kyori.adventure.text.Component message); -+ // Paper end -+ - /** - * Says a message (or runs a command). - * -@@ -448,6 +529,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - @Deprecated - public boolean sendChunkChange(@NotNull Location loc, int sx, int sy, int sz, @NotNull byte[] data); - -+ // Paper start - /** - * Send a sign change. This fakes a sign change packet for a user at - * a certain location. This will not actually change the world in any way. -@@ -463,6 +545,43 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 - */ -+ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines) throws IllegalArgumentException; -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

-+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @param dyeColor the color of the sign -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if dyeColor is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ */ -+ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; -+ // Paper end -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

-+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List)} -+ */ -+ @Deprecated // Paper - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; - - -@@ -482,7 +601,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if dyeColor is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List, org.bukkit.DyeColor)} - */ -+ @Deprecated // Paper - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; - - /** -@@ -1220,6 +1341,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public int getClientViewDistance(); - -+ // Paper start -+ /** -+ * Gets the player's current locale. -+ * -+ * @return the player's locale -+ */ -+ @NotNull java.util.Locale locale(); -+ // Paper end - /** - * Gets the player's estimated ping in milliseconds. - * -@@ -1245,8 +1374,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * they wish. - * - * @return the player's locale -+ * @deprecated in favour of {@link #locale()} - */ - @NotNull -+ @Deprecated // Paper - public String getLocale(); - - /** -@@ -1264,6 +1395,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void openBook(@NotNull ItemStack book); - -+ // Paper start -+ @NotNull -+ @Override -+ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); -+ } -+ // Paper end -+ - // Spigot start - public class Spigot extends Entity.Spigot { - -@@ -1318,11 +1457,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - throw new UnsupportedOperationException("Not supported yet."); - } - -+ @Deprecated // Paper - @Override - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } - -+ @Deprecated // Paper - @Override - public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); -@@ -1333,7 +1474,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param position the screen position - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1343,7 +1486,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * @param position the screen position - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1354,7 +1499,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param position the screen position - * @param sender the sender of the message - * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -1365,7 +1512,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param position the screen position - * @param sender the sender of the message - * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} - */ -+ @Deprecated // Paper - public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { - throw new UnsupportedOperationException("Not supported yet."); - -diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -index 63c80b4ee1f7adc8a9efc3b607993104b1991f90..91cab8b13d5bba34007f124838b32a1df58c5ac7 100644 ---- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java -@@ -32,7 +32,9 @@ public interface CommandMinecart extends Minecart { - * same as setting it to "@". - * - * @param name New name for this CommandMinecart. -+ * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setName(@Nullable String name); - - } -diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1f79f704abf339150df08900b8ea7da4cefef258 100644 ---- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java -+++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -@@ -16,12 +16,25 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; - private final Player player; -- private final String[] lines; -+ // Paper start -+ private final java.util.List adventure$lines; - -+ public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List adventure$lines) { -+ super(theBlock); -+ this.player = player; -+ this.adventure$lines = adventure$lines; -+ } -+ -+ @Deprecated // Paper end - public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) { - super(theBlock); - this.player = thePlayer; -- this.lines = theLines; -+ // Paper start -+ this.adventure$lines = new java.util.ArrayList<>(); -+ for (String theLine : theLines) { -+ this.adventure$lines.add(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(theLine)); -+ } -+ // Paper end - } - - /** -@@ -34,14 +47,52 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - return player; - } - -+ // Paper start -+ /** -+ * Gets all of the lines of text from the sign involved in this event. -+ * -+ * @return the String array for the sign's lines new text -+ */ -+ public @NotNull java.util.List lines() { -+ return this.adventure$lines; -+ } -+ -+ /** -+ * Gets a single line of text from the sign involved in this event. -+ * -+ * @param index index of the line to get -+ * @return the String containing the line of text associated with the -+ * provided index -+ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 -+ * or < 0} -+ */ -+ public @Nullable net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException { -+ return this.adventure$lines.get(index); -+ } -+ -+ /** -+ * Sets a single line for the sign involved in this event -+ * -+ * @param index index of the line to set -+ * @param line text to set -+ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 -+ * or < 0} -+ */ -+ public void line(int index, @Nullable net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException { -+ this.adventure$lines.set(index, line); -+ } -+ // Paper end -+ - /** - * Gets all of the lines of text from the sign involved in this event. - * - * @return the String array for the sign's lines new text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines() { -- return lines; -+ return adventure$lines.stream().map(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer()::serialize).toArray(String[]::new); // Paper - } - - /** -@@ -52,10 +103,12 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * provided index - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} -+ * @deprecated in favour of {@link #line(int)} - */ - @Nullable -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException { -- return lines[index]; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.adventure$lines.get(index)); // Paper - } - - /** -@@ -65,9 +118,11 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * @param line text to set - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} -+ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { -- lines[index] = line; -+ adventure$lines.set(index, line != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(line) : null); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -12,25 +12,48 @@ import org.jetbrains.annotations.Nullable; - public class PlayerDeathEvent extends EntityDeathEvent { - private int newExp = 0; - private String deathMessage = ""; -+ private net.kyori.adventure.text.Component adventure$deathMessage; // Paper - private int newLevel = 0; - private int newTotalExp = 0; - private boolean keepLevel = false; - private boolean keepInventory = false; -+ // Paper start -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { -+ this(player, drops, droppedExp, 0, adventure$deathMessage, null); -+ } -+ -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ this(player, drops, droppedExp, newExp, 0, 0, adventure$deathMessage, deathMessage); -+ } - -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ super(player, drops, droppedExp); -+ this.newExp = newExp; -+ this.newTotalExp = newTotalExp; -+ this.newLevel = newLevel; -+ this.deathMessage = deathMessage; -+ this.adventure$deathMessage = adventure$deathMessage; -+ } -+ // Paper end -+ -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, 0, deathMessage); - } - -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, newExp, 0, 0, deathMessage); - } - -+ @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; - this.newLevel = newLevel; - this.deathMessage = deathMessage; -+ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - - @NotNull -@@ -39,25 +62,55 @@ public class PlayerDeathEvent extends EntityDeathEvent { - return (Player) entity; - } - -+ // Paper start -+ /** -+ * Set the death message that will appear to everyone on the server. -+ * -+ * @param deathMessage Message to appear to other players on the server. -+ */ -+ public void deathMessage(@Nullable net.kyori.adventure.text.Component deathMessage) { -+ this.deathMessage = null; -+ this.adventure$deathMessage = deathMessage; -+ } -+ -+ /** -+ * Get the death message that will appear to everyone on the server. -+ * -+ * @return Message to appear to other players on the server. -+ */ -+ public @Nullable net.kyori.adventure.text.Component deathMessage() { -+ return this.adventure$deathMessage; -+ } -+ // Paper end -+ - /** - * Set the death message that will appear to everyone on the server. - * - * @param deathMessage Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setDeathMessage(@Nullable String deathMessage) { - this.deathMessage = deathMessage; -+ this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - - /** - * Get the death message that will appear to everyone on the server. - * - * @return Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getDeathMessage() { -- return deathMessage; -+ return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper - } -- -+ // Paper start //TODO: add translation API to drop String deathMessage in favor of just Adventure -+ private static String getDeathMessageString(net.kyori.adventure.text.Component component) { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(component); -+ } -+ // Paper end - /** - * Gets how much EXP the Player should have at respawn. - *

-diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java -index f1e9bc9bc797b7216336d3470e3c696a06f2b21a..090d22bd30f7947103771aaaf09a2398970ac337 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryType.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java -@@ -136,6 +136,18 @@ public enum InventoryType { - private final String title; - private final boolean isCreatable; - -+ // Paper start -+ private final net.kyori.adventure.text.Component defaultTitleComponent; -+ -+ /** -+ * Gets the inventory's default title. -+ * -+ * @return the inventory's default title -+ */ -+ public @NotNull net.kyori.adventure.text.Component defaultTitle() { -+ return defaultTitleComponent; -+ } -+ // Paper end - private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) { - this(defaultSize, defaultTitle, true); - } -@@ -144,6 +156,7 @@ public enum InventoryType { - size = defaultSize; - title = defaultTitle; - this.isCreatable = isCreatable; -+ this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure - } - - public int getDefaultSize() { -@@ -151,6 +164,7 @@ public enum InventoryType { - } - - @NotNull -+ @Deprecated // Paper - public String getDefaultTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -index 9c68c3f2d61500479f48b80264f625aaae2f3204..399afcd19fcb6acd24857ed6ab48cf0d105a01a3 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java -@@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull; - *

- * Care should be taken to check {@link #isAsynchronous()} and treat the event - * appropriately. -+ * -+ * @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead - */ -+@Deprecated // Paper -+@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper - public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index c8384da69af61e1970f254a3a9c206ee81d7a989..d3b4219a57fff4519ef8d803c333c854fafa7859 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; - public class AsyncPlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final String name; - private final InetAddress ipAddress; - private final UUID uniqueId; -@@ -27,7 +27,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { - super(true); - this.result = Result.ALLOWED; -- this.message = ""; -+ this.message = net.kyori.adventure.text.Component.empty(); // Paper - this.name = name; - this.ipAddress = ipAddress; - this.uniqueId = uniqueId; -@@ -79,6 +79,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.result = result == null ? null : Result.valueOf(result.name()); - } - -+ // Paper start - /** - * Gets the current kick message that will be used if getResult() != - * Result.ALLOWED -@@ -86,7 +87,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - * @return Current kick message - */ - @NotNull -- public String getKickMessage() { -+ public net.kyori.adventure.text.Component kickMessage() { - return message; - } - -@@ -95,16 +96,66 @@ public class AsyncPlayerPreLoginEvent extends Event { - * - * @param message New kick message - */ -- public void setKickMessage(@NotNull final String message) { -+ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { -+ this.message = message; -+ } -+ -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; - this.message = message; - } - -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ * @deprecated This method uses a deprecated enum from {@link -+ * PlayerPreLoginEvent} -+ * @see #disallow(Result, String) -+ */ -+ @Deprecated -+ public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result == null ? null : Result.valueOf(result.name()); -+ this.message = message; -+ } -+ // Paper end -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} -+ */ -+ @NotNull -+ @Deprecated // Paper -+ public String getKickMessage() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ public void setKickMessage(@NotNull final String message) { -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -112,10 +163,12 @@ public class AsyncPlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -@@ -130,7 +183,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - @Deprecated - public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) { - this.result = result == null ? null : Result.valueOf(result.name()); -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -index 8ea56aac752544f798728b429e7152afbee497e4..213837794c603cb9f152f917941b912326a08030 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java -@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; - * Listening to this event forces chat to wait for the main thread which - * causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged - * alternative for thread safe implementations. -+ * @deprecated use {@link io.papermc.paper.event.player.ChatEvent} instead - */ - @Deprecated - @Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") -diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java -index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a1290af3fd6d 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java -@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event { - player = who; - } - -- PlayerEvent(@NotNull final Player who, boolean async) { -+ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public - super(async); - player = who; - -diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -index d06684aba7688ce06777dbd837a46856a9d7767f..851a189d42e271679abc78f95049d8badf7a2b64 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -@@ -10,30 +10,60 @@ import org.jetbrains.annotations.Nullable; - */ - public class PlayerJoinEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); -- private String joinMessage; -+ // Paper start -+ private net.kyori.adventure.text.Component joinMessage; -+ public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) { -+ super(playerJoined); -+ this.joinMessage = joinMessage; -+ } - -+ @Deprecated // Paper end - public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { - super(playerJoined); -+ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper end -+ } -+ -+ // Paper start -+ /** -+ * Gets the join message to send to all online players -+ * -+ * @return string join message. Can be null -+ */ -+ public @Nullable net.kyori.adventure.text.Component joinMessage() { -+ return this.joinMessage; -+ } -+ -+ /** -+ * Sets the join message to send to all online players -+ * -+ * @param joinMessage join message. If null, no message will be sent -+ */ -+ public void joinMessage(@Nullable net.kyori.adventure.text.Component joinMessage) { - this.joinMessage = joinMessage; - } -+ // Paper end - - /** - * Gets the join message to send to all online players - * - * @return string join message. Can be null -+ * @deprecated in favour of {@link #joinMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getJoinMessage() { -- return joinMessage; -+ return this.joinMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.joinMessage); // Paper - } - - /** - * Sets the join message to send to all online players - * - * @param joinMessage join message. If null, no message will be sent -+ * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setJoinMessage(@Nullable String joinMessage) { -- this.joinMessage = joinMessage; -+ this.joinMessage = joinMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(joinMessage) : null; // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index 14c337f15fc804f52e52cb0a185aad38d89303a8..5c0efe74237dbe6803ce023fde99682ff70d1a92 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -@@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull; - */ - public class PlayerKickEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); -- private String leaveMessage; -- private String kickReason; -+ private net.kyori.adventure.text.Component leaveMessage; // Paper -+ private net.kyori.adventure.text.Component kickReason; // Paper - private Boolean cancel; - -+ @Deprecated // Paper - public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) { -+ super(playerKicked); -+ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper -+ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper -+ this.cancel = false; -+ } -+ // Paper start -+ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { - super(playerKicked); - this.kickReason = kickReason; - this.leaveMessage = leaveMessage; - this.cancel = false; - } - -+ /** -+ * Gets the leave message send to all online players -+ * -+ * @return string kick reason -+ */ -+ public @NotNull net.kyori.adventure.text.Component leaveMessage() { -+ return this.leaveMessage; -+ } -+ -+ /** -+ * Sets the leave message send to all online players -+ * -+ * @param leaveMessage leave message -+ */ -+ public void leaveMessage(@NotNull net.kyori.adventure.text.Component leaveMessage) { -+ this.leaveMessage = leaveMessage; -+ } -+ - /** - * Gets the reason why the player is getting kicked - * - * @return string kick reason - */ -+ public @NotNull net.kyori.adventure.text.Component reason() { -+ return this.kickReason; -+ } -+ -+ /** -+ * Sets the reason why the player is getting kicked -+ * -+ * @param kickReason kick reason -+ */ -+ public void reason(@NotNull net.kyori.adventure.text.Component kickReason) { -+ this.kickReason = kickReason; -+ } -+ // Paper end -+ -+ /** -+ * Gets the reason why the player is getting kicked -+ * -+ * @return string kick reason -+ * @deprecated in favour of {@link #reason()} -+ */ - @NotNull -+ @Deprecated // Paper - public String getReason() { -- return kickReason; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.kickReason); // Paper - } - - /** - * Gets the leave message send to all online players - * - * @return string kick reason -+ * @deprecated in favour of {@link #leaveMessage()} - */ - @NotNull -+ @Deprecated // Paper - public String getLeaveMessage() { -- return leaveMessage; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.leaveMessage); // Paper - } - - @Override -@@ -55,18 +104,22 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { - * Sets the reason why the player is getting kicked - * - * @param kickReason kick reason -+ * @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setReason(@NotNull String kickReason) { -- this.kickReason = kickReason; -+ this.kickReason = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickReason); // Paper - } - - /** - * Sets the leave message send to all online players - * - * @param leaveMessage leave message -+ * @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setLeaveMessage(@NotNull String leaveMessage) { -- this.leaveMessage = leaveMessage; -+ this.leaveMessage = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(leaveMessage); // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -index 1db386bb701cb6974daedc6bb5b93a3afbc42100..84521186404b8e43c81a2f9513dce2be40d27840 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java -@@ -12,18 +12,32 @@ public class PlayerLocaleChangeEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); - // - private final String locale; -+ // Paper start -+ private final java.util.Locale adventure$locale; -+ /** -+ * @see Player#getLocale() -+ * -+ * @return the player's new locale -+ */ -+ public @NotNull java.util.Locale locale() { -+ return this.adventure$locale; -+ } -+ // Paper end - - public PlayerLocaleChangeEvent(@NotNull Player who, @NotNull String locale) { - super(who); - this.locale = locale; -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(locale); // Paper - } - - /** - * @see Player#getLocale() - * - * @return the player's new locale -+ * @deprecated in favour of {@link #locale()} - */ - @NotNull -+ @Deprecated // Paper - public String getLocale() { - return locale; - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..75cc54739ef841cd90568d74927d6002d4cfa7e0 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -@@ -17,7 +17,7 @@ public class PlayerLoginEvent extends PlayerEvent { - private final InetAddress address; - private final String hostname; - private Result result = Result.ALLOWED; -- private String message = ""; -+ private net.kyori.adventure.text.Component message = net.kyori.adventure.text.Component.empty(); - private final InetAddress realAddress; // Spigot - - /** -@@ -53,12 +53,52 @@ public class PlayerLoginEvent extends PlayerEvent { - * @param result The result status for this event - * @param message The message to be displayed if result denies login - * @param realAddress the actual, unspoofed connecting address -+ * @deprecated in favour of {@link #PlayerLoginEvent(Player, String, InetAddress, Result, net.kyori.adventure.text.Component, InetAddress)} - */ -+ @Deprecated // Paper - public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) { // Spigot - this(player, hostname, address, realAddress); // Spigot - this.result = result; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ -+ // Paper start -+ /** -+ * This constructor pre-configures the event with a result and message -+ * -+ * @param player The {@link Player} for this event -+ * @param hostname The hostname that was used to connect to the server -+ * @param address The address the player used to connect, provided for -+ * timing issues -+ * @param result The result status for this event -+ * @param message The message to be displayed if result denies login -+ * @param realAddress the actual, unspoofed connecting address -+ */ -+ public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) { // Spigot -+ this(player, hostname, address, realAddress); // Spigot -+ this.result = result; -+ this.message = message; -+ } -+ -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ */ -+ public @NotNull net.kyori.adventure.text.Component kickMessage() { -+ return this.message; -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ */ -+ public void kickMessage(@NotNull net.kyori.adventure.text.Component message) { - this.message = message; - } -+ // Paper end - - // Spigot start - /** -@@ -96,19 +136,23 @@ public class PlayerLoginEvent extends PlayerEvent { - * Result.ALLOWED - * - * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} - */ - @NotNull -+ @Deprecated // Paper - public String getKickMessage() { -- return message; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper - } - - /** - * Sets the kick message to display if getResult() != Result.ALLOWED - * - * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setKickMessage(@NotNull final String message) { -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -@@ -127,7 +171,7 @@ public class PlayerLoginEvent extends PlayerEvent { - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -135,8 +179,21 @@ public class PlayerLoginEvent extends PlayerEvent { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper start - public void disallow(@NotNull final Result result, @NotNull final String message) { -+ this.result = result; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); -+ } -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ // Paper end - this.result = result; - this.message = message; - } -diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -index fb066251f793ec3b41bfc075b9478901b15ee549..123979ed64939d615b061f91c19c630e1e1db8c7 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; - public class PlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final String name; - private final InetAddress ipAddress; - private final UUID uniqueId; -@@ -31,7 +31,7 @@ public class PlayerPreLoginEvent extends Event { - - public PlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { - this.result = Result.ALLOWED; -- this.message = ""; -+ this.message = net.kyori.adventure.text.Component.empty(); // Paper - this.name = name; - this.ipAddress = ipAddress; - this.uniqueId = uniqueId; -@@ -56,6 +56,7 @@ public class PlayerPreLoginEvent extends Event { - this.result = result; - } - -+ // Paper start - /** - * Gets the current kick message that will be used if getResult() != - * Result.ALLOWED -@@ -63,7 +64,7 @@ public class PlayerPreLoginEvent extends Event { - * @return Current kick message - */ - @NotNull -- public String getKickMessage() { -+ public net.kyori.adventure.text.Component kickMessage() { - return message; - } - -@@ -72,16 +73,51 @@ public class PlayerPreLoginEvent extends Event { - * - * @param message New kick message - */ -- public void setKickMessage(@NotNull final String message) { -+ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { - this.message = message; - } - -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ -+ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; -+ this.message = message; -+ } -+ // Paper end -+ /** -+ * Gets the current kick message that will be used if getResult() != -+ * Result.ALLOWED -+ * -+ * @return Current kick message -+ * @deprecated in favour of {@link #kickMessage()} -+ */ -+ @Deprecated // Paper -+ @NotNull -+ public String getKickMessage() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper -+ } -+ -+ /** -+ * Sets the kick message to display if getResult() != Result.ALLOWED -+ * -+ * @param message New kick message -+ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated // Paper -+ public void setKickMessage(@NotNull final String message) { -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper -+ } -+ - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; -+ message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -89,10 +125,12 @@ public class PlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user -+ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index d70c25f404e994766a9ebce89a917c8d0719777c..849e8f10dd77e9fb46aab17752b8f1ff79e9d42e 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -10,30 +10,59 @@ import org.jetbrains.annotations.Nullable; - */ - public class PlayerQuitEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); -- private String quitMessage; -+ private net.kyori.adventure.text.Component quitMessage; // Paper - -+ @Deprecated // Paper - public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { - super(who); -+ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper -+ } -+ // Paper start -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { -+ super(who); -+ this.quitMessage = quitMessage; -+ } -+ -+ /** -+ * Gets the quit message to send to all online players -+ * -+ * @return string quit message -+ */ -+ public @Nullable net.kyori.adventure.text.Component quitMessage() { -+ return quitMessage; -+ } -+ -+ /** -+ * Sets the quit message to send to all online players -+ * -+ * @param quitMessage quit message -+ */ -+ public void quitMessage(@Nullable net.kyori.adventure.text.Component quitMessage) { - this.quitMessage = quitMessage; - } -+ // Paper end - - /** - * Gets the quit message to send to all online players - * - * @return string quit message -+ * @deprecated in favour of {@link #quitMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getQuitMessage() { -- return quitMessage; -+ return this.quitMessage == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.quitMessage); // Paper - } - - /** - * Sets the quit message to send to all online players - * - * @param quitMessage quit message -+ * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setQuitMessage(@Nullable String quitMessage) { -- this.quitMessage = quitMessage; -+ this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper - } - - @NotNull -diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..4f8c85222c7bd33217c7db0ff5f47bf397f8f3e5 100644 ---- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -+++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -@@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; - public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); -- private String message; -+ private net.kyori.adventure.text.Component message; // Paper - private final Set recipients; - private boolean cancelled = false; - -@@ -27,29 +27,66 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { - this(false, message, recipients); - } - -+ @Deprecated // Paper - public BroadcastMessageEvent(boolean isAsync, @NotNull String message, @NotNull Set recipients) { -+ // Paper start -+ super(isAsync); -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); -+ this.recipients = recipients; -+ } -+ -+ @Deprecated -+ public BroadcastMessageEvent(@NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { -+ this(false, message, recipients); -+ } -+ -+ public BroadcastMessageEvent(boolean isAsync, @NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { -+ // Paper end - super(isAsync); - this.message = message; - this.recipients = recipients; - } -+ // Paper start -+ /** -+ * Get the broadcast message. -+ * -+ * @return Message to broadcast -+ */ -+ public @NotNull net.kyori.adventure.text.Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Set the broadcast message. -+ * -+ * @param message New message to broadcast -+ */ -+ public void message(@NotNull net.kyori.adventure.text.Component message) { -+ this.message = message; -+ } -+ // Paper end - - /** - * Get the message to broadcast. - * - * @return Message to broadcast -+ * @deprecated in favour of {@link #message()} - */ - @NotNull -+ @Deprecated // Paper - public String getMessage() { -- return message; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); // Paper - } - - /** - * Set the message to broadcast. - * - * @param message New message to broadcast -+ * @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setMessage(@NotNull String message) { -- this.message = message; -+ this.message = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -index 7a2a58bac8e721c3f0c64f69f77be07a51f76d58..ede5a41bc071a9c9cea369b227b37a50222f295d 100644 ---- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -+++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -@@ -17,15 +17,16 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - private static final int MAGIC_PLAYER_COUNT = Integer.MIN_VALUE; - private static final HandlerList handlers = new HandlerList(); - private final InetAddress address; -- private String motd; -+ private net.kyori.adventure.text.Component motd; // Paper - private final int numPlayers; - private int maxPlayers; - -+ @Deprecated // Paper - public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int numPlayers, final int maxPlayers) { - super(true); - Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); - this.address = address; -- this.motd = motd; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper - this.numPlayers = numPlayers; - this.maxPlayers = maxPlayers; - } -@@ -38,14 +39,58 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * @param address the address of the pinger - * @param motd the message of the day - * @param maxPlayers the max number of players -+ * @deprecated in favour of {@link #ServerListPingEvent(java.net.InetAddress, net.kyori.adventure.text.Component, int)} - */ -+ @Deprecated // Paper - protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) { -+ super(true); -+ this.numPlayers = MAGIC_PLAYER_COUNT; -+ this.address = address; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper -+ this.maxPlayers = maxPlayers; -+ } -+ // Paper start -+ public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) { -+ super(true); -+ Validate.isTrue(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); -+ this.address = address; -+ this.motd = motd; -+ this.numPlayers = numPlayers; -+ this.maxPlayers = maxPlayers; -+ } -+ /** -+ * This constructor is intended for implementations that provide the -+ * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} -+ * count. -+ * -+ * @param address the address of the pinger -+ * @param motd the message of the day -+ * @param maxPlayers the max number of players -+ */ -+ protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int maxPlayers) { - super(true); - this.numPlayers = MAGIC_PLAYER_COUNT; - this.address = address; - this.motd = motd; - this.maxPlayers = maxPlayers; - } -+ /** -+ * Get the message of the day message. -+ * -+ * @return the message of the day -+ */ -+ public @NotNull net.kyori.adventure.text.Component motd() { -+ return motd; -+ } -+ /** -+ * Change the message of the day message. -+ * -+ * @param motd the message of the day -+ */ -+ public void motd(@NotNull net.kyori.adventure.text.Component motd) { -+ this.motd = motd; -+ } -+ // Paper end - - /** - * Get the address the ping is coming from. -@@ -61,19 +106,23 @@ public class ServerListPingEvent extends ServerEvent implements Iterable - * Get the message of the day message. - * - * @return the message of the day -+ * @deprecated in favour of {@link #motd()} - */ - @NotNull -+ @Deprecated // Paper - public String getMotd() { -- return motd; -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.motd); // Paper - } - - /** - * Change the message of the day message. - * - * @param motd the message of the day -+ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setMotd(@NotNull String motd) { -- this.motd = motd; -+ this.motd = org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(motd); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 14346d83bc99581b18e53d19af03708c0bf22cf7..664de64b020cf9090a2fbee0afe2bfaf150adc3c 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -446,11 +446,25 @@ public abstract class InventoryView { - return getPlayer().setWindowProperty(prop, value); - } - -+ // Paper start - /** - * Get the title of this inventory window. - * - * @return The title. - */ - @NotNull -+ public /*abstract*/ net.kyori.adventure.text.Component title() { -+ return org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(this.getTitle()); -+ } -+ // Paper end -+ -+ /** -+ * Get the title of this inventory window. -+ * -+ * @return The title. -+ * @deprecated in favour of {@link #title()} -+ */ -+ @Deprecated // Paper -+ @NotNull - public abstract String getTitle(); - } -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 4ff149fd98895dd8ba45939a37c223b1f8d7281f..6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -141,4 +141,24 @@ public interface ItemFactory { - @Deprecated - @NotNull - Material updateMaterial(@NotNull final ItemMeta meta, @NotNull final Material material) throws IllegalArgumentException; -+ -+ // Paper start -+ /** -+ * Creates a hover event for the given item. -+ * -+ * @param item The item -+ * @return A hover event -+ */ -+ @NotNull -+ net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator op); -+ -+ /** -+ * Get the formatted display name of the {@link ItemStack}. -+ * -+ * @param itemStack the {@link ItemStack} -+ * @return display name of the {@link ItemStack} -+ */ -+ @NotNull -+ net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index f70a6a22b85ff0da76e67e9b223ad4e0b020b5c4..a15abec467bac70116a6fc21a300d4930b909f15 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; - * use this class to encapsulate Materials for which {@link Material#isItem()} - * returns false. - */ --public class ItemStack implements Cloneable, ConfigurationSerializable { -+public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyori.adventure.text.event.HoverEventSource { // Paper - private Material type = Material.AIR; - private int amount = 0; - private MaterialData data = null; -@@ -595,4 +595,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable { - - return true; - } -+ -+ // Paper start -+ @NotNull -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { -+ return org.bukkit.Bukkit.getServer().getItemFactory().asHoverEvent(this, op); -+ } -+ -+ /** -+ * Get the formatted display name of the {@link ItemStack}. -+ * -+ * @return display name of the {@link ItemStack} -+ */ -+ public @NotNull net.kyori.adventure.text.Component displayName() { -+ return Bukkit.getServer().getItemFactory().displayName(this); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -index 94852d50e88d0594b84b581cd627174043629995..fdbd32c4bb6428f2dde484ecb53acdaaba2a0d18 100644 ---- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -@@ -1,8 +1,11 @@ - package org.bukkit.inventory.meta; - - import java.util.List; -+ -+import net.kyori.adventure.inventory.Book; - import net.md_5.bungee.api.chat.BaseComponent; - import org.bukkit.Material; -+import org.checkerframework.checker.nullness.qual.NonNull; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -10,7 +13,7 @@ import org.jetbrains.annotations.Nullable; - * Represents a book ({@link Material#WRITABLE_BOOK} or {@link - * Material#WRITTEN_BOOK}) that can have a title, an author, and pages. - */ --public interface BookMeta extends ItemMeta { -+public interface BookMeta extends ItemMeta, net.kyori.adventure.inventory.Book { // Paper - - /** - * Represents the generation (or level of copying) of a written book -@@ -119,6 +122,116 @@ public interface BookMeta extends ItemMeta { - */ - boolean hasPages(); - -+ // Paper start -+ /** -+ * Gets the title of the book. -+ *

-+ * Plugins should check that hasTitle() returns true before calling this -+ * method. -+ * -+ * @return the title of the book -+ */ -+ @Nullable -+ @Override -+ net.kyori.adventure.text.Component title(); -+ -+ /** -+ * Sets the title of the book. -+ *

-+ * Limited to 32 characters. Removes title when given null. -+ * -+ * @param title the title to set -+ * @return true if the title was successfully set -+ */ -+ @NotNull -+ @Override -+ BookMeta title(@Nullable net.kyori.adventure.text.Component title); -+ -+ /** -+ * Gets the author of the book. -+ *

-+ * Plugins should check that hasAuthor() returns true before calling this -+ * method. -+ * -+ * @return the author of the book -+ */ -+ @Nullable -+ @Override -+ net.kyori.adventure.text.Component author(); -+ -+ /** -+ * Sets the author of the book. Removes author when given null. -+ * -+ * @param author the author to set -+ */ -+ @NotNull -+ @Override -+ BookMeta author(@Nullable net.kyori.adventure.text.Component author); -+ /** -+ * Gets the specified page in the book. The page must exist. -+ *

-+ * Pages are 1-indexed. -+ * -+ * @param page the page number to get, in range [1, getPageCount()] -+ * @return the page from the book -+ */ -+ @NotNull net.kyori.adventure.text.Component page(int page); -+ -+ /** -+ * Sets the specified page in the book. Pages of the book must be -+ * contiguous. -+ *

-+ * The data can be up to 256 characters in length, additional characters -+ * are truncated. -+ *

-+ * Pages are 1-indexed. -+ * -+ * @param page the page number to set, in range [1, getPageCount()] -+ * @param data the data to set for that page -+ */ -+ void page(int page, @NotNull net.kyori.adventure.text.Component data); -+ -+ /** -+ * Adds new pages to the end of the book. Up to a maximum of 50 pages with -+ * 256 characters per page. -+ * -+ * @param pages A list of strings, each being a page -+ */ -+ void addPages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ interface BookMetaBuilder extends Builder { -+ -+ @NotNull -+ @Override -+ BookMetaBuilder title(@Nullable net.kyori.adventure.text.Component title); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder author(@Nullable net.kyori.adventure.text.Component author); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder addPage(@NotNull net.kyori.adventure.text.Component page); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull java.util.Collection pages); -+ -+ @NotNull -+ @Override -+ BookMeta build(); -+ } -+ -+ @Override -+ @NonNull -+ BookMetaBuilder toBuilder(); -+ -+ // Paper end -+ - /** - * Gets the specified page in the book. The given page must exist. - *

-@@ -126,8 +239,10 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to get, in range [1, getPageCount()] - * @return the page from the book -+ * @deprecated in favour of {@link #page(int)} - */ - @NotNull -+ @Deprecated // Paper - String getPage(int page); - - /** -@@ -141,15 +256,19 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to set, in range [1, getPageCount()] - * @param data the data to set for that page -+ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setPage(int page, @NotNull String data); - - /** - * Gets all the pages in the book. - * - * @return list of all the pages in the book -+ * @deprecated in favour of {@link #pages()} - */ - @NotNull -+ @Deprecated // Paper - List getPages(); - - /** -@@ -157,7 +276,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 100 pages with 256 characters per page. - * - * @param pages A list of pages to set the book to use -+ * @deprecated in favour of {@link #pages(List)} - */ -+ @Deprecated // Paper - void setPages(@NotNull List pages); - - /** -@@ -165,7 +286,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of strings, each being a page -+ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - void setPages(@NotNull String... pages); - - /** -@@ -173,7 +296,9 @@ public interface BookMeta extends ItemMeta { - * 256 characters per page. - * - * @param pages A list of strings, each being a page -+ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - void addPage(@NotNull String... pages); - - /** -@@ -195,8 +320,10 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to get - * @return the page from the book -+ * @deprecated in favour of {@link #page(int)} - */ - @NotNull -+ @Deprecated // Paper - public BaseComponent[] getPage(int page) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -210,7 +337,9 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to set - * @param data the data to set for that page -+ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setPage(int page, @Nullable BaseComponent... data) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -219,8 +348,10 @@ public interface BookMeta extends ItemMeta { - * Gets all the pages in the book. - * - * @return list of all the pages in the book -+ * @deprecated in favour of {@link #pages()} - */ - @NotNull -+ @Deprecated // Paper - public List getPages() { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -230,7 +361,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of pages to set the book to use -+ * @deprecated in favour of {@link #pages(java.util.List)} - */ -+ @Deprecated // Paper - public void setPages(@NotNull List pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -240,7 +373,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of component arrays, each being a page -+ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - public void setPages(@NotNull BaseComponent[]... pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -@@ -250,7 +385,9 @@ public interface BookMeta extends ItemMeta { - * with 256 characters per page. - * - * @param pages A list of component arrays, each being a page -+ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - public void addPage(@NotNull BaseComponent[]... pages) { - throw new UnsupportedOperationException("Not supported yet."); - } -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index f2e9f2753ec92aa4a3e3f06ca6053bd70b9091d7..1c362636c56db0e6c118171ba367c43c4f7cff33 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -31,6 +31,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - */ - boolean hasDisplayName(); - -+ // Paper start -+ /** -+ * Gets the display name. -+ * -+ *

Plugins should check that {@link #hasDisplayName()} returns true before calling this method.

-+ * -+ * @return the display name -+ */ -+ @Nullable net.kyori.adventure.text.Component displayName(); -+ -+ /** -+ * Sets the display name. -+ * -+ * @param displayName the display name to set -+ */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); -+ // Paper end -+ - /** - * Gets the display name that is set. - *

-@@ -38,7 +56,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * before calling this method. - * - * @return the display name that is set -+ * @deprecated in favour of {@link #displayName()} - */ -+ @Deprecated // Paper - @NotNull - String getDisplayName(); - -@@ -46,7 +66,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * Sets the display name. - * - * @param name the name to set -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@Nullable String name); - - /** -@@ -81,6 +103,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - */ - boolean hasLore(); - -+ // Paper start -+ /** -+ * Gets the lore. -+ * -+ *

Plugins should check that {@link #hasLore()} returns true before calling this method.

-+ * -+ * @return the display name -+ */ -+ @Nullable List lore(); -+ -+ /** -+ * Sets the lore. -+ * -+ * @param lore the lore to set -+ */ -+ void lore(final @Nullable List lore); -+ // Paper end -+ - /** - * Gets the lore that is set. - *

-@@ -88,7 +128,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * calling this method. - * - * @return a list of lore that is set -+ * @deprecated in favour of {@link #lore()} - */ -+ @Deprecated // Paper - @Nullable - List getLore(); - -@@ -97,7 +139,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - * Removes lore when given null. - * - * @param lore the lore that will be set -+ * @deprecated in favour of {@link #lore(List)} - */ -+ @Deprecated // Paper - void setLore(@Nullable List lore); - - /** -diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java -index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ed0bc2024a0bb85837e25f75ae89d1fe257b2e60 100644 ---- a/src/main/java/org/bukkit/map/MapCursor.java -+++ b/src/main/java/org/bukkit/map/MapCursor.java -@@ -10,7 +10,7 @@ public final class MapCursor { - private byte x, y; - private byte direction, type; - private boolean visible; -- private String caption; -+ private net.kyori.adventure.text.Component caption; // Paper - - /** - * Initialize the map cursor. -@@ -24,7 +24,7 @@ public final class MapCursor { - */ - @Deprecated - public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) { -- this(x, y, direction, type, visible, null); -+ this(x, y, direction, type, visible, (String) null); // Paper - } - - /** -@@ -37,7 +37,7 @@ public final class MapCursor { - * @param visible Whether the cursor is visible by default. - */ - public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) { -- this(x, y, direction, type, visible, null); -+ this(x, y, direction, type, visible, (String) null); // Paper - } - - /** -@@ -49,7 +49,7 @@ public final class MapCursor { - * @param type The type (color/style) of the map cursor. - * @param visible Whether the cursor is visible by default. - * @param caption cursor caption -- * @deprecated Magic value -+ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, byte, boolean, net.kyori.adventure.text.Component)} - */ - @Deprecated - public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { -@@ -58,8 +58,42 @@ public final class MapCursor { - setDirection(direction); - setRawType(type); - this.visible = visible; -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } -+ // Paper start -+ /** -+ * Initialize the map cursor. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible by default. -+ * @param caption cursor caption -+ * @deprecated Magic value -+ */ -+ @Deprecated -+ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ this.x = x; this.y = y; this.visible = visible; this.caption = caption; -+ setDirection(direction); -+ setRawType(type); -+ } -+ /** -+ * Initialize the map cursor. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible by default. -+ * @param caption cursor caption -+ */ -+ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ this.x = x; this.y = y; this.visible = visible; this.caption = caption; -+ setDirection(direction); -+ setType(type); -+ } -+ // Paper end - - /** - * Initialize the map cursor. -@@ -77,7 +111,7 @@ public final class MapCursor { - setDirection(direction); - setType(type); - this.visible = visible; -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } - - /** -@@ -200,23 +234,45 @@ public final class MapCursor { - this.visible = visible; - } - -+ // Paper start -+ /** -+ * Gets the caption on this cursor. -+ * -+ * @return caption -+ */ -+ public @Nullable net.kyori.adventure.text.Component caption() { -+ return this.caption; -+ } -+ /** -+ * Sets the caption on this cursor. -+ * -+ * @param caption new caption -+ */ -+ public void caption(@Nullable net.kyori.adventure.text.Component caption) { -+ this.caption = caption; -+ } -+ // Paper end - /** - * Gets the caption on this cursor. - * - * @return caption -+ * @deprecated in favour of {@link #caption()} - */ - @Nullable -+ @Deprecated // Paper - public String getCaption() { -- return caption; -+ return this.caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.caption); // Paper - } - - /** - * Sets the caption on this cursor. - * - * @param caption new caption -+ * @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - public void setCaption(@Nullable String caption) { -- this.caption = caption; -+ this.caption = caption == null ? null : org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(caption); // Paper - } - - /** -diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java -index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..01dec2c877df58c9dc22445e8b1f9ce2e53066da 100644 ---- a/src/main/java/org/bukkit/map/MapCursorCollection.java -+++ b/src/main/java/org/bukkit/map/MapCursorCollection.java -@@ -117,4 +117,22 @@ public final class MapCursorCollection { - public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable String caption) { - return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); - } -+ // Paper start -+ /** -+ * Add a cursor to the collection. -+ * -+ * @param x The x coordinate, from -128 to 127. -+ * @param y The y coordinate, from -128 to 127. -+ * @param direction The facing of the cursor, from 0 to 15. -+ * @param type The type (color/style) of the map cursor. -+ * @param visible Whether the cursor is visible. -+ * @param caption banner caption -+ * @return The newly added MapCursor. -+ * @deprecated Magic value -+ */ -+ @Deprecated -+ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java -index f5cbf6df32ef169cf0f2266f7c6e9c4f771ccb7d..58bddb11fd534e7c33a4ffd7b72b055ba92c767a 100644 ---- a/src/main/java/org/bukkit/scoreboard/Objective.java -+++ b/src/main/java/org/bukkit/scoreboard/Objective.java -@@ -19,14 +19,35 @@ public interface Objective { - */ - @NotNull - String getName() throws IllegalStateException; -+ // Paper start -+ /** -+ * Gets the name displayed to players for this objective -+ * -+ * @return this objective's display name -+ * @throws IllegalStateException if this objective has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; -+ /** -+ * Sets the name displayed to players for this objective. -+ * -+ * @param displayName Display name to set -+ * @throws IllegalStateException if this objective has been unregistered -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; -+ // Paper end - - /** - * Gets the name displayed to players for this objective - * - * @return this objective's display name - * @throws IllegalStateException if this objective has been unregistered -+ * @deprecated in favour of {@link #displayName()} - */ - @NotNull -+ @Deprecated // Paper - String getDisplayName() throws IllegalStateException; - - /** -@@ -37,7 +58,9 @@ public interface Objective { - * @throws IllegalArgumentException if displayName is null - * @throws IllegalArgumentException if displayName is longer than 128 - * characters. -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -index 4bfaaea78c9b6aa5d392629aa943d26dbe6a7d4a..f09ff32cc3ffc16af379a378b1948991435393e8 100644 ---- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java -+++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -@@ -27,6 +27,48 @@ public interface Scoreboard { - @Deprecated - @NotNull - Objective registerNewObjective(@NotNull String name, @NotNull String criteria) throws IllegalArgumentException; -+ // Paper start -+ /** -+ * Registers an Objective on this Scoreboard -+ * -+ * @param name Name of the Objective -+ * @param criteria Criteria for the Objective -+ * @param displayName Name displayed to players for the Objective. -+ * @return The registered Objective -+ * @throws IllegalArgumentException if name is null -+ * @throws IllegalArgumentException if name is longer than 16 -+ * characters. -+ * @throws IllegalArgumentException if criteria is null -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalArgumentException if an objective by that name already -+ * exists -+ */ -+ @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName) throws IllegalArgumentException; -+ /** -+ * Registers an Objective on this Scoreboard -+ * -+ * @param name Name of the Objective -+ * @param criteria Criteria for the Objective -+ * @param displayName Name displayed to players for the Objective. -+ * @param renderType Manner of rendering the Objective -+ * @return The registered Objective -+ * @throws IllegalArgumentException if name is null -+ * @throws IllegalArgumentException if name is longer than 16 -+ * characters. -+ * @throws IllegalArgumentException if criteria is null -+ * @throws IllegalArgumentException if displayName is null -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalArgumentException if renderType is null -+ * @throws IllegalArgumentException if an objective by that name already -+ * exists -+ */ -+ @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; -+ // Paper end - - /** - * Registers an Objective on this Scoreboard -@@ -44,8 +86,10 @@ public interface Scoreboard { - * characters. - * @throws IllegalArgumentException if an objective by that name already - * exists -+ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component)} - */ - @NotNull -+ @Deprecated // Paper - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName) throws IllegalArgumentException; - - /** -@@ -66,8 +110,10 @@ public interface Scoreboard { - * @throws IllegalArgumentException if renderType is null - * @throws IllegalArgumentException if an objective by that name already - * exists -+ * @deprecated in favour of {@link #registerNewObjective(String, String, net.kyori.adventure.text.Component, RenderType)} - */ - @NotNull -+ @Deprecated // Paper - Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException; - - /** -diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java -index da01d2926cc8a2485a3349ac1ebb32cad20e287c..f0af10a5b9ad048be197ed5ec6c8ed2672eb3dd5 100644 ---- a/src/main/java/org/bukkit/scoreboard/Team.java -+++ b/src/main/java/org/bukkit/scoreboard/Team.java -@@ -22,14 +22,95 @@ public interface Team { - */ - @NotNull - String getName() throws IllegalStateException; -+ // Paper start -+ /** -+ * Gets the name displayed to entries for this team -+ * -+ * @return Team display name -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; -+ -+ /** -+ * Sets the name displayed to entries for this team -+ * -+ * @param displayName New display name -+ * @throws IllegalArgumentException if displayName is longer than 128 -+ * characters. -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the prefix prepended to the display of entries on this team. -+ * -+ * @return Team prefix -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component prefix() throws IllegalStateException; -+ -+ /** -+ * Sets the prefix prepended to the display of entries on this team. -+ * -+ * @param prefix New prefix -+ * @throws IllegalArgumentException if prefix is null -+ * @throws IllegalArgumentException if prefix is longer than 64 -+ * characters -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void prefix(@Nullable net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the suffix appended to the display of entries on this team. -+ * -+ * @return the team's current suffix -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component suffix() throws IllegalStateException; -+ -+ /** -+ * Sets the suffix appended to the display of entries on this team. -+ * -+ * @param suffix the new suffix for this team. -+ * @throws IllegalArgumentException if suffix is null -+ * @throws IllegalArgumentException if suffix is longer than 64 -+ * characters -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ void suffix(@Nullable net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException; -+ -+ /** -+ * Gets the color of the team. -+ *
-+ * This only sets the team outline, other occurrences of colors such as in -+ * names are handled by prefixes / suffixes. -+ * -+ * @return team color, defaults to {@link ChatColor#RESET} -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.format.TextColor color() throws IllegalStateException; -+ -+ /** -+ * Sets the color of the team. -+ *
-+ * This only sets the team outline, other occurrences of colors such as in -+ * names are handled by prefixes / suffixes. -+ * -+ * @param color new color, must be non-null. Use {@link ChatColor#RESET} for -+ * no color -+ */ -+ void color(@Nullable net.kyori.adventure.text.format.NamedTextColor color); -+ // Paper end - - /** - * Gets the name displayed to entries for this team - * - * @return Team display name - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #displayName()} - */ - @NotNull -+ @Deprecated // Paper - String getDisplayName() throws IllegalStateException; - - /** -@@ -39,7 +120,9 @@ public interface Team { - * @throws IllegalArgumentException if displayName is longer than 128 - * characters. - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -47,8 +130,10 @@ public interface Team { - * - * @return Team prefix - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #prefix()} - */ - @NotNull -+ @Deprecated // Paper - String getPrefix() throws IllegalStateException; - - /** -@@ -59,7 +144,9 @@ public interface Team { - * @throws IllegalArgumentException if prefix is longer than 64 - * characters - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setPrefix(@NotNull String prefix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -67,8 +154,10 @@ public interface Team { - * - * @return the team's current suffix - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #suffix()} - */ - @NotNull -+ @Deprecated // Paper - String getSuffix() throws IllegalStateException; - - /** -@@ -79,7 +168,9 @@ public interface Team { - * @throws IllegalArgumentException if suffix is longer than 64 - * characters - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setSuffix(@NotNull String suffix) throws IllegalStateException, IllegalArgumentException; - - /** -@@ -90,8 +181,10 @@ public interface Team { - * - * @return team color, defaults to {@link ChatColor#RESET} - * @throws IllegalStateException if this team has been unregistered -+ * @deprecated in favour of {@link #color()} - */ - @NotNull -+ @Deprecated // Paper - ChatColor getColor() throws IllegalStateException; - - /** -@@ -102,7 +195,9 @@ public interface Team { - * - * @param color new color, must be non-null. Use {@link ChatColor#RESET} for - * no color -+ * @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)} - */ -+ @Deprecated // Paper - void setColor(@NotNull ChatColor color); - - /** -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 0c7377247ad9251c9e498039511e7220370aba2d..c62919f18f318fec15a6c364d8b6d562c2b04762 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -26,6 +26,12 @@ import org.objectweb.asm.tree.ParameterNode; - public class AnnotationTest { - - private static final String[] ACCEPTED_ANNOTATIONS = { -+ // Paper start -+ "Lorg/checkerframework/checker/nullness/qual/Nullable;", -+ "Lorg/checkerframework/checker/nullness/qual/NonNull;", -+ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", -+ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", -+ // Paper end - "Lorg/jetbrains/annotations/Nullable;", - "Lorg/jetbrains/annotations/NotNull;", - "Lorg/jetbrains/annotations/Contract;", -@@ -66,7 +72,7 @@ public class AnnotationTest { - continue; - } - -- if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) { -+ if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations) && !isWellAnnotated(method.visibleTypeAnnotations)) { // Paper - also check visible type annotations - warn(errors, clazz, method, "return value"); - } - -@@ -174,7 +180,7 @@ public class AnnotationTest { - return true; - } - -- private static boolean isWellAnnotated(@Nullable List annotations) { -+ private static boolean isWellAnnotated(@Nullable List annotations) { // Paper - allow children of AnnotationNode - if (annotations == null) { - return false; - } diff --git a/Spigot-API-Patches/0006-Player-affects-spawning-API.patch b/Spigot-API-Patches/0006-Player-affects-spawning-API.patch deleted file mode 100644 index f923a3d19be2..000000000000 --- a/Spigot-API-Patches/0006-Player-affects-spawning-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Mon, 29 Feb 2016 17:22:34 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 171e2663301f654258dbd772a57688b5a2f8469c..76ac0b20842002ce1b593e338bea98483e7080ac 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1380,6 +1380,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - @Deprecated // Paper - public String getLocale(); - -+ // Paper start -+ /** -+ * Get whether the player can affect mob spawning -+ * -+ * @return if the player can affect mob spawning -+ */ -+ public boolean getAffectsSpawning(); -+ -+ /** -+ * Set whether the player can affect mob spawning -+ * -+ * @param affects Whether the player can affect mob spawning -+ */ -+ public void setAffectsSpawning(boolean affects); -+ // Paper end -+ - /** - * Update the list of commands sent to the client. - *
diff --git a/Spigot-API-Patches/0007-Add-getTPS-method.patch b/Spigot-API-Patches/0007-Add-getTPS-method.patch deleted file mode 100644 index b4bcd8fbba50..000000000000 --- a/Spigot-API-Patches/0007-Add-getTPS-method.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 17:24:57 -0600 -Subject: [PATCH] Add getTPS method - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 426b1e83226e674ee4bf3ec05ddcd3ac4376b06d..cd1b4be422a3a4290579d5daed9466084f18ed60 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1531,6 +1531,17 @@ public final class Bukkit { - return server.getEntity(uuid); - } - -+ // Paper start -+ /** -+ * Gets the current server TPS -+ * @return current server TPS (1m, 5m, 15m in Paper-Server) -+ */ -+ @NotNull -+ public static double[] getTPS() { -+ return server.getTPS(); -+ } -+ // Paper end -+ - /** - * Get the advancement specified by this key. - * -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index d9515a79dc7ed60c66960cd6c6bb4c108f206f3c..9ec374570e135a4ba14db7efdbb5c1bd213226eb 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1290,6 +1290,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - Entity getEntity(@NotNull UUID uuid); - -+ // Paper start -+ /** -+ * Gets the current server TPS -+ * -+ * @return current server TPS (1m, 5m, 15m in Paper-Server) -+ */ -+ @NotNull -+ public double[] getTPS(); -+ // Paper end -+ - /** - * Get the advancement specified by this key. - * diff --git a/Spigot-API-Patches/0008-Entity-Origin-API.patch b/Spigot-API-Patches/0008-Entity-Origin-API.patch deleted file mode 100644 index b26d5933f845..000000000000 --- a/Spigot-API-Patches/0008-Entity-Origin-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 17:50:31 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 41a1bc45cc5eb7f19374115ade7f5328c7fc1dae..e9d0d507b47b0347b975b1a83f5ae70dca5587b8 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -609,5 +609,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { - return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); - } -+ -+ /** -+ * Gets the location where this entity originates from. -+ *

-+ * This value can be null if the entity hasn't yet been added to the world. -+ * -+ * @return Location where entity originates or null if not yet added -+ */ -+ @Nullable -+ Location getOrigin(); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java -index 64f9d3fd870d65afd2ee9a85625b149163eee144..14cb0d770561151570ab4399ca5facff43076819 100644 ---- a/src/main/java/org/bukkit/entity/FallingBlock.java -+++ b/src/main/java/org/bukkit/entity/FallingBlock.java -@@ -54,4 +54,15 @@ public interface FallingBlock extends Entity { - * @param hurtEntities whether entities will be damaged by this block. - */ - void setHurtEntities(boolean hurtEntities); -+ -+ /** -+ * Gets the source block location of the FallingBlock -+ * -+ * @return the source block location the FallingBlock was spawned from -+ * @deprecated replaced by {@link Entity#getOrigin()} -+ */ -+ @Deprecated -+ default org.bukkit.Location getSourceLoc() { -+ return this.getOrigin(); -+ } - } -diff --git a/src/main/java/org/bukkit/entity/TNTPrimed.java b/src/main/java/org/bukkit/entity/TNTPrimed.java -index a23cfdf66877f0a61eae700de084c76e6ee7b431..0813bd913c8fdb2001963ce3e82c07c2af105418 100644 ---- a/src/main/java/org/bukkit/entity/TNTPrimed.java -+++ b/src/main/java/org/bukkit/entity/TNTPrimed.java -@@ -53,4 +53,15 @@ public interface TNTPrimed extends Explosive { - * @param source the source of this primed TNT - */ - public void setSource(@Nullable Entity source); -+ -+ /** -+ * Gets the source block location of the TNTPrimed -+ * -+ * @return the source block location the TNTPrimed was spawned from -+ * @deprecated replaced by {@link Entity#getOrigin()} -+ */ -+ @Deprecated -+ default org.bukkit.Location getSourceLoc() { -+ return this.getOrigin(); -+ } - } diff --git a/Spigot-API-Patches/0009-Version-Command-2.0.patch b/Spigot-API-Patches/0009-Version-Command-2.0.patch deleted file mode 100644 index c7cc974e1a1d..000000000000 --- a/Spigot-API-Patches/0009-Version-Command-2.0.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 27 May 2019 01:10:06 -0500 -Subject: [PATCH] Version Command 2.0 - - -diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c716339346 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.util; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+import org.bukkit.Bukkit; -+import org.jetbrains.annotations.NotNull; -+ -+public interface VersionFetcher { -+ /** -+ * Amount of time to cache results for in milliseconds -+ *

-+ * Negative values will never cache. -+ * -+ * @return cache time -+ */ -+ long getCacheTime(); -+ -+ /** -+ * Gets the version message to cache and show to command senders. -+ * -+ *

NOTE: This is run in a new thread separate from that of the command processing thread

-+ * -+ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) -+ * @return the message to show when requesting a version -+ */ -+ @NotNull -+ Component getVersionMessage(@NotNull String serverVersion); -+ -+ class DummyVersionFetcher implements VersionFetcher { -+ -+ @Override -+ public long getCacheTime() { -+ return -1; -+ } -+ -+ @NotNull -+ @Override -+ public Component getVersionMessage(@NotNull String serverVersion) { -+ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); -+ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); -+ new Throwable().printStackTrace(); -+ return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED); -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 207c656c0a11a3a630bc70491efcf433b2681e18..195b6bb328de92c4d17d1cd14e13578226b1ac3c 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -84,5 +84,12 @@ public interface UnsafeValues { - * @return name - */ - String getTimingsServerName(); -+ -+ /** -+ * Called once by the version command on first use, then cached. -+ */ -+ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -index 2305eb40832a82159cd89162934870cf57e1aa0e..4c2ddc722a9dc4011906ad9530b13fa9be1d3ff9 100644 ---- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -@@ -1,5 +1,6 @@ - package org.bukkit.command.defaults; - -+import com.destroystokyo.paper.util.VersionFetcher; // Paper - version supplier - import com.google.common.base.Charsets; - import com.google.common.collect.ImmutableList; - import com.google.common.io.Resources; -@@ -16,6 +17,7 @@ import java.util.HashSet; - import java.util.List; - import java.util.Set; - import java.util.concurrent.locks.ReentrantLock; -+import net.kyori.adventure.text.Component; // Paper - import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; -@@ -26,6 +28,15 @@ import org.bukkit.util.StringUtil; - import org.jetbrains.annotations.NotNull; - - public class VersionCommand extends BukkitCommand { -+ private VersionFetcher versionFetcher; -+ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration -+ if (versionFetcher == null) { -+ versionFetcher = Bukkit.getUnsafe().getVersionFetcher(); -+ } -+ -+ return versionFetcher; -+ } -+ - public VersionCommand(@NotNull String name) { - super(name); - -@@ -40,7 +51,7 @@ public class VersionCommand extends BukkitCommand { - if (!testPermission(sender)) return true; - - if (args.length == 0) { -- sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); -+ //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage - sendVersion(sender); - } else { - StringBuilder name = new StringBuilder(); -@@ -146,14 +157,14 @@ public class VersionCommand extends BukkitCommand { - - private final ReentrantLock versionLock = new ReentrantLock(); - private boolean hasVersion = false; -- private String versionMessage = null; -+ private Component versionMessage = null; // Paper - private final Set versionWaiters = new HashSet(); - private boolean versionTaskStarted = false; - private long lastCheck = 0; - - private void sendVersion(@NotNull CommandSender sender) { - if (hasVersion) { -- if (System.currentTimeMillis() - lastCheck > 21600000) { -+ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier - lastCheck = System.currentTimeMillis(); - hasVersion = false; - } else { -@@ -168,7 +179,7 @@ public class VersionCommand extends BukkitCommand { - return; - } - versionWaiters.add(sender); -- sender.sendMessage("Checking version, please wait..."); -+ sender.sendMessage(Component.text("Checking version, please wait...", net.kyori.adventure.text.format.NamedTextColor.WHITE, net.kyori.adventure.text.format.TextDecoration.ITALIC)); // Paper - if (!versionTaskStarted) { - versionTaskStarted = true; - new Thread(new Runnable() { -@@ -186,6 +197,13 @@ public class VersionCommand extends BukkitCommand { - - private void obtainVersion() { - String version = Bukkit.getVersion(); -+ // Paper start -+ if (version.startsWith("null")) { // running from ide? -+ setVersionMessage(Component.text("Unknown version, custom build?", net.kyori.adventure.text.format.NamedTextColor.YELLOW)); -+ return; -+ } -+ setVersionMessage(getVersionFetcher().getVersionMessage(version)); -+ /* - if (version == null) version = "Custom"; - String[] parts = version.substring(0, version.indexOf(' ')).split("-"); - if (parts.length == 4) { -@@ -215,11 +233,24 @@ public class VersionCommand extends BukkitCommand { - } else { - setVersionMessage("Unknown version, custom build?"); - } -+ */ -+ // Paper end - } - -- private void setVersionMessage(@NotNull String msg) { -+ // Paper start -+ private void setVersionMessage(final @NotNull Component msg) { - lastCheck = System.currentTimeMillis(); -- versionMessage = msg; -+ final Component message = net.kyori.adventure.text.TextComponent.ofChildren( -+ Component.text("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")", net.kyori.adventure.text.format.NamedTextColor.WHITE), -+ Component.newline(), -+ msg -+ ); -+ this.versionMessage = Component.text() -+ .append(message) -+ .hoverEvent(Component.text("Click to copy to clipboard", net.kyori.adventure.text.format.NamedTextColor.WHITE)) -+ .clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(net.kyori.adventure.text.serializer.plain.PlainComponentSerializer.plain().serialize(message))) -+ .build(); -+ // Paper end - versionLock.lock(); - try { - hasVersion = true; diff --git a/Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch b/Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 10593168ecec..000000000000 --- a/Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Mon, 29 Feb 2016 18:02:25 -0600 -Subject: [PATCH] Add PlayerLocaleChangeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..29dd763a99ce7c6ecb176b9fb346a400369d48a0 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+ -+/** -+ * Called when the locale of the player is changed. -+ * -+ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream -+ */ -+@Deprecated -+public class PlayerLocaleChangeEvent extends PlayerEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ private final String oldLocale; -+ private final String newLocale; -+ -+ public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) { -+ super(player); -+ this.oldLocale = oldLocale; -+ this.newLocale = newLocale; -+ } -+ -+ /** -+ * Gets the locale the player switched from. -+ * -+ * @return player's old locale -+ */ -+ public String getOldLocale() { -+ return oldLocale; -+ } -+ -+ /** -+ * Gets the locale the player is changed to. -+ * -+ * @return player's new locale -+ */ -+ public String getNewLocale() { -+ return newLocale; -+ } -+ -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0011-Add-player-view-distance-API.patch b/Spigot-API-Patches/0011-Add-player-view-distance-API.patch deleted file mode 100644 index 8b5561ac144b..000000000000 --- a/Spigot-API-Patches/0011-Add-player-view-distance-API.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 18:05:37 -0600 -Subject: [PATCH] Add player view distance API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 76ac0b20842002ce1b593e338bea98483e7080ac..f34601480a3b3069c30c52d258a35a2a79c981fb 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1394,6 +1394,28 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param affects Whether the player can affect mob spawning - */ - public void setAffectsSpawning(boolean affects); -+ -+ /** -+ * Gets the view distance for this player -+ * -+ * @return the player's view distance -+ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. -+ * @see org.bukkit.World#getViewDistance() -+ * @see org.bukkit.World#getNoTickViewDistance() -+ */ -+ @Deprecated -+ public int getViewDistance(); -+ -+ /** -+ * Sets the view distance for this player -+ * -+ * @param viewDistance the player's view distance -+ * @deprecated This is unimplemented and will throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work. -+ * @see org.bukkit.World#setViewDistance(int) -+ * @see org.bukkit.World#setNoTickViewDistance(int) -+ */ -+ @Deprecated -+ public void setViewDistance(int viewDistance); - // Paper end - - /** diff --git a/Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch b/Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch deleted file mode 100644 index 43af3c3828b5..000000000000 --- a/Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Mon, 29 Feb 2016 18:09:40 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..978813b94a5eae0afccbd3b38b463091a46b56ac ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java -@@ -0,0 +1,86 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.potion.PotionEffect; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a beacon effect is being applied to a player. -+ */ -+public class BeaconEffectEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private PotionEffect effect; -+ private Player player; -+ private boolean primary; -+ -+ public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) { -+ super(block); -+ this.effect = effect; -+ this.player = player; -+ this.primary = primary; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the potion effect being applied. -+ * -+ * @return Potion effect -+ */ -+ @NotNull -+ public PotionEffect getEffect() { -+ return effect; -+ } -+ -+ /** -+ * Sets the potion effect that will be applied. -+ * -+ * @param effect Potion effect -+ */ -+ public void setEffect(@NotNull PotionEffect effect) { -+ this.effect = effect; -+ } -+ -+ /** -+ * Gets the player who the potion effect is being applied to. -+ * -+ * @return Affected player -+ */ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ /** -+ * Gets whether the effect is a primary beacon effect. -+ * -+ * @return true if this event represents a primary effect -+ */ -+ public boolean isPrimary() { -+ return primary; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch b/Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index c113777bf519..000000000000 --- a/Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Mon, 29 Feb 2016 18:13:58 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8b1fdb9d2869d4c1862d557c91bf8a1d8c537507 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java -@@ -0,0 +1,16 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+import org.spigotmc.event.player.PlayerSpawnLocationEvent; -+ -+/** -+ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API -+ */ -+public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent { -+ -+ public PlayerInitialSpawnEvent(@NotNull Player who, @NotNull Location spawnLocation) { -+ super(who, spawnLocation); -+ } -+} diff --git a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch b/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch deleted file mode 100644 index 55aeb559ba06..000000000000 --- a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 19:45:21 -0600 -Subject: [PATCH] Automatically disable plugins that fail to load - - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index cf2f517765d8f2a23cc4a17d9ee2dcd81f841b1b..2e306c7b984a02e12a74fac14589bf29ab6488bf 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -335,6 +335,10 @@ public final class JavaPluginLoader implements PluginLoader { - jPlugin.setEnabled(true); - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ // Paper start - Disable plugins that fail to load -+ disablePlugin(jPlugin); -+ return; -+ // Paper end - } - - // Perhaps abort here, rather than continue going, but as it stands, diff --git a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch b/Spigot-API-Patches/0015-Expose-server-CommandMap.patch deleted file mode 100644 index aa4d6d7b13c8..000000000000 --- a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Mon, 29 Feb 2016 19:48:59 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index cd1b4be422a3a4290579d5daed9466084f18ed60..10274053320f1ec690a65d3794abb44b58658059 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1705,6 +1705,19 @@ public final class Bukkit { - return server.getUnsafe(); - } - -+ -+ // Paper start -+ /** -+ * Gets the active {@link org.bukkit.command.CommandMap} -+ * -+ * @return the active command map -+ */ -+ @NotNull -+ public static org.bukkit.command.CommandMap getCommandMap() { -+ return server.getCommandMap(); -+ } -+ // Paper end -+ - @NotNull - public static Server.Spigot spigot() { - return server.spigot(); -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9ec374570e135a4ba14db7efdbb5c1bd213226eb..7e4a728ceb943b6a32b9ba9b84bada34e71c0980 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1300,6 +1300,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - public double[] getTPS(); - // Paper end - -+ // Paper start -+ /** -+ * Gets the active {@link org.bukkit.command.CommandMap} -+ * -+ * @return the active command map -+ */ -+ @NotNull -+ org.bukkit.command.CommandMap getCommandMap(); -+ - /** - * Get the advancement specified by this key. - * diff --git a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch deleted file mode 100644 index 28128cfb6928..000000000000 --- a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 19:54:32 -0600 -Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses - -Change Javadoc to be accurate - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 10274053320f1ec690a65d3794abb44b58658059..22b83b142de97dcba28fa9a49730de7880d0b5d2 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -285,6 +285,30 @@ public final class Bukkit { - return server.broadcastMessage(message); - } - -+ // Paper start -+ /** -+ * Sends the component to all online players. -+ * -+ * @param component the component to send -+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ server.broadcast(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to all online players. -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ server.broadcast(components); -+ } -+ // Paper end -+ - /** - * Gets the name of the update folder. The update folder is used to safely - * update plugins at the right moment on a plugin load. -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7e4a728ceb943b6a32b9ba9b84bada34e71c0980..9ce9b4ce2da6c57c62607502ae2042e30fc26d88 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -234,6 +234,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Deprecated // Paper - public int broadcastMessage(@NotNull String message); - -+ // Paper start -+ /** -+ * Sends the component to all online players. -+ * -+ * @param component the component to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ spigot().broadcast(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to all online players. -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Deprecated -+ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().broadcast(components); -+ } -+ // Paper end -+ - /** - * Gets the name of the update folder. The update folder is used to safely - * update plugins at the right moment on a plugin load. -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68795a48cb15d322906ce0569b7701231c1f94c2..88853cc165c67fd60a0a8f87e4ce356e4ca045f9 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -614,6 +614,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void sendMap(@NotNull MapView map); - -+ // Paper start -+ /** -+ * Sends the component to the player -+ * -+ * @param component the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Override -+ @Deprecated -+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ spigot().sendMessage(component); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the player -+ * -+ * @param components the components to send -+ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -+ */ -+ @Override -+ @Deprecated -+ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().sendMessage(components); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the specified screen position of this player -+ * -+ * @param position the screen position -+ * @param components the components to send -+ */ -+ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { -+ spigot().sendMessage(position, components); -+ } -+ // Paper end -+ - /** - * Forces an update of the player's entire inventory. - * diff --git a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch b/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index 90316cae1dfc..000000000000 --- a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,577 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Mon, 29 Feb 2016 20:02:40 -0600 -Subject: [PATCH] Player Tab List and Title APIs - -Co-authored-by: Fruxz - -diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9e90c3df567a65b48a0b9341f784eb902cb35d8c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Title.java -@@ -0,0 +1,420 @@ -+package com.destroystokyo.paper; -+ -+import net.md_5.bungee.api.chat.BaseComponent; -+import net.md_5.bungee.api.chat.TextComponent; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.List; -+ -+import static com.google.common.base.Preconditions.checkArgument; -+import static com.google.common.base.Preconditions.checkNotNull; -+import static com.google.common.base.Preconditions.checkState; -+ -+/** -+ * Represents a title to may be sent to a {@link Player}. -+ * -+ *

A title can be sent without subtitle text.

-+ * -+ * @deprecated use {@link net.kyori.adventure.title.Title} -+ */ -+@Deprecated -+public final class Title { -+ -+ /** -+ * The default number of ticks for the title to fade in. -+ */ -+ public static final int DEFAULT_FADE_IN = 20; -+ /** -+ * The default number of ticks for the title to stay. -+ */ -+ public static final int DEFAULT_STAY = 200; -+ /** -+ * The default number of ticks for the title to fade out. -+ */ -+ public static final int DEFAULT_FADE_OUT = 20; -+ -+ private final BaseComponent[] title; -+ private final BaseComponent[] subtitle; -+ private final int fadeIn; -+ private final int stay; -+ private final int fadeOut; -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull BaseComponent title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull BaseComponent[] title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values and no subtitle. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @throws NullPointerException if the title is null -+ */ -+ public Title(@NotNull String title) { -+ this(title, null); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Create a title with the default time values. -+ * -+ *

Times use default values.

-+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ */ -+ public Title(@NotNull String title, @Nullable String subtitle) { -+ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ * @throws IllegalArgumentException if any of the times are negative -+ */ -+ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) { -+ this( -+ new BaseComponent[]{checkNotNull(title, "title")}, -+ subtitle == null ? null : new BaseComponent[]{subtitle}, -+ fadeIn, -+ stay, -+ fadeOut -+ ); -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ * @throws IllegalArgumentException if any of the times are negative -+ */ -+ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) { -+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); -+ checkArgument(stay >= 0, "Negative stay: %s", stay); -+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); -+ this.title = checkNotNull(title, "title"); -+ this.subtitle = subtitle; -+ this.fadeIn = fadeIn; -+ this.stay = stay; -+ this.fadeOut = fadeOut; -+ } -+ -+ /** -+ * Creates a new title. -+ * -+ *

It is recommended to the {@link BaseComponent} constrctors.

-+ * -+ * @param title the main text of the title -+ * @param subtitle the secondary text of the title -+ * @param fadeIn the number of ticks for the title to fade in -+ * @param stay the number of ticks for the title to stay on screen -+ * @param fadeOut the number of ticks for the title to fade out -+ */ -+ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) { -+ this( -+ TextComponent.fromLegacyText(checkNotNull(title, "title")), -+ subtitle == null ? null : TextComponent.fromLegacyText(subtitle), -+ fadeIn, -+ stay, -+ fadeOut -+ ); -+ } -+ -+ /** -+ * Gets the text of this title -+ * -+ * @return the text -+ */ -+ @NotNull -+ public BaseComponent[] getTitle() { -+ return this.title; -+ } -+ -+ /** -+ * Gets the text of this title's subtitle -+ * -+ * @return the text -+ */ -+ @Nullable -+ public BaseComponent[] getSubtitle() { -+ return this.subtitle; -+ } -+ -+ /** -+ * Gets the number of ticks to fade in. -+ * -+ *

The returned value is never negative.

-+ * -+ * @return the number of ticks to fade in -+ */ -+ public int getFadeIn() { -+ return this.fadeIn; -+ } -+ -+ /** -+ * Gets the number of ticks to stay. -+ * -+ *

The returned value is never negative.

-+ * -+ * @return the number of ticks to stay -+ */ -+ public int getStay() { -+ return this.stay; -+ } -+ -+ /** -+ * Gets the number of ticks to fade out. -+ * -+ *

The returned value is never negative.

-+ * -+ * @return the number of ticks to fade out -+ */ -+ public int getFadeOut() { -+ return this.fadeOut; -+ } -+ -+ /** -+ * Sends the title directly to an player -+ * -+ * @param player the receiver of the title -+ */ -+ public void send(@NotNull Player player) { -+ player.sendTitle(this); -+ } -+ -+ /** -+ * Sends the title directly to the defined players -+ * -+ * @param players the receivers of the title -+ */ -+ public void send(@NotNull Collection players) { -+ for (Player player : players) { -+ player.sendTitle(this); -+ } -+ } -+ -+ /** -+ * Sends the title directly to the defined players -+ * -+ * @param players the receivers of the title -+ */ -+ public void send(@NotNull Player[] players) { -+ for (Player player : players) { -+ player.sendTitle(this); -+ } -+ } -+ -+ /** -+ * Sends the title directly to all online players -+ */ -+ public void broadcast() { -+ send(Bukkit.getOnlinePlayers()); -+ } -+ -+ @NotNull -+ public static Builder builder() { -+ return new Builder(); -+ } -+ -+ /** -+ * A builder for creating titles -+ */ -+ public static final class Builder { -+ -+ private BaseComponent[] title; -+ private BaseComponent[] subtitle; -+ private int fadeIn = DEFAULT_FADE_IN; -+ private int stay = DEFAULT_STAY; -+ private int fadeOut = DEFAULT_FADE_OUT; -+ -+ /** -+ * Sets the title to the given text. -+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull BaseComponent title) { -+ return this.title(new BaseComponent[]{checkNotNull(title, "title")}); -+ } -+ -+ /** -+ * Sets the title to the given text. -+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull BaseComponent[] title) { -+ this.title = checkNotNull(title, "title"); -+ return this; -+ } -+ -+ /** -+ * Sets the title to the given text. -+ * -+ *

It is recommended to the {@link BaseComponent} methods.

-+ * -+ * @param title the title text -+ * @return this builder instance -+ * @throws NullPointerException if the title is null -+ */ -+ @NotNull -+ public Builder title(@NotNull String title) { -+ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title"))); -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable BaseComponent subtitle) { -+ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle}); -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable BaseComponent[] subtitle) { -+ this.subtitle = subtitle; -+ return this; -+ } -+ -+ /** -+ * Sets the subtitle to the given text. -+ * -+ *

It is recommended to the {@link BaseComponent} methods.

-+ * -+ * @param subtitle the title text -+ * @return this builder instance -+ */ -+ @NotNull -+ public Builder subtitle(@Nullable String subtitle) { -+ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle)); -+ } -+ -+ /** -+ * Sets the number of ticks for the title to fade in -+ * -+ * @param fadeIn the number of ticks to fade in -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder fadeIn(int fadeIn) { -+ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); -+ this.fadeIn = fadeIn; -+ return this; -+ } -+ -+ -+ /** -+ * Sets the number of ticks for the title to stay. -+ * -+ * @param stay the number of ticks to stay -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder stay(int stay) { -+ checkArgument(stay >= 0, "Negative stay: %s", stay); -+ this.stay = stay; -+ return this; -+ } -+ -+ /** -+ * Sets the number of ticks for the title to fade out. -+ * -+ * @param fadeOut the number of ticks to fade out -+ * @return this builder instance -+ * @throws IllegalArgumentException if it is negative -+ */ -+ @NotNull -+ public Builder fadeOut(int fadeOut) { -+ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); -+ this.fadeOut = fadeOut; -+ return this; -+ } -+ -+ /** -+ * Create a title based on the values in the builder. -+ * -+ * @return a title from the values in this builder -+ * @throws IllegalStateException if title isn't specified -+ */ -+ @NotNull -+ public Title build() { -+ checkState(title != null, "Title not specified"); -+ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut); -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 88853cc165c67fd60a0a8f87e4ce356e4ca045f9..c9e4cb2d153fc0c6853fe520263a0073e7504e38 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2,6 +2,7 @@ package org.bukkit.entity; - - import java.net.InetSocketAddress; - import java.util.UUID; -+import com.destroystokyo.paper.Title; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -648,6 +649,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { - spigot().sendMessage(position, components); - } -+ -+ /** -+ * Set the text displayed in the player list header and footer for this player -+ * -+ * @param header content for the top of the player list -+ * @param footer content for the bottom of the player list -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated -+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer); -+ -+ /** -+ * Set the text displayed in the player list header and footer for this player -+ * -+ * @param header content for the top of the player list -+ * @param footer content for the bottom of the player list -+ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} -+ */ -+ @Deprecated -+ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer); -+ -+ /** -+ * Update the times for titles displayed to the player -+ * -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Update the subtitle of titles displayed to the player -+ * -+ * @param subtitle Subtitle to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle); -+ -+ /** -+ * Update the subtitle of titles displayed to the player -+ * -+ * @param subtitle Subtitle to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle); -+ -+ /** -+ * Show the given title to the player, along with the last subtitle set, using the last set times -+ * -+ * @param title Title to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title); -+ -+ /** -+ * Show the given title to the player, along with the last subtitle set, using the last set times -+ * -+ * @param title Title to set -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title); -+ -+ /** -+ * Show the given title and subtitle to the player using the given times -+ * -+ * @param title big text -+ * @param subtitle little text under it -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Show the given title and subtitle to the player using the given times -+ * -+ * @param title big text -+ * @param subtitle little text under it -+ * @param fadeInTicks ticks to fade-in -+ * @param stayTicks ticks to stay visible -+ * @param fadeOutTicks ticks to fade-out -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); -+ -+ /** -+ * Show the title to the player, overriding any previously displayed title. -+ * -+ *

This method overrides any previous title, use {@link #updateTitle(Title)} to change the existing one.

-+ * -+ * @param title the title to send -+ * @throws NullPointerException if the title is null -+ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ void sendTitle(@NotNull Title title); -+ -+ /** -+ * Show the title to the player, overriding any previously displayed title. -+ * -+ *

This method doesn't override previous titles, but changes their values.

-+ * -+ * @param title the title to send -+ * @throws NullPointerException if title is null -+ * @deprecated use {@link #showTitle(net.kyori.adventure.title.Title)} -+ */ -+ @Deprecated -+ void updateTitle(@NotNull Title title); -+ -+ /** -+ * Hide any title that is currently visible to the player -+ * -+ * @deprecated use {@link #clearTitle()} -+ */ -+ @Deprecated -+ public void hideTitle(); - // Paper end - - /** diff --git a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch b/Spigot-API-Patches/0018-Add-exception-reporting-event.patch deleted file mode 100644 index b295b466fcb2..000000000000 --- a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch +++ /dev/null @@ -1,604 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:24:35 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2f573299a9a817a98372817a1de8bf641aaca956 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java -@@ -0,0 +1,43 @@ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.base.Preconditions; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import com.destroystokyo.paper.exception.ServerException; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called whenever an exception is thrown in a recoverable section of the server. -+ */ -+public class ServerExceptionEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private ServerException exception; -+ -+ public ServerExceptionEvent(@NotNull ServerException exception) { -+ super(!Bukkit.isPrimaryThread()); -+ this.exception = Preconditions.checkNotNull(exception, "exception"); -+ } -+ -+ /** -+ * Gets the wrapped exception that was thrown. -+ * -+ * @return Exception thrown -+ */ -+ @NotNull -+ public ServerException getException() { -+ return exception; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Thrown when a command throws an exception -+ */ -+public class ServerCommandException extends ServerException { -+ -+ private final Command command; -+ private final CommandSender commandSender; -+ private final String[] arguments; -+ -+ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(cause); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ this.commandSender = checkNotNull(commandSender, "commandSender"); -+ this.arguments = checkNotNull(arguments, "arguments"); -+ this.command = checkNotNull(command, "command"); -+ } -+ -+ /** -+ * Gets the command which threw the exception -+ * -+ * @return exception throwing command -+ */ -+ public Command getCommand() { -+ return command; -+ } -+ -+ /** -+ * Gets the command sender which executed the command request -+ * -+ * @return command sender of exception thrown command request -+ */ -+ public CommandSender getCommandSender() { -+ return commandSender; -+ } -+ -+ /** -+ * Gets the arguments which threw the exception for the command -+ * -+ * @return arguments of exception thrown command request -+ */ -+ public String[] getArguments() { -+ return arguments; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Exception thrown when a server event listener throws an exception -+ */ -+public class ServerEventException extends ServerPluginException { -+ -+ private final Listener listener; -+ private final Event event; -+ -+ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(message, cause, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(cause, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ this.listener = checkNotNull(listener, "listener"); -+ this.event = checkNotNull(event, "event"); -+ } -+ -+ /** -+ * Gets the listener which threw the exception -+ * -+ * @return event listener -+ */ -+ public Listener getListener() { -+ return listener; -+ } -+ -+ /** -+ * Gets the event which caused the exception -+ * -+ * @return event -+ */ -+ public Event getEvent() { -+ return event; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java -@@ -0,0 +1,23 @@ -+package com.destroystokyo.paper.exception; -+ -+/** -+ * Wrapper exception for all exceptions that are thrown by the server. -+ */ -+public class ServerException extends Exception { -+ -+ public ServerException(String message) { -+ super(message); -+ } -+ -+ public ServerException(String message, Throwable cause) { -+ super(message, cause); -+ } -+ -+ public ServerException(Throwable cause) { -+ super(cause); -+ } -+ -+ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e762ed0dbad51625e65fef2e1898679108459a36 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java -@@ -0,0 +1,35 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.Bukkit; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+ -+/** -+ * Thrown when the internal server throws a recoverable exception. -+ */ -+public class ServerInternalException extends ServerException { -+ -+ public ServerInternalException(String message) { -+ super(message); -+ } -+ -+ public ServerInternalException(String message, Throwable cause) { -+ super(message, cause); -+ } -+ -+ public ServerInternalException(Throwable cause) { -+ super(cause); -+ } -+ -+ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ } -+ -+ public static void reportInternalException(Throwable cause) { -+ try { -+ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause))); -+ ; -+ } catch (Throwable t) { -+ t.printStackTrace(); // Don't want to rethrow! -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java -@@ -0,0 +1,20 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.plugin.Plugin; -+ -+/** -+ * Thrown whenever there is an exception with any enabling or disabling of plugins. -+ */ -+public class ServerPluginEnableDisableException extends ServerPluginException { -+ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) { -+ super(message, cause, responsiblePlugin); -+ } -+ -+ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) { -+ super(cause, responsiblePlugin); -+ } -+ -+ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ } -+} -\ No newline at end of file -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6defac287d0214fdf99418d979144050cc1e53bc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.exception; -+ -+import com.google.common.base.Preconditions; -+import org.apache.commons.lang.Validate; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Wrapper exception for all cases to which a plugin can be immediately blamed for -+ */ -+public class ServerPluginException extends ServerException { -+ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) { -+ super(message, cause); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) { -+ super(cause); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { -+ super(message, cause, enableSuppression, writableStackTrace); -+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); -+ } -+ -+ private final Plugin responsiblePlugin; -+ -+ /** -+ * Gets the plugin which is directly responsible for the exception being thrown -+ * -+ * @return plugin which is responsible for the exception throw -+ */ -+ public Plugin getResponsiblePlugin() { -+ return responsiblePlugin; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89e132525cfae0ce979e37b3e2793df781e47227 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.plugin.Plugin; -+ -+import static com.google.common.base.Preconditions.*; -+ -+/** -+ * Thrown when an incoming plugin message channel throws an exception -+ */ -+public class ServerPluginMessageException extends ServerPluginException { -+ -+ private final Player player; -+ private final String channel; -+ private final byte[] data; -+ -+ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(message, cause, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(cause, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) { -+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); -+ this.player = checkNotNull(player, "player"); -+ this.channel = checkNotNull(channel, "channel"); -+ this.data = checkNotNull(data, "data"); -+ } -+ -+ /** -+ * Gets the channel to which the error occurred from recieving data from -+ * -+ * @return exception channel -+ */ -+ public String getChannel() { -+ return channel; -+ } -+ -+ /** -+ * Gets the data to which the error occurred from -+ * -+ * @return exception data -+ */ -+ public byte[] getData() { -+ return data; -+ } -+ -+ /** -+ * Gets the player which the plugin message causing the exception originated from -+ * -+ * @return exception player -+ */ -+ public Player getPlayer() { -+ return player; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java -@@ -0,0 +1,37 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.scheduler.BukkitTask; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Thrown when a plugin's scheduler fails with an exception -+ */ -+public class ServerSchedulerException extends ServerPluginException { -+ -+ private final BukkitTask task; -+ -+ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) { -+ super(message, cause, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ public ServerSchedulerException(Throwable cause, BukkitTask task) { -+ super(cause, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) { -+ super(message, cause, enableSuppression, writableStackTrace, task.getOwner()); -+ this.task = checkNotNull(task, "task"); -+ } -+ -+ /** -+ * Gets the task which threw the exception -+ * -+ * @return exception throwing task -+ */ -+ public BukkitTask getTask() { -+ return task; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java -@@ -0,0 +1,22 @@ -+package com.destroystokyo.paper.exception; -+ -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+/** -+ * Called when a tab-complete request throws an exception -+ */ -+public class ServerTabCompleteException extends ServerCommandException { -+ -+ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, command, commandSender, arguments); -+ } -+ -+ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { -+ super(cause, command, commandSender, arguments); -+ } -+ -+ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { -+ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments); -+ } -+} -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index f020cb04eba27a2e70fc7cf799ebbfb434b9d974..adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -8,6 +8,10 @@ import java.util.HashMap; - import java.util.Iterator; - import java.util.List; - import java.util.Map; -+ -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerCommandException; -+import com.destroystokyo.paper.exception.ServerTabCompleteException; - import org.apache.commons.lang.Validate; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -155,11 +159,14 @@ public class SimpleCommandMap implements CommandMap { - target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); - } // target.timings.stopTiming(); // Spigot // Paper - } catch (CommandException ex) { -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper - //target.timings.stopTiming(); // Spigot // Paper - throw ex; - } catch (Throwable ex) { - //target.timings.stopTiming(); // Spigot // Paper -- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); -+ String msg = "Unhandled exception executing '" + commandLine + "' in " + target; -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerCommandException(ex, target, sender, args))); // Paper -+ throw new CommandException(msg, ex); - } - - // return true as command was handled -@@ -238,7 +245,9 @@ public class SimpleCommandMap implements CommandMap { - } catch (CommandException ex) { - throw ex; - } catch (Throwable ex) { -- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex); -+ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target; -+ server.getPluginManager().callEvent(new ServerExceptionEvent(new ServerTabCompleteException(msg, ex, target, sender, args))); // Paper -+ throw new CommandException(msg, ex); - } - } - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 745eaa8f2f2ff83536301db8ca47a8af30df7a73..d0fec44d2546290091649879450761ce08514fcb 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -23,6 +23,10 @@ import java.util.WeakHashMap; - import java.util.logging.Level; - import java.util.regex.Matcher; - import java.util.regex.Pattern; -+ -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerEventException; -+import com.destroystokyo.paper.exception.ServerPluginEnableDisableException; - import org.apache.commons.lang.Validate; - import org.bukkit.Server; - import org.bukkit.World; -@@ -478,7 +482,8 @@ public final class SimplePluginManager implements PluginManager { - try { - plugin.getPluginLoader().enablePlugin(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while enabling " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); - } - - HandlerList.bakeAll(); -@@ -499,32 +504,37 @@ public final class SimplePluginManager implements PluginManager { - try { - plugin.getPluginLoader().disablePlugin(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while disabling " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getScheduler().cancelTasks(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getServicesManager().unregisterAll(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering services for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - HandlerList.unregisterAll(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering events for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { - server.getMessenger().unregisterIncomingPluginChannel(plugin); - server.getMessenger().unregisterOutgoingPluginChannel(plugin); - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for " -+ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper - } - - try { -@@ -537,6 +547,13 @@ public final class SimplePluginManager implements PluginManager { - } - } - -+ // Paper start -+ private void handlePluginException(String msg, Throwable ex, Plugin plugin) { -+ server.getLogger().log(Level.SEVERE, msg, ex); -+ callEvent(new ServerExceptionEvent(new ServerPluginEnableDisableException(msg, ex, plugin))); -+ } -+ // Paper end -+ - @Override - public void clearPlugins() { - synchronized (this) { -@@ -600,7 +617,13 @@ public final class SimplePluginManager implements PluginManager { - )); - } - } catch (Throwable ex) { -- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex); -+ // Paper start - error reporting -+ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); -+ server.getLogger().log(Level.SEVERE, msg, ex); -+ if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop -+ callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); -+ } -+ // Paper end - } - } - } diff --git a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch deleted file mode 100644 index b8376a9108cf..000000000000 --- a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 8 Mar 2016 13:05:59 -0800 -Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender - - -diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java -index c88418c7aa19b4fecdfa9af3d18ff202a5dc5763..fb0e608fa92dae99b9eee8fc1cbdf4b91a33e620 100644 ---- a/src/main/java/org/bukkit/command/CommandSender.java -+++ b/src/main/java/org/bukkit/command/CommandSender.java -@@ -1,6 +1,9 @@ - package org.bukkit.command; - - import java.util.UUID; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.identity.Identity; -+import net.kyori.adventure.text.Component; - import org.bukkit.Server; - import org.bukkit.permissions.Permissible; - import org.jetbrains.annotations.NotNull; -@@ -117,5 +120,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe - default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { - this.sendMessage(org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().serialize(message)); - } -+ -+ /** -+ * Sends the component to the sender -+ * -+ *

If this sender does not support sending full components then -+ * the component will be sent as legacy text.

-+ * -+ * @param component the component to send -+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead -+ */ -+ @Deprecated -+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { -+ this.sendMessage(component.toLegacyText()); -+ } -+ -+ /** -+ * Sends an array of components as a single message to the sender -+ * -+ *

If this sender does not support sending full components then -+ * the components will be sent as legacy text.

-+ * -+ * @param components the components to send -+ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead -+ */ -+ @Deprecated -+ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { -+ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText()); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index 515b56ff039e..000000000000 --- a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:47:27 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 24c858182f25496cc7254f7cf9e996b3bea1f9ec..45e9f585c3e522ecf94a6bc42cdc190e1a191a5c 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -605,4 +605,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @return Whether the entity is invisible - */ - public boolean isInvisible(); -+ -+ // Paper start -+ /** -+ * Get the number of arrows stuck in this entity -+ * @return Number of arrows stuck -+ */ -+ int getArrowsStuck(); -+ -+ /** -+ * Set the number of arrows stuck in this entity -+ * -+ * @param arrows Number of arrows to stick in this entity -+ */ -+ void setArrowsStuck(int arrows); -+ // Paper end - } diff --git a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch b/Spigot-API-Patches/0022-Complete-resource-pack-API.patch deleted file mode 100644 index ff78c17d141e..000000000000 --- a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 22:59:54 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 769ad98fd7a6a866b320e1ccffd7962228d564cf..ddbe5734ac0f905b0c388e30f17a281530b82262 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1124,7 +1124,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException Thrown if the URL is null. - * @throws IllegalArgumentException Thrown if the URL is too long. The - * length restriction is an implementation specific arbitrary value. -+ * @deprecated use {@link #setResourcePack(String, String)} - */ -+ @Deprecated // Paper - public void setResourcePack(@NotNull String url); - - /** -@@ -1601,6 +1603,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { - return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); - } -+ -+ /** -+ * Request that the player's client download and switch resource packs. -+ *

-+ * The player's client will download the new resource pack asynchronously -+ * in the background, and will automatically switch to it once the -+ * download is complete. If the client has downloaded and cached the same -+ * resource pack in the past, it will perform a quick timestamp check -+ * over the network to determine if the resource pack has changed and -+ * needs to be downloaded again. When this request is sent for the very -+ * first time from a given server, the client will first display a -+ * confirmation GUI to the player before proceeding with the download. -+ *

-+ * Notes: -+ *

    -+ *
  • Players can disable server resources on their client, in which -+ * case this method will have no affect on them. -+ *
  • There is no concept of resetting resource packs back to default -+ * within Minecraft, so players will have to relog to do so. -+ *
-+ * -+ * @param url The URL from which the client will download the resource -+ * pack. The string must contain only US-ASCII characters and should -+ * be encoded as per RFC 1738. -+ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of -+ * the resource pack file. -+ * @throws IllegalArgumentException Thrown if the URL is null. -+ * @throws IllegalArgumentException Thrown if the URL is too long. The -+ * length restriction is an implementation specific arbitrary value. -+ */ -+ void setResourcePack(@NotNull String url, @NotNull String hash); -+ -+ /** -+ * @return the most recent resource pack status received from the player, -+ * or null if no status has ever been received from this player. -+ */ -+ @Nullable -+ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus(); -+ -+ /** -+ * @return the most recent resource pack hash received from the player, -+ * or null if no hash has ever been received from this player. -+ * -+ * @deprecated This is no longer sent from the client and will always be null -+ */ -+ @Nullable -+ @Deprecated -+ String getResourcePackHash(); -+ -+ /** -+ * @return true if the last resource pack status received from this player -+ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} -+ */ -+ boolean hasResourcePack(); - // Paper end - - // Spigot start -diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -index b98195650d49d78ec35970ca0376b6289b861e4b..4c2102a11c3d682d98f0db4ccafa35231e66bcdd 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java -@@ -11,13 +11,32 @@ import org.jetbrains.annotations.NotNull; - public class PlayerResourcePackStatusEvent extends PlayerEvent { - - private static final HandlerList handlers = new HandlerList(); -+ @Deprecated -+ private final String hash; // Paper - private final Status status; - - public PlayerResourcePackStatusEvent(@NotNull final Player who, @NotNull Status resourcePackStatus) { - super(who); -+ this.hash = null; // Paper - this.status = resourcePackStatus; - } - -+ @Deprecated // Paper -+ public PlayerResourcePackStatusEvent(final Player who, Status resourcePackStatus, String hash) { -+ super(who); -+ this.hash = hash; // Paper -+ this.status = resourcePackStatus; -+ } -+ -+ @Deprecated -+ /** -+ * @deprecated Hash does not seem to ever be set -+ */ -+ public String getHash() { -+ return this.hash; -+ } -+ // Paper end -+ - /** - * Gets the status of this pack. - * diff --git a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch b/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch deleted file mode 100644 index bcbe8ec071f4..000000000000 --- a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 13:20:33 -0700 -Subject: [PATCH] Use ASM for event executors. - -Uses method handles for private or static methods. - -diff --git a/pom.xml b/pom.xml -index 1ced7a212684cee8faf07fa9a083adcd47be7fcb..7ec7e6047193a6b390d24f6d2722e35d1d36830d 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -163,6 +163,17 @@ - 9.1 - test -
-+ -+ -+ org.ow2.asm -+ asm -+ 9.0 -+ -+ -+ org.ow2.asm -+ asm-commons -+ 9.0 -+ -
- - -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5b28e9b1daba7834af67dbc193dd656bedd9a994 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java -@@ -0,0 +1,42 @@ -+package com.destroystokyo.paper.event.executor; -+ -+import java.lang.invoke.MethodHandle; -+import java.lang.invoke.MethodHandles; -+import java.lang.reflect.Method; -+ -+import com.destroystokyo.paper.util.SneakyThrow; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+ -+public class MethodHandleEventExecutor implements EventExecutor { -+ private final Class eventClass; -+ private final MethodHandle handle; -+ -+ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull MethodHandle handle) { -+ this.eventClass = eventClass; -+ this.handle = handle; -+ } -+ -+ public MethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { -+ this.eventClass = eventClass; -+ try { -+ m.setAccessible(true); -+ this.handle = MethodHandles.lookup().unreflect(m); -+ } catch (IllegalAccessException e) { -+ throw new AssertionError("Unable to set accessible", e); -+ } -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (!eventClass.isInstance(event)) return; -+ try { -+ handle.invoke(listener, event); -+ } catch (Throwable t) { -+ SneakyThrow.sneaky(t); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c83672427324bd068ed52916f700b68446a226f6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java -@@ -0,0 +1,43 @@ -+package com.destroystokyo.paper.event.executor; -+ -+import java.lang.invoke.MethodHandle; -+import java.lang.invoke.MethodHandles; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+ -+import com.destroystokyo.paper.util.SneakyThrow; -+import com.google.common.base.Preconditions; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.EventException; -+import org.bukkit.event.Listener; -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+ -+public class StaticMethodHandleEventExecutor implements EventExecutor { -+ private final Class eventClass; -+ private final MethodHandle handle; -+ -+ public StaticMethodHandleEventExecutor(@NotNull Class eventClass, @NotNull Method m) { -+ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); -+ Preconditions.checkArgument(eventClass != null, "eventClass is null"); -+ this.eventClass = eventClass; -+ try { -+ m.setAccessible(true); -+ this.handle = MethodHandles.lookup().unreflect(m); -+ } catch (IllegalAccessException e) { -+ throw new AssertionError("Unable to set accessible", e); -+ } -+ } -+ -+ @Override -+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { -+ if (!eventClass.isInstance(event)) return; -+ try { -+ handle.invoke(event); -+ } catch (Throwable throwable) { -+ SneakyThrow.sneaky(throwable); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b6e7d8ee8d903ebf975d60bec0e08603d9a49fdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java -@@ -0,0 +1,47 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import java.lang.reflect.Method; -+import java.util.concurrent.atomic.AtomicInteger; -+ -+import org.bukkit.plugin.EventExecutor; -+import org.jetbrains.annotations.NotNull; -+import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.Type; -+import org.objectweb.asm.commons.GeneratorAdapter; -+ -+import static org.objectweb.asm.Opcodes.*; -+ -+public class ASMEventExecutorGenerator { -+ @NotNull -+ public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) { -+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); -+ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)}); -+ // Generate constructor -+ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "", "()V", null, null), ACC_PUBLIC, "", "()V"); -+ methodGenerator.loadThis(); -+ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); // Invoke the super class (Object) constructor -+ methodGenerator.returnValue(); -+ methodGenerator.endMethod(); -+ // Generate the execute method -+ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");; -+ methodGenerator.loadArg(0); -+ methodGenerator.checkCast(Type.getType(m.getDeclaringClass())); -+ methodGenerator.loadArg(1); -+ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0])); -+ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface()); -+ if (m.getReturnType() != void.class) { -+ methodGenerator.pop(); -+ } -+ methodGenerator.returnValue(); -+ methodGenerator.endMethod(); -+ writer.visitEnd(); -+ return writer.toByteArray(); -+ } -+ -+ public static AtomicInteger NEXT_ID = new AtomicInteger(1); -+ @NotNull -+ public static String generateName() { -+ int id = NEXT_ID.getAndIncrement(); -+ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f79685b48bb581277a6891927988b6f7a4389dc4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java -@@ -0,0 +1,34 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import org.jetbrains.annotations.NotNull; -+ -+public interface ClassDefiner { -+ -+ /** -+ * Returns if the defined classes can bypass access checks -+ * -+ * @return if classes bypass access checks -+ */ -+ public default boolean isBypassAccessChecks() { -+ return false; -+ } -+ -+ /** -+ * Define a class -+ * -+ * @param parentLoader the parent classloader -+ * @param name the name of the class -+ * @param data the class data to load -+ * @return the defined class -+ * @throws ClassFormatError if the class data is invalid -+ * @throws NullPointerException if any of the arguments are null -+ */ -+ @NotNull -+ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data); -+ -+ @NotNull -+ public static ClassDefiner getInstance() { -+ return SafeClassDefiner.INSTANCE; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ac99477e9f2c08041aeff31abc1d1edee58d0a67 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.event.executor.asm; -+ -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentMap; -+ -+import com.google.common.base.Preconditions; -+ -+import com.google.common.collect.MapMaker; -+import org.jetbrains.annotations.NotNull; -+import org.objectweb.asm.Type; -+ -+public class SafeClassDefiner implements ClassDefiner { -+ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner(); -+ -+ private SafeClassDefiner() {} -+ -+ private final ConcurrentMap loaders = new MapMaker().weakKeys().makeMap(); -+ -+ @NotNull -+ @Override -+ public Class defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) { -+ GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new); -+ synchronized (loader.getClassLoadingLock(name)) { -+ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name); -+ Class c = loader.define(name, data); -+ assert c.getName().equals(name); -+ return c; -+ } -+ } -+ -+ private static class GeneratedClassLoader extends ClassLoader { -+ static { -+ ClassLoader.registerAsParallelCapable(); -+ } -+ -+ protected GeneratedClassLoader(@NotNull ClassLoader parent) { -+ super(parent); -+ } -+ -+ private Class define(@NotNull String name, byte[] data) { -+ synchronized (getClassLoadingLock(name)) { -+ assert !hasClass(name); -+ Class c = defineClass(name, data, 0, data.length); -+ resolveClass(c); -+ return c; -+ } -+ } -+ -+ @Override -+ @NotNull -+ public Object getClassLoadingLock(@NotNull String name) { -+ return super.getClassLoadingLock(name); -+ } -+ -+ public boolean hasClass(@NotNull String name) { -+ synchronized (getClassLoadingLock(name)) { -+ try { -+ Class.forName(name); -+ return true; -+ } catch (ClassNotFoundException e) { -+ return false; -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java -index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644 ---- a/src/main/java/org/bukkit/plugin/EventExecutor.java -+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java -@@ -5,9 +5,75 @@ import org.bukkit.event.EventException; - import org.bukkit.event.Listener; - import org.jetbrains.annotations.NotNull; - -+// Paper start -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentMap; -+import java.util.function.Function; -+ -+import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; -+import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor; -+import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; -+import com.destroystokyo.paper.event.executor.asm.ClassDefiner; -+import com.google.common.base.Preconditions; -+// Paper end -+ - /** - * Interface which defines the class for event call backs to plugins - */ - public interface EventExecutor { - public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException; -+ -+ // Paper start -+ ConcurrentMap> eventExecutorMap = new ConcurrentHashMap>() { -+ @NotNull -+ @Override -+ public Class computeIfAbsent(@NotNull Method key, @NotNull Function> mappingFunction) { -+ Class executorClass = get(key); -+ if (executorClass != null) -+ return executorClass; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (key) { -+ executorClass = get(key); -+ if (executorClass != null) -+ return executorClass; -+ -+ return super.computeIfAbsent(key, mappingFunction); -+ } -+ } -+ }; -+ -+ @NotNull -+ public static EventExecutor create(@NotNull Method m, @NotNull Class eventClass) { -+ Preconditions.checkNotNull(m, "Null method"); -+ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); -+ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); -+ ClassDefiner definer = ClassDefiner.getInstance(); -+ if (Modifier.isStatic(m.getModifiers())) { -+ return new StaticMethodHandleEventExecutor(eventClass, m); -+ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { -+ // get the existing generated EventExecutor class for the Method or generate one -+ Class executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { -+ String name = ASMEventExecutorGenerator.generateName(); -+ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); -+ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); -+ }); -+ -+ try { -+ EventExecutor asmExecutor = executorClass.newInstance(); -+ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) -+ return (listener, event) -> { -+ if (!eventClass.isInstance(event)) return; -+ asmExecutor.execute(listener, event); -+ }; -+ } catch (InstantiationException | IllegalAccessException e) { -+ throw new AssertionError("Unable to initialize generated event executor", e); -+ } -+ } else { -+ return new MethodHandleEventExecutor(eventClass, m); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 2e306c7b984a02e12a74fac14589bf29ab6488bf..79ac529017aac059d13fe342f279e9c8faeba599 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -291,21 +291,7 @@ public final class JavaPluginLoader implements PluginLoader { - } - } - -- EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper -- @Override -- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper -- try { -- if (!eventClass.isAssignableFrom(event.getClass())) { -- return; -- } -- method.invoke(listener, event); -- } catch (InvocationTargetException ex) { -- throw new EventException(ex.getCause()); -- } catch (Throwable t) { -- throw new EventException(t); -- } -- } -- }, plugin, method, eventClass); // Paper -+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); // Paper // Paper (Yes.) - Use factory method `EventExecutor.create()` - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { diff --git a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch deleted file mode 100644 index ebb524d78104..000000000000 --- a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:28:07 -0400 -Subject: [PATCH] Add command to reload permissions.yml and require confirm to - reload - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 22b83b142de97dcba28fa9a49730de7880d0b5d2..945d75525465739dd30610dff985ea0fb0f1c8df 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1740,6 +1740,13 @@ public final class Bukkit { - public static org.bukkit.command.CommandMap getCommandMap() { - return server.getCommandMap(); - } -+ -+ /** -+ * Reload the Permissions in permissions.yml -+ */ -+ public static void reloadPermissions() { -+ server.reloadPermissions(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9ce9b4ce2da6c57c62607502ae2042e30fc26d88..f69c30ebea9c9e9add0b6c97994be0ce64a80ad3 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1538,4 +1538,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - Spigot spigot(); - // Spigot end -+ -+ void reloadPermissions(); // Paper - } -diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..c62da4131b17e66892678e8b618fb9ba3de93b56 100644 ---- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand { - public ReloadCommand(@NotNull String name) { - super(name); - this.description = "Reloads the server configuration and plugins"; -- this.usageMessage = "/reload"; -+ this.usageMessage = "/reload [permissions]"; // Paper - this.setPermission("bukkit.command.reload"); - this.setAliases(Arrays.asList("rl")); - } - - @Override -- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { -+ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper - if (!testPermission(sender)) return true; - -+ // Paper start - Reload permissions.yml & require confirm -+ boolean confirmed = System.getProperty("LetMeReload") != null; -+ if (args.length == 1) { -+ if (args[0].equalsIgnoreCase("permissions")) { -+ Bukkit.getServer().reloadPermissions(); -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); -+ return true; -+ } else if ("confirm".equalsIgnoreCase(args[0])) { -+ confirmed = true; -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Usage: " + usageMessage); -+ return true; -+ } -+ } -+ if (!confirmed) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type " + ChatColor.YELLOW + "/reload confirm"); -+ return true; -+ } -+ // Paper end -+ - Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins."); - Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); - Bukkit.reload(); -@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand { - @NotNull - @Override - public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { -- return Collections.emptyList(); -+ return java.util.Collections.singletonList("permissions"); // Paper - } - } -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index d0fec44d2546290091649879450761ce08514fcb..8b33d914d29897c0276f9e2e7ce83bd2c316d5e2 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -894,4 +894,13 @@ public final class SimplePluginManager implements PluginManager { - public void useTimings(boolean use) { - co.aikar.timings.Timings.setTimingsEnabled(use); // Paper - } -+ -+ // Paper start -+ public void clearPermissions() { -+ permissions.clear(); -+ defaultPerms.get(true).clear(); -+ defaultPerms.get(false).clear(); -+ } -+ // Paper end -+ - } diff --git a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch b/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index 94ff9d88e2aa..000000000000 --- a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:05:21 -0400 -Subject: [PATCH] Custom replacement for eaten items - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -index c2793f3ef01c1246c130971c17e1c2bf8f551435..373f4b5b5185aa81ff728da89c9cc4e0ccf87889 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java -@@ -22,6 +22,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean isCancelled = false; - private ItemStack item; -+ @Nullable private ItemStack replacement; // Paper - - /** - * @param player the player consuming -@@ -58,6 +59,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { - } - } - -+ // Paper start -+ /** -+ * Return the custom item stack that will replace the consumed item, or null if no -+ * custom replacement has been set (which means the default replacement will be used). -+ * -+ * @return The custom item stack that will replace the consumed item or null -+ */ -+ @Nullable -+ public ItemStack getReplacement() { -+ return this.replacement; -+ } -+ -+ /** -+ * Set a custom item stack to replace the consumed item. Pass null to clear any custom -+ * stack that has been set and use the default replacement. -+ * -+ * @param replacement Replacement item to set, null to clear any custom stack and use default -+ */ -+ public void setReplacement(@Nullable ItemStack replacement) { -+ this.replacement = replacement; -+ } -+ // Paper end -+ - @Override - public boolean isCancelled() { - return this.isCancelled; diff --git a/Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 5dc11c88f891..000000000000 --- a/Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:26:34 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..07660202e41ee86f1b66bad3335cf6fe126e7f9c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity is being added to the world for any reason. -+ * -+ * Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent} -+ * This will fire anytime a chunk is reloaded too. -+ */ -+public class EntityAddToWorldEvent extends EntityEvent { -+ -+ public EntityAddToWorldEvent(@NotNull Entity entity) { -+ super(entity); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e5dbbd660409bae0d3b96e83390511d3a423a52e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity is being removed from a world for any reason -+ */ -+public class EntityRemoveFromWorldEvent extends EntityEvent { -+ -+ public EntityRemoveFromWorldEvent(@NotNull Entity entity) { -+ super(entity); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0029-EntityPathfindEvent.patch b/Spigot-API-Patches/0029-EntityPathfindEvent.patch deleted file mode 100644 index 697b76661aca..000000000000 --- a/Spigot-API-Patches/0029-EntityPathfindEvent.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:15:34 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..63e46b2fb1b12b36fcb1e98b178cf29dd2e3d1b5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java -@@ -0,0 +1,82 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when an Entity decides to start moving towards a location. -+ * -+ * This event does not fire for the entities actual movement. Only when it -+ * is choosing to start moving to a location. -+ */ -+public class EntityPathfindEvent extends EntityEvent implements Cancellable { -+ @Nullable private final Entity targetEntity; -+ @NotNull private final Location loc; -+ -+ public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) { -+ super(entity); -+ this.targetEntity = targetEntity; -+ this.loc = loc; -+ } -+ -+ /** -+ * The Entity that is pathfinding. -+ * @return The Entity that is pathfinding. -+ */ -+ @NotNull -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * If the Entity is trying to pathfind to an entity, this is the entity in relation. -+ * -+ * Otherwise this will return null. -+ * -+ * @return The entity target or null -+ */ -+ @Nullable -+ public Entity getTargetEntity() { -+ return targetEntity; -+ } -+ -+ /** -+ * The Location of where the entity is about to move to. -+ * -+ * Note that if the target happened to of been an entity -+ * @return Location of where the entity is trying to pathfind to. -+ */ -+ @NotNull -+ public Location getLoc() { -+ return loc; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch deleted file mode 100644 index d4674ca2f47e..000000000000 --- a/Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: crast -Date: Sat, 1 Jun 2013 13:52:30 -0600 -Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase - -Use ConcurrentHashMap to allow thread-safe access methods and very -limited synchronized portions to allow much higher concurrency in -MetadataStore as well as far less locking, especially on reads - -diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -index baf850226aed8545a5794deba6dff9603953b4b2..d363d517c05b3335101d829ce4ec22d049059c24 100644 ---- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin; - import org.jetbrains.annotations.NotNull; - - public abstract class MetadataStoreBase { -- private Map> metadataMap = new HashMap>(); -+ private Map> metadataMap = new java.util.concurrent.ConcurrentHashMap>(); // Paper - - /** - * Adds a metadata value to an object. Each metadata value is owned by a -@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase { - entry = new WeakHashMap(1); - metadataMap.put(key, entry); - } -- entry.put(owningPlugin, newMetadataValue); -+ synchronized (entry) { -+ entry.put(owningPlugin, newMetadataValue); -+ } - } - - /** -@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase { - * @see MetadataStore#getMetadata(Object, String) - */ - @NotNull -- public synchronized List getMetadata(@NotNull T subject, @NotNull String metadataKey) { -+ public List getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper - String key = disambiguate(subject, metadataKey); -- if (metadataMap.containsKey(key)) { -- Collection values = metadataMap.get(key).values(); -+ Map entry = metadataMap.get(key); -+ if (entry != null) { -+ Collection values = entry.values(); - return Collections.unmodifiableList(new ArrayList(values)); - } else { - return Collections.emptyList(); -@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase { - * @param metadataKey the unique metadata key being queried. - * @return the existence of the metadataKey within subject. - */ -- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { -+ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper - String key = disambiguate(subject, metadataKey); - return metadataMap.containsKey(key); - } -@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase { - * @see MetadataStore#removeMetadata(Object, String, - * org.bukkit.plugin.Plugin) - */ -- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { -+ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper - Validate.notNull(owningPlugin, "Plugin cannot be null"); - String key = disambiguate(subject, metadataKey); - Map entry = metadataMap.get(key); - if (entry == null) { - return; - } -- -- entry.remove(owningPlugin); -- if (entry.isEmpty()) { -- metadataMap.remove(key); -+ synchronized (entry) { -+ entry.remove(owningPlugin); -+ if (entry.isEmpty()) { -+ metadataMap.remove(key); -+ } - } - } - -@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase { - * @throws IllegalArgumentException If plugin is null - * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) - */ -- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) { -+ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper - Validate.notNull(owningPlugin, "Plugin cannot be null"); - for (Map values : metadataMap.values()) { - if (values.containsKey(owningPlugin)) { diff --git a/Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch b/Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch deleted file mode 100644 index d15d19b31607..000000000000 --- a/Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 16 Jul 2013 21:26:50 -0400 -Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin) - -So that on reload, metadata will be cleared - -diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -index d363d517c05b3335101d829ce4ec22d049059c24..abbe545af572687a0399c2387434863cd2b70f68 100644 ---- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java -@@ -4,6 +4,7 @@ import java.util.ArrayList; - import java.util.Collection; - import java.util.Collections; - import java.util.HashMap; -+import java.util.Iterator; // Paper - import java.util.List; - import java.util.Map; - import java.util.WeakHashMap; -@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase { - } - } - -+ /** -+ * Removes all metadata in the metadata store that originates from the -+ * given plugin. -+ * -+ * @param owningPlugin the plugin requesting the invalidation. -+ * @throws IllegalArgumentException If plugin is null -+ */ -+ public void removeAll(@NotNull Plugin owningPlugin) { -+ Validate.notNull(owningPlugin, "Plugin cannot be null"); -+ for (Iterator> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) { -+ Map values = iterator.next(); -+ if (values.containsKey(owningPlugin)) { -+ values.remove(owningPlugin); -+ } -+ if (values.isEmpty()) { -+ iterator.remove(); -+ } -+ } -+ } -+ - /** - * Creates a unique name for the object receiving metadata by combining - * unique data from the subject with a metadataKey. diff --git a/Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch b/Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 8fa59475c298..000000000000 --- a/Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:08:36 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..09cfdf48ead8f03f3497646537292174241b0868 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.jetbrains.annotations.NotNull; -+ -+public class PlayerUseUnknownEntityEvent extends PlayerEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int entityId; -+ private final boolean attack; -+ @NotNull private final EquipmentSlot hand; -+ -+ public PlayerUseUnknownEntityEvent(@NotNull Player who, int entityId, boolean attack, @NotNull EquipmentSlot hand) { -+ super(who); -+ this.entityId = entityId; -+ this.attack = attack; -+ this.hand = hand; -+ } -+ -+ public int getEntityId() { -+ return this.entityId; -+ } -+ -+ public boolean isAttack() { -+ return this.attack; -+ } -+ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return this.hand; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index eb1703e48534..000000000000 --- a/Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 13 Apr 2016 20:20:18 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a077962fa786a3291849abfa823c7f0ec4664fce ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java -@@ -0,0 +1,277 @@ -+package com.destroystokyo.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * This event is fired during a player handshake. -+ * -+ *

If there are no listeners listening to this event, the logic default -+ * to your server platform will be ran.

-+ * -+ *

WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

-+ */ -+public class PlayerHandshakeEvent extends Event implements Cancellable { -+ -+ private static final HandlerList HANDLERS = new HandlerList(); -+ @NotNull private final String originalHandshake; -+ @NotNull private final String originalSocketAddressHostname; -+ private boolean cancelled; -+ @Nullable private String serverHostname; -+ @Nullable private String socketAddressHostname; -+ @Nullable private UUID uniqueId; -+ @Nullable private String propertiesJson; -+ private boolean failed; -+ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW); -+ -+ /** -+ * Creates a new {@link PlayerHandshakeEvent}. -+ * -+ * @param originalHandshake the original handshake string -+ * @param cancelled if this event is enabled -+ * -+ * @deprecated in favour of {@link PlayerHandshakeEvent(String, String, boolean)} -+ */ -+ @Deprecated -+ public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) { -+ this(originalHandshake, "127.0.0.1", cancelled); -+ } -+ -+ /** -+ * Creates a new {@link PlayerHandshakeEvent}. -+ * -+ * @param originalHandshake the original handshake string -+ * @param originalSocketAddressHostname the original socket address hostname -+ * @param cancelled if this event is enabled -+ */ -+ public PlayerHandshakeEvent(@NotNull String originalHandshake, @NotNull String originalSocketAddressHostname, boolean cancelled) { -+ super(true); -+ this.originalHandshake = originalHandshake; -+ this.originalSocketAddressHostname = originalSocketAddressHostname; -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Determines if this event is cancelled. -+ * -+ *

When this event is cancelled, custom handshake logic will not -+ * be processed.

-+ * -+ * @return {@code true} if this event is cancelled, {@code false} otherwise -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets if this event is cancelled. -+ * -+ *

When this event is cancelled, custom handshake logic will not -+ * be processed.

-+ * -+ * @param cancelled {@code true} if this event is cancelled, {@code false} otherwise -+ */ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the original handshake string. -+ * -+ * @return the original handshake string -+ */ -+ @NotNull -+ public String getOriginalHandshake() { -+ return this.originalHandshake; -+ } -+ -+ /** -+ * Gets the original socket address hostname. -+ * -+ *

This does not include the port.

-+ *

In cases where this event is manually fired and the plugin wasn't updated yet, the default is {@code "127.0.0.1"}.

-+ * -+ * @return the original socket address hostname -+ */ -+ @NotNull -+ public String getOriginalSocketAddressHostname() { -+ return this.originalSocketAddressHostname; -+ } -+ -+ /** -+ * Gets the server hostname string. -+ * -+ *

This should not include the port.

-+ * -+ * @return the server hostname string -+ */ -+ @Nullable -+ public String getServerHostname() { -+ return this.serverHostname; -+ } -+ -+ /** -+ * Sets the server hostname string. -+ * -+ *

This should not include the port.

-+ * -+ * @param serverHostname the server hostname string -+ */ -+ public void setServerHostname(@NotNull String serverHostname) { -+ this.serverHostname = serverHostname; -+ } -+ -+ /** -+ * Gets the socket address hostname string. -+ * -+ *

This should not include the port.

-+ * -+ * @return the socket address hostname string -+ */ -+ @Nullable -+ public String getSocketAddressHostname() { -+ return this.socketAddressHostname; -+ } -+ -+ /** -+ * Sets the socket address hostname string. -+ * -+ *

This should not include the port.

-+ * -+ * @param socketAddressHostname the socket address hostname string -+ */ -+ public void setSocketAddressHostname(@NotNull String socketAddressHostname) { -+ this.socketAddressHostname = socketAddressHostname; -+ } -+ -+ /** -+ * Gets the unique id. -+ * -+ * @return the unique id -+ */ -+ @Nullable -+ public UUID getUniqueId() { -+ return this.uniqueId; -+ } -+ -+ /** -+ * Sets the unique id. -+ * -+ * @param uniqueId the unique id -+ */ -+ public void setUniqueId(@NotNull UUID uniqueId) { -+ this.uniqueId = uniqueId; -+ } -+ -+ /** -+ * Gets the profile properties. -+ * -+ *

This should be a valid JSON string.

-+ * -+ * @return the profile properties, as JSON -+ */ -+ @Nullable -+ public String getPropertiesJson() { -+ return this.propertiesJson; -+ } -+ -+ /** -+ * Determines if authentication failed. -+ * -+ *

When {@code true}, the client connecting will be disconnected -+ * with the {@link #getFailMessage() fail message}.

-+ * -+ * @return {@code true} if authentication failed, {@code false} otherwise -+ */ -+ public boolean isFailed() { -+ return this.failed; -+ } -+ -+ /** -+ * Sets if authentication failed and the client should be disconnected. -+ * -+ *

When {@code true}, the client connecting will be disconnected -+ * with the {@link #getFailMessage() fail message}.

-+ * -+ * @param failed {@code true} if authentication failed, {@code false} otherwise -+ */ -+ public void setFailed(boolean failed) { -+ this.failed = failed; -+ } -+ -+ /** -+ * Sets the profile properties. -+ * -+ *

This should be a valid JSON string.

-+ * -+ * @param propertiesJson the profile properties, as JSON -+ */ -+ public void setPropertiesJson(@NotNull String propertiesJson) { -+ this.propertiesJson = propertiesJson; -+ } -+ -+ /** -+ * Gets the message to display to the client when authentication fails. -+ * -+ * @return the message to display to the client -+ */ -+ @NotNull -+ public Component failMessage() { -+ return this.failMessage; -+ } -+ -+ /** -+ * Sets the message to display to the client when authentication fails. -+ * -+ * @param failMessage the message to display to the client -+ */ -+ public void failMessage(@NotNull Component failMessage) { -+ this.failMessage = failMessage; -+ } -+ -+ /** -+ * Gets the message to display to the client when authentication fails. -+ * -+ * @return the message to display to the client -+ * @deprecated use {@link #failMessage()} -+ */ -+ @NotNull -+ @Deprecated -+ public String getFailMessage() { -+ return Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.failMessage()); -+ } -+ -+ /** -+ * Sets the message to display to the client when authentication fails. -+ * -+ * @param failMessage the message to display to the client -+ * @deprecated use {@link #failMessage(Component)} -+ */ -+ @Deprecated -+ public void setFailMessage(@NotNull String failMessage) { -+ Validate.notEmpty(failMessage, "fail message cannot be null or empty"); -+ this.failMessage(Bukkit.getUnsafe().legacyComponentSerializer().deserialize(failMessage)); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} diff --git a/Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch b/Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch deleted file mode 100644 index fb3753f0e176..000000000000 --- a/Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Fri, 4 Mar 2016 03:13:18 -0500 -Subject: [PATCH] Arrow pickup rule API - - -diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java -index 5b50a4e10e8ace8cc53ad3c8d7c3185f88d5c8db..e8e56e89e32d84af0639fe2e9b0eeabd747b6007 100644 ---- a/src/main/java/org/bukkit/entity/AbstractArrow.java -+++ b/src/main/java/org/bukkit/entity/AbstractArrow.java -@@ -141,4 +141,38 @@ public interface AbstractArrow extends Projectile { - */ - CREATIVE_ONLY - } -+ -+ // Paper start -+ /** -+ * Gets the {@link PickupRule} for this arrow. -+ * -+ *

This is generally {@link PickupRule#ALLOWED} only if the arrow was -+ * not fired from a bow with the infinity enchantment.

-+ * -+ * @return The pickup rule -+ * @deprecated Use {@link Arrow#getPickupStatus()} as an upstream compatible replacement for this function -+ */ -+ @Deprecated -+ default PickupRule getPickupRule() { -+ return PickupRule.valueOf(this.getPickupStatus().name()); -+ } -+ -+ /** -+ * Set the rule for which players can pickup this arrow as an item. -+ * -+ * @param rule The pickup rule -+ * @deprecated Use {@link Arrow#setPickupStatus(PickupStatus)} with {@link PickupStatus} as an upstream compatible replacement for this function -+ */ -+ @Deprecated -+ default void setPickupRule(PickupRule rule) { -+ this.setPickupStatus(PickupStatus.valueOf(rule.name())); -+ } -+ -+ @Deprecated -+ enum PickupRule { -+ DISALLOWED, -+ ALLOWED, -+ CREATIVE_ONLY; -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0036-LootTable-API.patch b/Spigot-API-Patches/0036-LootTable-API.patch deleted file mode 100644 index 8c3b9e180757..000000000000 --- a/Spigot-API-Patches/0036-LootTable-API.patch +++ /dev/null @@ -1,402 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 15:19:49 -0400 -Subject: [PATCH] LootTable API - -Provides API to control what Loot Table an object uses. - -Also provides an Event to control if a lootable inventory should -auto replenish for a player. - -Provides methods to determine players looted state for an object - -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..92d7b853a2ccaae5afa8ac141bead840942944ef ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.block.Block; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts -+ */ -+public interface LootableBlockInventory extends LootableInventory { -+ -+ /** -+ * Gets the block that is lootable -+ * @return The Block -+ */ -+ @NotNull -+ Block getBlock(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b387894fe8001edb41ad2ad2b70ebabe065b682e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Entity; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts -+ */ -+public interface LootableEntityInventory extends LootableInventory { -+ -+ /** -+ * Gets the entity that is lootable -+ * @return The Entity -+ */ -+ @NotNull -+ Entity getEntity(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..97815eeb231cf0706b34fa47a4f7d1bb786305b4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java -@@ -0,0 +1,116 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.loot.Lootable; -+ -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents an Inventory that contains a Loot Table associated to it that will -+ * automatically fill on first open. -+ * -+ * A new feature and API is provided to support automatically refreshing the contents -+ * of the inventory based on that Loot Table after a configurable amount of time has passed. -+ * -+ * The behavior of how the Inventory is filled based on the loot table may vary based -+ * on Minecraft versions and the Loot Table feature. -+ */ -+public interface LootableInventory extends Lootable { -+ -+ /** -+ * Server owners have to enable whether or not an object in a world should refill -+ * -+ * @return If the world this inventory is currently in has Replenishable Lootables enabled -+ */ -+ boolean isRefillEnabled(); -+ -+ /** -+ * Whether or not this object has ever been filled -+ * @return Has ever been filled -+ */ -+ boolean hasBeenFilled(); -+ -+ /** -+ * Has this player ever looted this block -+ * @param player The player to check -+ * @return Whether or not this player has looted this block -+ */ -+ default boolean hasPlayerLooted(@NotNull Player player) { -+ return hasPlayerLooted(player.getUniqueId()); -+ } -+ -+ /** -+ * Has this player ever looted this block -+ * @param player The player to check -+ * @return Whether or not this player has looted this block -+ */ -+ boolean hasPlayerLooted(@NotNull UUID player); -+ -+ /** -+ * Gets the timestamp, in milliseconds, of when the player last looted this object -+ * -+ * @param player The player to check -+ * @return Timestamp last looted, or null if player has not looted this object -+ */ -+ @Nullable -+ default Long getLastLooted(@NotNull Player player) { -+ return getLastLooted(player.getUniqueId()); -+ } -+ -+ /** -+ * Gets the timestamp, in milliseconds, of when the player last looted this object -+ * -+ * @param player The player to check -+ * @return Timestamp last looted, or null if player has not looted this object -+ */ -+ @Nullable -+ Long getLastLooted(@NotNull UUID player); -+ -+ /** -+ * Change the state of whether or not a player has looted this block -+ * @param player The player to change state for -+ * @param looted true to add player to looted list, false to remove -+ * @return The previous state of whether the player had looted this or not -+ */ -+ default boolean setHasPlayerLooted(@NotNull Player player, boolean looted) { -+ return setHasPlayerLooted(player.getUniqueId(), looted); -+ } -+ -+ /** -+ * Change the state of whether or not a player has looted this block -+ * @param player The player to change state for -+ * @param looted true to add player to looted list, false to remove -+ * @return The previous state of whether the player had looted this or not -+ */ -+ boolean setHasPlayerLooted(@NotNull UUID player, boolean looted); -+ -+ /** -+ * Returns Whether or not this object has been filled and now has a pending refill -+ * @return Has pending refill -+ */ -+ boolean hasPendingRefill(); -+ -+ /** -+ * Gets the timestamp in milliseconds that the Lootable object was last refilled -+ * -+ * @return -1 if it was never refilled, or timestamp in milliseconds -+ */ -+ long getLastFilled(); -+ -+ /** -+ * Gets the timestamp in milliseconds that the Lootable object will refill -+ * -+ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds -+ */ -+ long getNextRefill(); -+ -+ /** -+ * Sets the timestamp in milliseconds of the next refill for this object -+ * -+ * @param refillAt timestamp in milliseconds. -1 to clear next refill -+ * @return The previous scheduled time to refill, or -1 if was not scheduled -+ */ -+ long setNextRefill(long refillAt); -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fd184f13f5e8ee5cf829fff4f44696e1f760430b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.loottable; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable { -+ @NotNull private final LootableInventory inventory; -+ -+ public LootableInventoryReplenishEvent(@NotNull Player player, @NotNull LootableInventory inventory) { -+ super(player); -+ this.inventory = inventory; -+ } -+ -+ @NotNull -+ public LootableInventory getInventory() { -+ return inventory; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java -index b451191312e4fb19f2131c2d0a0c0337953f6c7c..db6affbc78106b2d93b41953b624a0bca0ca1d72 100644 ---- a/src/main/java/org/bukkit/block/Chest.java -+++ b/src/main/java/org/bukkit/block/Chest.java -@@ -1,5 +1,7 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; // Paper -+import org.bukkit.Nameable; // Paper - import org.bukkit.inventory.Inventory; - import org.bukkit.loot.Lootable; - import org.jetbrains.annotations.NotNull; -@@ -7,7 +9,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a captured state of a chest. - */ --public interface Chest extends Container, Lootable, Lidded { -+public interface Chest extends Container, LootableBlockInventory, Lidded { // Paper - - /** - * Gets the inventory of the chest block represented by this block state. -diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java -index 74cd194c9a98245dc52e7e352d7d6c046e1e5cf3..07af1a3f011d4b96275f919d302ac367198e923e 100644 ---- a/src/main/java/org/bukkit/block/Dispenser.java -+++ b/src/main/java/org/bukkit/block/Dispenser.java -@@ -1,5 +1,6 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.Nameable; - import org.bukkit.loot.Lootable; - import org.bukkit.projectiles.BlockProjectileSource; -@@ -8,7 +9,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a captured state of a dispenser. - */ --public interface Dispenser extends Container, Nameable, Lootable { -+public interface Dispenser extends Container, Nameable, LootableBlockInventory { // Paper - - /** - * Gets the BlockProjectileSource object for the dispenser. -diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java -index 424392fb5ed4628199b0e73689522aa3c90740cb..c76202321e29ad67597ca3017eb8d9baf6787383 100644 ---- a/src/main/java/org/bukkit/block/Dropper.java -+++ b/src/main/java/org/bukkit/block/Dropper.java -@@ -1,11 +1,12 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.loot.Lootable; - - /** - * Represents a captured state of a dropper. - */ --public interface Dropper extends Container, Lootable { -+public interface Dropper extends Container, LootableBlockInventory { // Paper - - /** - * Tries to drop a randomly selected item from the dropper's inventory, -diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java -index 58e493099810fb8d4705ecd49b4a5e1e1949b87b..7ade312f180b7e30871d3a3240c76325cc369c26 100644 ---- a/src/main/java/org/bukkit/block/Hopper.java -+++ b/src/main/java/org/bukkit/block/Hopper.java -@@ -1,8 +1,9 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.loot.Lootable; - - /** - * Represents a captured state of a hopper. - */ --public interface Hopper extends Container, Lootable { } -+public interface Hopper extends Container, LootableBlockInventory { } // Paper -diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java -index 2ab26605814c0745ddb0836b2b3618a5b9251ab7..172f383fea619127324fec2b043639fd0683f135 100644 ---- a/src/main/java/org/bukkit/block/ShulkerBox.java -+++ b/src/main/java/org/bukkit/block/ShulkerBox.java -@@ -1,5 +1,6 @@ - package org.bukkit.block; - -+import com.destroystokyo.paper.loottable.LootableBlockInventory; - import org.bukkit.DyeColor; - import org.bukkit.loot.Lootable; - import org.jetbrains.annotations.NotNull; -@@ -7,7 +8,7 @@ import org.jetbrains.annotations.NotNull; - /** - * Represents a captured state of a ShulkerBox. - */ --public interface ShulkerBox extends Container, Lootable, Lidded { -+public interface ShulkerBox extends Container, LootableBlockInventory, Lidded { // Paper - - /** - * Get the {@link DyeColor} corresponding to this ShulkerBox -diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -index 937b99f8734d71b2ad33af142afbc251b81d9745..db69687a7ad4b18d17ab1677cae5d8dd4dcd3678 100644 ---- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity.minecart; - -+import com.destroystokyo.paper.loottable.LootableEntityInventory; - import org.bukkit.entity.Minecart; - import org.bukkit.inventory.InventoryHolder; - import org.bukkit.loot.Lootable; -@@ -7,7 +8,7 @@ import org.bukkit.loot.Lootable; - /** - * Represents a Minecart with a Hopper inside it - */ --public interface HopperMinecart extends Minecart, InventoryHolder, Lootable { -+public interface HopperMinecart extends Minecart, InventoryHolder, LootableEntityInventory { - - /** - * Checks whether or not this Minecart will pick up -diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -index 9ea403e6fd8e960d017660e0aec118abeda2c42b..238d118f7788b13cd86b7e9ea3a0fc38e2e09715 100644 ---- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -+++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity.minecart; - -+import com.destroystokyo.paper.loottable.LootableEntityInventory; - import org.bukkit.entity.Minecart; - import org.bukkit.inventory.InventoryHolder; - import org.bukkit.loot.Lootable; -@@ -9,5 +10,5 @@ import org.bukkit.loot.Lootable; - * minecarts} have their own inventory that can be accessed using methods - * from the {@link InventoryHolder} interface. - */ --public interface StorageMinecart extends Minecart, InventoryHolder, Lootable { -+public interface StorageMinecart extends Minecart, InventoryHolder, LootableEntityInventory { // Paper - } -diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java -index 24a3d989db3bc67e7afe8459a3d4bb132f448ea7..901db852498e0658c79a57582508dab29bf0a798 100644 ---- a/src/main/java/org/bukkit/loot/Lootable.java -+++ b/src/main/java/org/bukkit/loot/Lootable.java -@@ -36,6 +36,34 @@ public interface Lootable { - @Nullable - LootTable getLootTable(); - -+ // Paper start -+ /** -+ * Set the loot table and seed for a container or entity at the same time. -+ * -+ * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have. -+ * @param seed the seed to used to generate loot. Default is 0. -+ */ -+ default void setLootTable(@Nullable LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ /** -+ * Returns whether or not this object has a Loot Table -+ * @return Has a loot table -+ */ -+ default boolean hasLootTable() { -+ return getLootTable() != null; -+ } -+ -+ /** -+ * Clears the associated Loot Table to this object -+ */ -+ default void clearLootTable() { -+ setLootTable(null); -+ } -+ // Paper end -+ - /** - * Set the seed used when this Loot Table generates loot. - * diff --git a/Spigot-API-Patches/0037-Add-EntityZapEvent.patch b/Spigot-API-Patches/0037-Add-EntityZapEvent.patch deleted file mode 100644 index 41d603f0739e..000000000000 --- a/Spigot-API-Patches/0037-Add-EntityZapEvent.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:34 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3b725a489008d333630af166d2be5fc48168a6b9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java -@@ -0,0 +1,65 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.apache.commons.lang.Validate; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LightningStrike; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.event.entity.EntityTransformEvent; -+ -+import java.util.Collections; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when lightning strikes an entity -+ */ -+public class EntityZapEvent extends EntityTransformEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final LightningStrike bolt; -+ -+ public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) { -+ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING); -+ Validate.notNull(bolt); -+ Validate.notNull(replacementEntity); -+ this.bolt = bolt; -+ } -+ -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ /** -+ * Gets the lightning bolt that is striking the entity. -+ * @return The lightning bolt responsible for this event -+ */ -+ @NotNull -+ public LightningStrike getBolt() { -+ return bolt; -+ } -+ -+ /** -+ * Gets the entity that will replace the struck entity. -+ * @return The entity that will replace the struck entity -+ */ -+ @NotNull -+ public Entity getReplacementEntity() { -+ return getTransformedEntity(); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/entity/PigZapEvent.java b/src/main/java/org/bukkit/event/entity/PigZapEvent.java -index 0e0ed93b568fd2c0d8f6e359c31dc29cb0fa71c2..d3949edfc736b3d67a627ef378748b374769e183 100644 ---- a/src/main/java/org/bukkit/event/entity/PigZapEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PigZapEvent.java -@@ -2,6 +2,7 @@ package org.bukkit.event.entity; - - import java.util.Collections; - import org.bukkit.entity.Entity; -+import com.destroystokyo.paper.event.entity.EntityZapEvent; - import org.bukkit.entity.LightningStrike; - import org.bukkit.entity.Pig; - import org.bukkit.entity.PigZombie; -@@ -12,14 +13,14 @@ import org.jetbrains.annotations.NotNull; - /** - * Stores data for pigs being zapped - */ --public class PigZapEvent extends EntityTransformEvent implements Cancellable { -- private static final HandlerList handlers = new HandlerList(); -+public class PigZapEvent extends EntityZapEvent implements Cancellable { -+ //private static final HandlerList handlers = new HandlerList(); - private boolean canceled; - private final PigZombie pigzombie; - private final LightningStrike bolt; - - public PigZapEvent(@NotNull final Pig pig, @NotNull final LightningStrike bolt, @NotNull final PigZombie pigzombie) { -- super(pig, Collections.singletonList((Entity) pigzombie), TransformReason.LIGHTNING); -+ super(pig, bolt, pigzombie); - this.bolt = bolt; - this.pigzombie = pigzombie; - } -@@ -63,6 +64,8 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { - return pigzombie; - } - -+ // Paper start -+ /* - @NotNull - @Override - public HandlerList getHandlers() { -@@ -73,4 +76,6 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ -+ // Paper end - } diff --git a/Spigot-API-Patches/0038-Misc-Utils.patch b/Spigot-API-Patches/0038-Misc-Utils.patch deleted file mode 100644 index fac858b16c88..000000000000 --- a/Spigot-API-Patches/0038-Misc-Utils.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 12:53:43 -0500 -Subject: [PATCH] Misc Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5bb677ce585b856b3d3e589e29786a29619c56a7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java -@@ -0,0 +1,34 @@ -+package com.destroystokyo.paper.utils; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.LongAdder; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class CachedSizeConcurrentLinkedQueue extends ConcurrentLinkedQueue { -+ private final LongAdder cachedSize = new LongAdder(); -+ -+ @Override -+ public boolean add(@NotNull E e) { -+ boolean result = super.add(e); -+ if (result) { -+ cachedSize.increment(); -+ } -+ return result; -+ } -+ -+ @Nullable -+ @Override -+ public E poll() { -+ E result = super.poll(); -+ if (result != null) { -+ cachedSize.decrement(); -+ } -+ return result; -+ } -+ -+ @Override -+ public int size() { -+ return cachedSize.intValue(); -+ } -+} diff --git a/Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch b/Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 69796b58591a..000000000000 --- a/Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:16:39 -0500 -Subject: [PATCH] Allow Reloading of Command Aliases - -Reload the aliases stored in commands.yml - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 945d75525465739dd30610dff985ea0fb0f1c8df..555ef4c187ce0c83cc29af145694ec9c448d452e 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1747,6 +1747,15 @@ public final class Bukkit { - public static void reloadPermissions() { - server.reloadPermissions(); - } -+ -+ /** -+ * Reload the Command Aliases in commands.yml -+ * -+ * @return Whether the reload was successful -+ */ -+ public static boolean reloadCommandAliases() { -+ return server.reloadCommandAliases(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index f69c30ebea9c9e9add0b6c97994be0ce64a80ad3..9d81f25e39d345b797f73855a802b186d77f6d12 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1540,4 +1540,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - // Spigot end - - void reloadPermissions(); // Paper -+ -+ boolean reloadCommandAliases(); // Paper - } -diff --git a/src/main/java/org/bukkit/command/CommandMap.java b/src/main/java/org/bukkit/command/CommandMap.java -index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a884d0731 100644 ---- a/src/main/java/org/bukkit/command/CommandMap.java -+++ b/src/main/java/org/bukkit/command/CommandMap.java -@@ -128,4 +128,14 @@ public interface CommandMap { - */ - @Nullable - public List tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) throws IllegalArgumentException; -+ -+ // Paper start - Expose Known Commands -+ /** -+ * Return a Map of known commands -+ * -+ * @return known commands -+ */ -+ @NotNull -+ public java.util.Map getKnownCommands(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index adfc7aae2c0f49bbcdd358e83b04a0cf078a7d52..460fda05a62b12db2edcfb7ea8b2a5dd8e4b110d 100644 ---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java -+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -297,4 +297,11 @@ public class SimpleCommandMap implements CommandMap { - } - } - } -+ -+ // Paper start - Expose Known Commands -+ @NotNull -+ public Map getKnownCommands() { -+ return knownCommands; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -index c62da4131b17e66892678e8b618fb9ba3de93b56..0c7ba0718de2b93d013968ca0fec34ffd423990f 100644 ---- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -@@ -13,7 +13,7 @@ public class ReloadCommand extends BukkitCommand { - public ReloadCommand(@NotNull String name) { - super(name); - this.description = "Reloads the server configuration and plugins"; -- this.usageMessage = "/reload [permissions]"; // Paper -+ this.usageMessage = "/reload [permissions|commands|confirm]"; // Paper - this.setPermission("bukkit.command.reload"); - this.setAliases(Arrays.asList("rl")); - } -@@ -29,6 +29,13 @@ public class ReloadCommand extends BukkitCommand { - Bukkit.getServer().reloadPermissions(); - Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Permissions successfully reloaded."); - return true; -+ } else if ("commands".equalsIgnoreCase(args[0])) { -+ if (Bukkit.getServer().reloadCommandAliases()) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Command aliases successfully reloaded."); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "An error occurred while trying to reload command aliases."); -+ } -+ return true; - } else if ("confirm".equalsIgnoreCase(args[0])) { - confirmed = true; - } else { -@@ -53,6 +60,6 @@ public class ReloadCommand extends BukkitCommand { - @NotNull - @Override - public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { -- return java.util.Collections.singletonList("permissions"); // Paper -+ return com.google.common.collect.Lists.newArrayList("permissions", "commands"); // Paper - } - } diff --git a/Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch b/Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch deleted file mode 100644 index a5c9df18df3f..000000000000 --- a/Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..453663893021768ae21d4980ce17ffba55d9e129 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when an projectile collides with an entity -+ *

-+ * This event is called before {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying -+ */ -+public class ProjectileCollideEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Entity collidedWith; -+ -+ /** -+ * Get the entity the projectile collided with -+ * -+ * @return the entity collided with -+ */ -+ @NotNull -+ public Entity getCollidedWith() { -+ return collidedWith; -+ } -+ -+ public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) { -+ super(what); -+ this.collidedWith = collidedWith; -+ } -+ -+ /** -+ * Get the projectile that collided -+ * -+ * @return the projectile that collided -+ */ -+ @NotNull -+ public Projectile getEntity() { -+ return (Projectile) super.getEntity(); -+ } -+ -+ private static final HandlerList handlerList = new HandlerList(); -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlerList; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlerList; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch b/Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch deleted file mode 100644 index ae3f76e08cfd..000000000000 --- a/Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:55:55 -0500 -Subject: [PATCH] Add String based Action Bar API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ddbe5734ac0f905b0c388e30f17a281530b82262..6bb0bb8052c12c5a215abf4bd9602fbefc769523 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3,6 +3,7 @@ package org.bukkit.entity; - import java.net.InetSocketAddress; - import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper -+import net.kyori.adventure.text.Component; - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -616,6 +617,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public void sendMap(@NotNull MapView map); - - // Paper start -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * Use Section symbols for legacy color codes to send formatting. -+ * -+ * @param message The message to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(@NotNull String message); -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * Use supplied alternative character to the section symbol to represent legacy color codes. -+ * -+ * @param alternateChar Alternate symbol such as '&' -+ * @param message The message to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(char alternateChar, @NotNull String message); -+ -+ /** -+ * Sends an Action Bar message to the client. -+ * -+ * @param message The components to send -+ * @deprecated use {@link #sendActionBar(Component)} -+ */ -+ @Deprecated -+ public void sendActionBar(@NotNull net.md_5.bungee.api.chat.BaseComponent... message); -+ - /** - * Sends the component to the player - * -@@ -643,9 +677,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends an array of components as a single message to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param components the components to send - */ -+ @Deprecated - public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { - spigot().sendMessage(position, components); - } -@@ -1728,6 +1764,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends the component to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param component the components to send - * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} -@@ -1740,6 +1777,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - /** - * Sends an array of components as a single message to the specified screen position of this player - * -+ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. - * @param position the screen position - * @param components the components to send - * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} diff --git a/Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 3f2a53935308..000000000000 --- a/Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index e94ec567fbda93f4f5783f84b4b5136b309d0eab..fddc063798edc8084ca695578a47485204a7f3cd 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity { - */ - ADDING; - } -+ // Paper start -+ /** -+ * Tests if this armor stand can move. -+ * -+ *

The default value is {@code true}.

-+ * -+ * @return {@code true} if this armour stand can move, {@code false} otherwise -+ */ -+ boolean canMove(); -+ -+ /** -+ * Sets if this armor stand can move. -+ * -+ * @param move {@code true} if this armour stand can move, {@code false} otherwise -+ */ -+ void setCanMove(boolean move); -+ // Paper end - } diff --git a/Spigot-API-Patches/0044-IllegalPacketEvent.patch b/Spigot-API-Patches/0044-IllegalPacketEvent.patch deleted file mode 100644 index 7eb8d61aaa15..000000000000 --- a/Spigot-API-Patches/0044-IllegalPacketEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 4 Dec 2016 01:19:14 -0500 -Subject: [PATCH] IllegalPacketEvent - -Fire an event when an illegal packet is received to let plugins handle it - -Lets plugins change the kick message and if it should kick or not. - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8d8e9b16f2a6707d2af7567c7682dfc5db51a737 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java -@@ -0,0 +1,74 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * @deprecated Not used -+ */ -+@Deprecated -+public class IllegalPacketEvent extends PlayerEvent { -+ @Nullable private final String type; -+ @Nullable private final String ex; -+ @Nullable private String kickMessage; -+ private boolean shouldKick = true; -+ -+ public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) { -+ super(player); -+ this.type = type; -+ this.kickMessage = kickMessage; -+ this.ex = e.getMessage(); -+ } -+ -+ public boolean isShouldKick() { -+ return shouldKick; -+ } -+ -+ public void setShouldKick(boolean shouldKick) { -+ this.shouldKick = shouldKick; -+ } -+ -+ @Nullable -+ public String getKickMessage() { -+ return kickMessage; -+ } -+ -+ public void setKickMessage(@Nullable String kickMessage) { -+ this.kickMessage = kickMessage; -+ } -+ -+ @Nullable -+ public String getType() { -+ return type; -+ } -+ -+ @Nullable -+ public String getExceptionMessage() { -+ return ex; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) { -+ IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception); -+ event.callEvent(); -+ if (event.shouldKick) { -+ player.kickPlayer(kickMessage); -+ } -+ Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage()); -+ } -+} diff --git a/Spigot-API-Patches/0045-Fireworks-API-s.patch b/Spigot-API-Patches/0045-Fireworks-API-s.patch deleted file mode 100644 index a0ed753ac6c4..000000000000 --- a/Spigot-API-Patches/0045-Fireworks-API-s.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 01:18:55 -0500 -Subject: [PATCH] Fireworks API's - -Get the Entity being boosted -Get the firework launcher - -diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java -index 05e86cb9d826cdf14490fa649348d46c51adbfdb..d616d5941b3c7b85e350e845901da798601b9a3c 100644 ---- a/src/main/java/org/bukkit/entity/Firework.java -+++ b/src/main/java/org/bukkit/entity/Firework.java -@@ -43,4 +43,15 @@ public interface Firework extends Projectile { - * @param shotAtAngle the new shotAtAngle - */ - void setShotAtAngle(boolean shotAtAngle); -+ -+ // Paper start -+ @org.jetbrains.annotations.Nullable -+ public java.util.UUID getSpawningEntity(); -+ /** -+ * If this firework is boosting an entity, return it -+ * @return The entity being boosted -+ */ -+ @org.jetbrains.annotations.Nullable -+ public LivingEntity getBoostedEntity(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch b/Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 664edd24cd69..000000000000 --- a/Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 20:29:33 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b64ab6eecd8bc4ca9c109b9d83c82861d6260793 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.block.EndGateway; -+import org.bukkit.entity.Player; -+import org.bukkit.event.player.PlayerTeleportEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a teleport is triggered for an End Gateway -+ */ -+public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent { -+ @NotNull private final EndGateway gateway; -+ -+ public PlayerTeleportEndGatewayEvent(@NotNull Player player, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { -+ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ this.gateway = gateway; -+ } -+ -+ /** -+ * The gateway triggering the teleport -+ * -+ * @return EndGateway used -+ */ -+ @NotNull -+ public EndGateway getGateway() { -+ return gateway; -+ } -+} diff --git a/Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index fc838a6f0232..000000000000 --- a/Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:23:03 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6b5dbe4ea711807a1944cfe2aae2ce415d4f2638..789e070f6aee83e4b6426def784e05df98e1bc65 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -40,6 +40,33 @@ import org.jetbrains.annotations.Nullable; - */ - public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper - -+ // Paper start -+ /** -+ * @return The amount of Entities in this world -+ */ -+ int getEntityCount(); -+ -+ /** -+ * @return The amount of Tile Entities in this world -+ */ -+ int getTileEntityCount(); -+ -+ /** -+ * @return The amount of Tickable Tile Entities in this world -+ */ -+ int getTickableTileEntityCount(); -+ -+ /** -+ * @return The amount of Chunks in this world -+ */ -+ int getChunkCount(); -+ -+ /** -+ * @return The amount of Players in this world -+ */ -+ int getPlayerCount(); -+ // Paper end -+ - /** - * Gets the {@link Block} at the given coordinates - * diff --git a/Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch b/Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch deleted file mode 100644 index f700226be303..000000000000 --- a/Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 21 Jan 2017 17:03:10 -0600 -Subject: [PATCH] Expose WorldBorder#isInBounds(Location) check - - -diff --git a/src/main/java/org/bukkit/WorldBorder.java b/src/main/java/org/bukkit/WorldBorder.java -index 7e8f5649ce0eb0090899514b1e228601eb644613..afb7b136b461202026290624836446cff9f9e45d 100644 ---- a/src/main/java/org/bukkit/WorldBorder.java -+++ b/src/main/java/org/bukkit/WorldBorder.java -@@ -117,4 +117,18 @@ public interface WorldBorder { - * @return if this location is inside the border or not - */ - public boolean isInside(@NotNull Location location); -+ -+ // Paper start -+ /** -+ * Checks if the location is within the boundaries of this border. -+ * -+ * @param location specific location to check -+ * @return true if the location is within the bounds of this border, false otherwise. -+ * @deprecated use {@link #isInside(Location)} for an upstream compatible replacement -+ */ -+ @Deprecated -+ public default boolean isInBounds(@NotNull Location location) { -+ return this.isInside(location); -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch b/Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 929cd006660a..000000000000 --- a/Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Fri, 9 Jun 2017 07:24:24 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 555ef4c187ce0c83cc29af145694ec9c448d452e..2527e896a4409326ea2612723b829696d44fc199 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1756,6 +1756,16 @@ public final class Bukkit { - public static boolean reloadCommandAliases() { - return server.reloadCommandAliases(); - } -+ -+ /** -+ * Checks if player names should be suggested when a command returns {@code null} as -+ * their tab completion result. -+ * -+ * @return true if player names should be suggested -+ */ -+ public static boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return server.suggestPlayerNamesWhenNullTabCompletions(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9d81f25e39d345b797f73855a802b186d77f6d12..7d94242b2f8ecb537b3140f9d6f706d3e266c456 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1542,4 +1542,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - void reloadPermissions(); // Paper - - boolean reloadCommandAliases(); // Paper -+ -+ // Paper start - allow preventing player name suggestions by default -+ /** -+ * Checks if player names should be suggested when a command returns {@code null} as -+ * their tab completion result. -+ * -+ * @return true if player names should be suggested -+ */ -+ boolean suggestPlayerNamesWhenNullTabCompletions(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 03bdc1622791e1206406c87065978688d602e39e..7c80dc54776d0d66f7816b77136f6dbd9b801704 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -99,7 +99,7 @@ public abstract class Command { - Validate.notNull(args, "Arguments cannot be null"); - Validate.notNull(alias, "Alias cannot be null"); - -- if (args.length == 0) { -+ if (args.length == 0 || !sender.getServer().suggestPlayerNamesWhenNullTabCompletions()) { // Paper - allow preventing player name suggestions by default) { - return ImmutableList.of(); - } - diff --git a/Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch b/Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch deleted file mode 100644 index 083596bdd24d..000000000000 --- a/Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 10 Jun 2017 16:59:40 -0500 -Subject: [PATCH] Fix upstream javadoc warnings and errors - -Upstream still refuses to use Java 8 with the API so they are likely unaware these are even issues. - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3f68baef538098d9ce66b91195b6fa17f26f0d78..e71b048e53ee2db4e768eea2ddf19b00a14d2484 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -634,7 +634,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * - * Use supplied alternative character to the section symbol to represent legacy color codes. - * -- * @param alternateChar Alternate symbol such as '&' -+ * @param alternateChar Alternate symbol such as '&' - * @param message The message to send - * @deprecated use {@link #sendActionBar(Component)} - */ -diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -index 1b2267f4e8ebded198773ec80e2bff2c861c7084..1a58734d919fae247eeb85dd785fd59990856505 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java -@@ -78,7 +78,7 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { - * - * @return Location the player moved to - */ -- @Nullable -+ @NotNull // Paper - public Location getTo() { - return to; - } -diff --git a/src/main/java/org/bukkit/inventory/PlayerInventory.java b/src/main/java/org/bukkit/inventory/PlayerInventory.java -index 91afd844dafec4ed9ab9e2e16b220ffbd35e7495..1e45c9078ffffe9d3c25538fdd433780ae751270 100644 ---- a/src/main/java/org/bukkit/inventory/PlayerInventory.java -+++ b/src/main/java/org/bukkit/inventory/PlayerInventory.java -@@ -106,7 +106,7 @@ public interface PlayerInventory extends Inventory { - * - * @return the ItemStack in the given slot - */ -- @NotNull -+ @Nullable - public ItemStack getItem(@NotNull EquipmentSlot slot); - - /** diff --git a/Spigot-API-Patches/0052-Item-canEntityPickup.patch b/Spigot-API-Patches/0052-Item-canEntityPickup.patch deleted file mode 100644 index 27894bda9322..000000000000 --- a/Spigot-API-Patches/0052-Item-canEntityPickup.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:08 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java -index 3f2736fbddd8661e764bc2f8d0499bd13ca91df5..c404a5b8efea7c780db5ddae19456753808abb3d 100644 ---- a/src/main/java/org/bukkit/entity/Item.java -+++ b/src/main/java/org/bukkit/entity/Item.java -@@ -75,4 +75,20 @@ public interface Item extends Entity { - */ - @Nullable - public UUID getThrower(); -+ -+ // Paper Start -+ /** -+ * Gets if non-player entities can pick this Item up -+ * -+ * @return True if non-player entities can pickup -+ */ -+ public boolean canMobPickup(); -+ -+ /** -+ * Sets if non-player entities can pick this Item up -+ * -+ * @param canMobPickup True to allow non-player entity pickup -+ */ -+ public void setCanMobPickup(boolean canMobPickup); -+ // Paper end - } diff --git a/Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index 353d39591191..000000000000 --- a/Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:01 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -index 951ea2cc763973655beedcba3c75332d3f297313..18d82c111f30e0279c10a174a51bac018185cd38 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerPickupItemEvent.java -@@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; - public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private final Item item; -+ private boolean flyAtPlayer = true; // Paper - private boolean cancel = false; - private final int remaining; - -@@ -45,6 +46,27 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - return remaining; - } - -+ // Paper Start -+ /** -+ * Set if the item will fly at the player -+ *

Cancelling the event will set this value to false.

-+ * -+ * @param flyAtPlayer True for item to fly at player -+ */ -+ public void setFlyAtPlayer(boolean flyAtPlayer) { -+ this.flyAtPlayer = flyAtPlayer; -+ } -+ -+ /** -+ * Gets if the item will fly at the player -+ * -+ * @return True if the item will fly at the player -+ */ -+ public boolean getFlyAtPlayer() { -+ return flyAtPlayer; -+ } -+ // Paper End -+ - @Override - public boolean isCancelled() { - return cancel; -@@ -53,6 +75,7 @@ public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable { - @Override - public void setCancelled(boolean cancel) { - this.cancel = cancel; -+ this.flyAtPlayer = !cancel; // Paper - } - - @NotNull diff --git a/Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch b/Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 6b504ae68865..000000000000 --- a/Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:37 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0788153a9641e75da565d2e6eee37eeee1cbc61e ---- /dev/null -+++ b/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java -@@ -0,0 +1,90 @@ -+package org.bukkit.event.player; -+ -+import org.bukkit.entity.Item; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Thrown when a player attempts to pick an item up from the ground -+ */ -+public class PlayerAttemptPickupItemEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Item item; -+ private final int remaining; -+ private boolean flyAtPlayer = true; -+ private boolean isCancelled = false; -+ -+ @Deprecated // Remove in 1.13 // Remove in 1.14? -+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item) { -+ this(player, item, 0); -+ } -+ -+ public PlayerAttemptPickupItemEvent(@NotNull final Player player, @NotNull final Item item, final int remaining) { -+ super(player); -+ this.item = item; -+ this.remaining = remaining; -+ } -+ -+ /** -+ * Gets the Item attempted by the player. -+ * -+ * @return Item -+ */ -+ @NotNull -+ public Item getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets the amount that will remain on the ground, if any -+ * -+ * @return amount that will remain on the ground -+ */ -+ public int getRemaining() { -+ return remaining; -+ } -+ -+ /** -+ * Set if the item will fly at the player -+ *

Cancelling the event will set this value to false.

-+ * -+ * @param flyAtPlayer True for item to fly at player -+ */ -+ public void setFlyAtPlayer(boolean flyAtPlayer) { -+ this.flyAtPlayer = flyAtPlayer; -+ } -+ -+ /** -+ * Gets if the item will fly at the player -+ * -+ * @return True if the item will fly at the player -+ */ -+ public boolean getFlyAtPlayer() { -+ return this.flyAtPlayer; -+ } -+ -+ -+ @Override -+ public boolean isCancelled() { -+ return this.isCancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.isCancelled = cancel; -+ this.flyAtPlayer = !cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch b/Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch deleted file mode 100644 index 9e3d997b0def..000000000000 --- a/Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:06 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d5632d352590dec6982a372b285a8d4a332fa589 ---- /dev/null -+++ b/src/main/java/org/bukkit/event/command/UnknownCommandEvent.java -@@ -0,0 +1,114 @@ -+package org.bukkit.event.command; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; -+import org.bukkit.command.CommandSender; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.Event; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Thrown when a player executes a command that is not defined -+ */ -+public class UnknownCommandEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private CommandSender sender; -+ @NotNull private String commandLine; -+ @Nullable private Component message; -+ -+ @Deprecated -+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final String message) { -+ this(sender, commandLine, message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); -+ } -+ -+ public UnknownCommandEvent(@NotNull final CommandSender sender, @NotNull final String commandLine, @Nullable final Component message) { -+ super(false); -+ this.sender = sender; -+ this.commandLine = commandLine; -+ this.message = message; -+ } -+ -+ /** -+ * Gets the CommandSender or ConsoleCommandSender -+ *

-+ * -+ * @return Sender of the command -+ */ -+ @NotNull -+ public CommandSender getSender() { -+ return sender; -+ } -+ -+ /** -+ * Gets the command that was send -+ *

-+ * -+ * @return Command sent -+ */ -+ @NotNull -+ public String getCommandLine() { -+ return commandLine; -+ } -+ -+ /** -+ * Gets message that will be returned -+ *

-+ * -+ * @return Unknown command message -+ * @deprecated use {@link #message()} -+ */ -+ @Nullable -+ @Deprecated -+ public String getMessage() { -+ return this.message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(this.message); -+ } -+ -+ /** -+ * Sets message that will be returned -+ *

-+ * Set to null to avoid any message being sent -+ * -+ * @param message the message to be returned, or null -+ * @deprecated use {@link #message(Component)} -+ */ -+ @Deprecated -+ public void setMessage(@Nullable String message) { -+ this.message(message == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(message)); -+ } -+ -+ /** -+ * Gets message that will be returned -+ *

-+ * -+ * @return Unknown command message -+ */ -+ @Nullable -+ public Component message() { -+ return this.message; -+ } -+ -+ /** -+ * Sets message that will be returned -+ *

-+ * Set to null to avoid any message being sent -+ * -+ * @param message the message to be returned, or null -+ */ -+ public void message(@Nullable Component message) { -+ this.message = message; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ diff --git a/Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch b/Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch deleted file mode 100644 index 96944d344908..000000000000 --- a/Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 21:46:46 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Provides basic elements of a PlayerProfile to be used by future API/events - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2ef9a7bd55e2c9cf8cb20d5f77282676ae11181f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java -@@ -0,0 +1,177 @@ -+package com.destroystokyo.paper.profile; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a players profile for the game, such as UUID, Name, and textures. -+ */ -+public interface PlayerProfile { -+ -+ /** -+ * @return The players name, if set -+ */ -+ @Nullable -+ String getName(); -+ -+ /** -+ * Sets this profiles Name -+ * -+ * @param name The new Name -+ * @return The previous Name -+ */ -+ @NotNull -+ String setName(@Nullable String name); -+ -+ /** -+ * @return The players unique identifier, if set -+ */ -+ @Nullable UUID getId(); -+ -+ /** -+ * Sets this profiles UUID -+ * -+ * @param uuid The new UUID -+ * @return The previous UUID -+ */ -+ @Nullable -+ UUID setId(@Nullable UUID uuid); -+ -+ /** -+ * @return A Mutable set of this players properties, such as textures. -+ * Values specified here are subject to implementation details. -+ */ -+ @NotNull Set getProperties(); -+ -+ /** -+ * Check if the Profile has the specified property -+ * @param property Property name to check -+ * @return If the property is set -+ */ -+ boolean hasProperty(@Nullable String property); -+ -+ /** -+ * Sets a property. If the property already exists, the previous one will be replaced -+ * @param property Property to set. -+ */ -+ void setProperty(@NotNull ProfileProperty property); -+ -+ /** -+ * Sets multiple properties. If any of the set properties already exist, it will be replaced -+ * @param properties The properties to set -+ */ -+ void setProperties(@NotNull Collection properties); -+ -+ /** -+ * Removes a specific property from this profile -+ * @param property The property to remove -+ * @return If a property was removed -+ */ -+ boolean removeProperty(@Nullable String property); -+ -+ /** -+ * Removes a specific property from this profile -+ * @param property The property to remove -+ * @return If a property was removed -+ */ -+ default boolean removeProperty(@NotNull ProfileProperty property) { -+ return removeProperty(property.getName()); -+ } -+ -+ /** -+ * Removes all properties in the collection -+ * @param properties The properties to remove -+ * @return If any property was removed -+ */ -+ default boolean removeProperties(@NotNull Collection properties) { -+ boolean removed = false; -+ for (ProfileProperty property : properties) { -+ if (removeProperty(property)) { -+ removed = true; -+ } -+ } -+ return removed; -+ } -+ -+ /** -+ * Clears all properties on this profile -+ */ -+ void clearProperties(); -+ -+ /** -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean isComplete(); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @param onlineMode Treat this as online mode or not -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(boolean onlineMode); -+ -+ /** -+ * Like {@link #complete(boolean)} but will try only from cache, and not make network calls -+ * Does not account for textures. -+ * -+ * @param lookupUUID If only name is supplied, should we do a UUID lookup -+ * @param onlineMode Treat this as online mode or not -+ * @return If the profile is now complete (has UUID and Name) -+ */ -+ boolean completeFromCache(boolean lookupUUID, boolean onlineMode); -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}} -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ default boolean complete() { -+ return complete(true); -+ } -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * Optionally will also fill textures. -+ * -+ * Online mode will be automatically determined -+ * @param textures controls if we should fill the profile with texture properties -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ boolean complete(boolean textures); -+ -+ /** -+ * If this profile is not complete, then make the API call to complete it. -+ * This is a blocking operation and should be done asynchronously. -+ * -+ * Optionally will also fill textures. -+ * @param textures controls if we should fill the profile with texture properties -+ * @param onlineMode Treat this server as online mode or not -+ * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) -+ */ -+ boolean complete(boolean textures, boolean onlineMode); -+ -+ /** -+ * Whether or not this Profile has textures associated to it -+ * @return If has a textures property -+ */ -+ default boolean hasTextures() { -+ return hasProperty("textures"); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b3b6ef533d32169fbeca389bd61cfc6b0e0faee ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java -@@ -0,0 +1,72 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.google.common.base.Preconditions; -+ -+import java.util.Objects; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a property on a {@link PlayerProfile} -+ */ -+public class ProfileProperty { -+ private final String name; -+ private final String value; -+ private final String signature; -+ -+ public ProfileProperty(@NotNull String name, @NotNull String value) { -+ this(name, value, null); -+ } -+ -+ public ProfileProperty(@NotNull String name, @NotNull String value, @Nullable String signature) { -+ this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null"); -+ this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null"); -+ this.signature = signature; -+ } -+ -+ /** -+ * @return The property name, ie "textures" -+ */ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ /** -+ * @return The property value, likely to be base64 encoded -+ */ -+ @NotNull -+ public String getValue() { -+ return value; -+ } -+ -+ /** -+ * @return A signature from Mojang for signed properties -+ */ -+ @Nullable -+ public String getSignature() { -+ return signature; -+ } -+ -+ /** -+ * @return If this property has a signature or not -+ */ -+ public boolean isSigned() { -+ return this.signature != null; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ ProfileProperty that = (ProfileProperty) o; -+ return Objects.equals(name, that.name) && -+ Objects.equals(value, that.value) && -+ Objects.equals(signature, that.signature); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(name); -+ } -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 2527e896a4409326ea2612723b829696d44fc199..f5d3a7370390871d1b6075f32846d1a942b05b7f 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1766,6 +1766,40 @@ public final class Bukkit { - public static boolean suggestPlayerNamesWhenNullTabCompletions() { - return server.suggestPlayerNamesWhenNullTabCompletions(); - } -+ -+ /** -+ * Creates a PlayerProfile for the specified uuid, with name as null -+ * @param uuid UUID to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid) { -+ return server.createProfile(uuid); -+ } -+ -+ /** -+ * Creates a PlayerProfile for the specified name, with UUID as null -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name) { -+ return server.createProfile(name); -+ } -+ -+ /** -+ * Creates a PlayerProfile for the specified name/uuid -+ * -+ * Both UUID and Name can not be null at same time. One must be supplied. -+ * -+ * @param uuid UUID to create profile for -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ return server.createProfile(uuid, name); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7d94242b2f8ecb537b3140f9d6f706d3e266c456..38d138b217734e598581ed14065ff2015135ee9a 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1551,5 +1551,33 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return true if player names should be suggested - */ - boolean suggestPlayerNamesWhenNullTabCompletions(); -+ -+ /** -+ * Creates a PlayerProfile for the specified uuid, with name as null -+ * @param uuid UUID to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid); -+ -+ /** -+ * Creates a PlayerProfile for the specified name, with UUID as null -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull String name); -+ -+ /** -+ * Creates a PlayerProfile for the specified name/uuid -+ * -+ * Both UUID and Name can not be null at same time. One must be supplied. -+ * -+ * @param uuid UUID to create profile for -+ * @param name Name to create profile for -+ * @return A PlayerProfile object -+ */ -+ @NotNull -+ com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); - // Paper end - } diff --git a/Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch b/Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch deleted file mode 100644 index 249e81f7ad9d..000000000000 --- a/Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:04:51 -0400 -Subject: [PATCH] Shoulder Entities Release API - - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 72178c3036f567ceaf15016978a9737eb9c4afc4..d212d5123b6294f7873d72f125505a006c290b05 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -300,6 +300,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public int getExpToLevel(); - -+ // Paper start -+ /** -+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. -+ * If no Entity is released, null will be returned. -+ * -+ * @return The released entity, or null -+ */ -+ @Nullable -+ public Entity releaseLeftShoulderEntity(); -+ -+ /** -+ * If there is an Entity on this entities left shoulder, it will be released to the world and returned. -+ * If no Entity is released, null will be returned. -+ * -+ * @return The released entity, or null -+ */ -+ @Nullable -+ public Entity releaseRightShoulderEntity(); -+ // Paper end -+ - /** - * Gets the current cooldown for a player's attack. - * diff --git a/Spigot-API-Patches/0058-Profile-Lookup-Events.patch b/Spigot-API-Patches/0058-Profile-Lookup-Events.patch deleted file mode 100644 index 1cdb35476d74..000000000000 --- a/Spigot-API-Patches/0058-Profile-Lookup-Events.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 16:30:44 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8df37c07cd55ddf110d1dd68183d7b697f7a6756 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/LookupProfileEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Allows a plugin to be notified anytime AFTER a Profile has been looked up from the Mojang API -+ * This is an opportunity to view the response and potentially cache things. -+ * -+ * No guarantees are made about thread execution context for this event. If you need to know, check -+ * event.isAsync() -+ */ -+public class LookupProfileEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final PlayerProfile profile; -+ -+ public LookupProfileEvent(@NotNull PlayerProfile profile) { -+ super(!Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The profile that was recently looked up. This profile can be mutated -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4dcf6242c9acc62d030a94f67b78729ed29f8c85 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreLookupProfileEvent.java -@@ -0,0 +1,108 @@ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import com.google.common.collect.ArrayListMultimap; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.HashSet; -+import java.util.Set; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows a plugin to intercept a Profile Lookup for a Profile by name -+ * -+ * At the point of event fire, the UUID and properties are unset. -+ * -+ * If a plugin sets the UUID, and optionally the properties, the API call to look up the profile may be skipped. -+ * -+ * No guarantees are made about thread execution context for this event. If you need to know, check -+ * event.isAsync() -+ */ -+public class PreLookupProfileEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final String name; -+ private UUID uuid; -+ @NotNull private Set properties = new HashSet<>(); -+ -+ public PreLookupProfileEvent(@NotNull String name) { -+ super(!Bukkit.isPrimaryThread()); -+ this.name = name; -+ } -+ -+ /** -+ * @return Name of the profile -+ */ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ /** -+ * If this value is left null by the completion of the event call, then the server will -+ * trigger a call to the Mojang API to look up the UUID (Network Request), and subsequently, fire a -+ * {@link LookupProfileEvent} -+ * -+ * @return The UUID of the profile if it has already been provided by a plugin -+ */ -+ @Nullable -+ public UUID getUUID() { -+ return uuid; -+ } -+ -+ /** -+ * Sets the UUID for this player name. This will skip the initial API call to find the players UUID. -+ * -+ * However, if Profile Properties are needed by the server, you must also set them or else an API call might still be made. -+ * -+ * @param uuid the UUID to set for the profile or null to reset -+ */ -+ public void setUUID(@Nullable UUID uuid) { -+ this.uuid = uuid; -+ } -+ -+ /** -+ * @return The currently pending prepopulated properties. -+ * Any property in this Set will be automatically prefilled on this Profile -+ */ -+ @NotNull -+ public Set getProfileProperties() { -+ return this.properties; -+ } -+ -+ /** -+ * Clears any existing prepopulated properties and uses the supplied properties -+ * Any property in this Set will be automatically prefilled on this Profile -+ * @param properties The properties to add -+ */ -+ public void setProfileProperties(@NotNull Set properties) { -+ this.properties = new HashSet<>(); -+ this.properties.addAll(properties); -+ } -+ -+ /** -+ * Adds any properties currently missing to the prepopulated properties set, replacing any that already were set. -+ * Any property in this Set will be automatically prefilled on this Profile -+ * @param properties The properties to add -+ */ -+ public void addProfileProperties(@NotNull Set properties) { -+ this.properties.addAll(properties); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+} diff --git a/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch b/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch deleted file mode 100644 index 6912236f76ab..000000000000 --- a/Spigot-API-Patches/0059-Entity-fromMobSpawner.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index e9d0d507b47b0347b975b1a83f5ae70dca5587b8..feb9507a972bf797144a01adeeaac83ec2bd165a 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -619,5 +619,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @Nullable - Location getOrigin(); -+ -+ /** -+ * Returns whether this entity was spawned from a mob spawner. -+ * -+ * @return True if entity spawned from a mob spawner -+ */ -+ boolean fromMobSpawner(); - // Paper end - } diff --git a/Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch b/Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 85814456bf48..000000000000 --- a/Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:12:48 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..163ffe8ff76ded6265d865901d5110fb6a56950d ---- /dev/null -+++ b/src/main/java/org/bukkit/inventory/ArmoredHorseInventory.java -@@ -0,0 +1,21 @@ -+package org.bukkit.inventory; -+ -+import org.jetbrains.annotations.Nullable; -+ -+public interface ArmoredHorseInventory extends AbstractHorseInventory { -+ -+ /** -+ * Gets the item in the horse's armor slot. -+ * -+ * @return the armor item -+ */ -+ @Nullable -+ ItemStack getArmor(); -+ -+ /** -+ * Sets the item in the horse's armor slot. -+ * -+ * @param stack the new item -+ */ -+ void setArmor(@Nullable ItemStack stack); -+} -diff --git a/src/main/java/org/bukkit/inventory/HorseInventory.java b/src/main/java/org/bukkit/inventory/HorseInventory.java -index 608e99c4207405bf9dd88d44ad8e82eefa19e45c..53498debe4cfb80592ef3025270bc8e5df4a5fec 100644 ---- a/src/main/java/org/bukkit/inventory/HorseInventory.java -+++ b/src/main/java/org/bukkit/inventory/HorseInventory.java -@@ -5,20 +5,4 @@ import org.jetbrains.annotations.Nullable; - /** - * An interface to the inventory of a Horse. - */ --public interface HorseInventory extends AbstractHorseInventory { -- -- /** -- * Gets the item in the horse's armor slot. -- * -- * @return the armor item -- */ -- @Nullable -- ItemStack getArmor(); -- -- /** -- * Sets the item in the horse's armor slot. -- * -- * @param stack the new item -- */ -- void setArmor(@Nullable ItemStack stack); --} -+public interface HorseInventory extends AbstractHorseInventory, ArmoredHorseInventory {} -diff --git a/src/main/java/org/bukkit/inventory/LlamaInventory.java b/src/main/java/org/bukkit/inventory/LlamaInventory.java -index 2fa2c9d07ecbafaf2396d913af90f1f4d432b238..5ac1afb8a213fa0fe344db4730ecbc5de6eed445 100644 ---- a/src/main/java/org/bukkit/inventory/LlamaInventory.java -+++ b/src/main/java/org/bukkit/inventory/LlamaInventory.java -@@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable; - /** - * An interface to the inventory of a {@link Llama}. - */ --public interface LlamaInventory extends AbstractHorseInventory { -+public interface LlamaInventory extends SaddledHorseInventory { - - /** - * Gets the item in the llama's decor slot. -diff --git a/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7944f26a3e2a92601c3be0e55c00c39cc16cf177 ---- /dev/null -+++ b/src/main/java/org/bukkit/inventory/SaddledHorseInventory.java -@@ -0,0 +1,3 @@ -+package org.bukkit.inventory; -+ -+public interface SaddledHorseInventory extends AbstractHorseInventory {} diff --git a/Spigot-API-Patches/0061-ensureServerConversions-API.patch b/Spigot-API-Patches/0061-ensureServerConversions-API.patch deleted file mode 100644 index ecb2199d5454..000000000000 --- a/Spigot-API-Patches/0061-ensureServerConversions-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:55:48 -0400 -Subject: [PATCH] ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 6cc4bad2ecd19f44a680ff03cbfb99d48ea5c337..845119c9ba9dc2719dc67b0edb0ff2ad58656bde 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -160,5 +160,17 @@ public interface ItemFactory { - */ - @NotNull - net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); -+ -+ /** -+ * Minecart updates are converting simple item stacks into more complex NBT oriented Item Stacks. -+ * -+ * Use this method to to ensure any desired data conversions are processed. -+ * The input itemstack will not be the same as the returned itemstack. -+ * -+ * @param item The item to process conversions on -+ * @return A potentially Data Converted ItemStack -+ */ -+ @NotNull -+ ItemStack ensureServerConversions(@NotNull ItemStack item); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index a15abec467bac70116a6fc21a300d4930b909f15..1c69ca6a6d0e956d796827159236ee3466813d0e 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -536,7 +536,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - } - } - -- return result; -+ return result.ensureServerConversions(); // Paper - } - - /** -@@ -611,5 +611,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public @NotNull net.kyori.adventure.text.Component displayName() { - return Bukkit.getServer().getItemFactory().displayName(this); - } -+ -+ /** -+ * Minecart updates are converting simple item stacks into more complex NBT oriented Item Stacks. -+ * -+ * Use this method to to ensure any desired data conversions are processed. -+ * The input itemstack will not be the same as the returned itemstack. -+ * -+ * @return A potentially Data Converted ItemStack -+ */ -+ @NotNull -+ public ItemStack ensureServerConversions() { -+ return Bukkit.getServer().getItemFactory().ensureServerConversions(this); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch b/Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch deleted file mode 100644 index e4dde4f260c0..000000000000 --- a/Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:55:48 -0400 -Subject: [PATCH] Add getI18NDisplayName API - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 44a858490f4db37f979fd487ed7a5b2b8b7f1a3f..3fd56a95de7d4cbeaf5d8554fbc7127a627cb977 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -172,5 +172,16 @@ public interface ItemFactory { - */ - @NotNull - ItemStack ensureServerConversions(@NotNull ItemStack item); -+ -+ /** -+ * Gets the Display name as seen in the Client. -+ * Currently the server only supports the English language. To override this, -+ * You must replace the language file embedded in the server jar. -+ * -+ * @param item Item to return Display name of -+ * @return Display name of Item -+ */ -+ @Nullable -+ String getI18NDisplayName(@Nullable ItemStack item); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 47d8611221967d32b654ddac0fbf0e405ef62352..82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -624,5 +624,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public ItemStack ensureServerConversions() { - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); - } -+ -+ /** -+ * Gets the Display name as seen in the Client. -+ * Currently the server only supports the English language. To override this, -+ * You must replace the language file embedded in the server jar. -+ * -+ * @return Display name of Item -+ */ -+ @Nullable -+ public String getI18NDisplayName() { -+ return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch b/Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index ff996377f417..000000000000 --- a/Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:34 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - -Fires when the server is validating if a player is whitelisted. - -Allows you to do dynamic whitelisting and change of kick message - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8a259ab49ea79673b6da9e4e2aaecec67469994e ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/ProfileWhitelistVerifyEvent.java -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (c) 2017 - Daniel Ennis (Aikar) - MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fires when the server needs to verify if a player is whitelisted. -+ * -+ * Plugins may override/control the servers whitelist with this event, -+ * and dynamically change the kick message. -+ */ -+public class ProfileWhitelistVerifyEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final PlayerProfile profile; -+ private final boolean whitelistEnabled; -+ private boolean whitelisted; -+ private final boolean isOp; -+ @Nullable private Component kickMessage; -+ -+ @Deprecated -+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable String kickMessage) { -+ this(profile, whitelistEnabled, whitelisted, isOp, kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); -+ } -+ -+ public ProfileWhitelistVerifyEvent(@NotNull final PlayerProfile profile, boolean whitelistEnabled, boolean whitelisted, boolean isOp, @Nullable Component kickMessage) { -+ this.profile = profile; -+ this.whitelistEnabled = whitelistEnabled; -+ this.whitelisted = whitelisted; -+ this.isOp = isOp; -+ this.kickMessage = kickMessage; -+ } -+ -+ /** -+ * @return the currently planned message to send to the user if they are not whitelisted -+ * @deprecated use {@link #kickMessage()} -+ */ -+ @Deprecated -+ @Nullable -+ public String getKickMessage() { -+ return this.kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().serialize(kickMessage); -+ } -+ -+ /** -+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default -+ * @deprecated Use {@link #kickMessage(Component)} -+ */ -+ @Deprecated -+ public void setKickMessage(@Nullable String kickMessage) { -+ this.kickMessage(kickMessage == null ? null : Bukkit.getUnsafe().legacyComponentSerializer().deserialize(kickMessage)); -+ } -+ -+ /** -+ * @return the currently planned message to send to the user if they are not whitelisted -+ */ -+ @Nullable -+ public Component kickMessage() { -+ return this.kickMessage; -+ } -+ -+ /** -+ * @param kickMessage The message to send to the player on kick if not whitelisted. May set to null to use the server configured default -+ */ -+ public void kickMessage(@Nullable Component kickMessage) { -+ this.kickMessage = kickMessage; -+ } -+ -+ /** -+ * @return The profile of the player trying to connect -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * @return Whether the player is whitelisted to play on this server (whitelist may be off is why its true) -+ */ -+ public boolean isWhitelisted() { -+ return whitelisted; -+ } -+ -+ /** -+ * Changes the players whitelisted state. false will deny the login -+ * @param whitelisted The new whitelisted state -+ */ -+ public void setWhitelisted(boolean whitelisted) { -+ this.whitelisted = whitelisted; -+ } -+ -+ /** -+ * @return if the player obtained whitelist status by having op -+ */ -+ public boolean isOp() { -+ return isOp; -+ } -+ -+ /** -+ * @return if the server even has whitelist on -+ */ -+ public boolean isWhitelistEnabled() { -+ return whitelistEnabled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch b/Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch deleted file mode 100644 index ec1fc9814a94..000000000000 --- a/Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 02:08:55 -0500 -Subject: [PATCH] Make /plugins list alphabetical - - -diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -index bcb576a4271b1ec7b1cfe6f83cf161b7d89ed2e5..4de959bbd1270d7d6ea8e5e69521bcca6abe2138 100644 ---- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -@@ -3,6 +3,9 @@ package org.bukkit.command.defaults; - import java.util.Arrays; - import java.util.Collections; - import java.util.List; -+import java.util.Map; -+import java.util.TreeMap; -+ - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; - import org.bukkit.command.CommandSender; -@@ -34,15 +37,22 @@ public class PluginsCommand extends BukkitCommand { - - @NotNull - private String getPluginList() { -- StringBuilder pluginList = new StringBuilder(); -- Plugin[] plugins = Bukkit.getPluginManager().getPlugins(); -+ // Paper start -+ TreeMap plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); -+ -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ plugins.put(plugin.getDescription().getName(), plugin); -+ } - -- for (Plugin plugin : plugins) { -+ StringBuilder pluginList = new StringBuilder(); -+ for (Map.Entry entry : plugins.entrySet()) { - if (pluginList.length() > 0) { - pluginList.append(ChatColor.WHITE); - pluginList.append(", "); - } - -+ Plugin plugin = entry.getValue(); -+ - pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); - pluginList.append(plugin.getDescription().getName()); - -@@ -51,6 +61,8 @@ public class PluginsCommand extends BukkitCommand { - } - } - -- return "(" + plugins.length + "): " + pluginList.toString(); -+ return "(" + plugins.size() + "): " + pluginList.toString(); -+ // Paper end - } -+ - } diff --git a/Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch b/Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch deleted file mode 100644 index a1273c87c675..000000000000 --- a/Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:13 +0200 -Subject: [PATCH] Handle plugin prefixes in implementation logging - configuration - -Currently, plugin prefixes are prepended to the log message in -the PluginLogger before passing the message to the underlying -logging framework. This is bad design because they need to be -stripped manually when using custom appenders to log messages -in a different format. - -Additionally, it makes integration of alternative logging APIs hard -because all logging must go through the PluginLogger. Avoid using -PluginLogger and create a regular logger using the plugin name. -The implementation should handle plugin prefixes by displaying -logger names when appropriate. - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index 2231900549607a0917dd04e8b433c027b846cef9..bb2e55e97bf887a28cac7d4f9a0a23960d22cf56 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private PluginLogger logger = null; -+ private Logger logger = null; // Paper - PluginLogger -> Logger - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,7 +276,8 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- this.logger = new PluginLogger(this); -+ // Paper - Handle plugin prefix in implementation -+ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); - } - - /** diff --git a/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch b/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch deleted file mode 100644 index 1f987148b32d..000000000000 --- a/Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:33:12 +0200 -Subject: [PATCH] Allow plugins to use SLF4J for logging - -SLF4J is a commonly used abstraction for various logging frameworks -such as java.util.logging (JUL) or Log4j. Currently, plugins are -required to do all their logging using the provided JUL logger. -This is annoying for plugins that target multiple platforms or when -using libraries that log messages using SLF4J. - -Expose SLF4J as optional logging API for plugins, so they can use -it without having to shade it in the plugin and going through -several layers of logging abstraction. - -diff --git a/pom.xml b/pom.xml -index 7ec7e6047193a6b390d24f6d2722e35d1d36830d..6b71d9a397dd5b72320402a47b8e7197d24e061c 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -144,6 +144,13 @@ - 20.1.0 - provided - -+ -+ -+ org.slf4j -+ slf4j-api -+ 1.7.25 -+ compile -+ - - - junit -diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java -index febfec6efafd76bb59b4b43aa223af16f73339b4..79890c68f1ad31f951dfdbd9a16dac500ec58c40 100644 ---- a/src/main/java/org/bukkit/plugin/Plugin.java -+++ b/src/main/java/org/bukkit/plugin/Plugin.java -@@ -166,6 +166,13 @@ public interface Plugin extends TabExecutor { - @NotNull - public Logger getLogger(); - -+ // Paper start - Add SLF4J logger -+ @NotNull -+ default org.slf4j.Logger getSLF4JLogger() { -+ return org.slf4j.LoggerFactory.getLogger(getLogger().getName()); -+ } -+ // Paper end -+ - /** - * Returns the name of the plugin. - *

diff --git a/Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch deleted file mode 100644 index af5715219761..000000000000 --- a/Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 19:41:20 +0200 -Subject: [PATCH] Add workaround for plugins modifying the parent of the plugin - logger - -Essentials uses a custom logger name ("Essentials") instead of the -plugin logger. Log messages are redirected to the plugin logger by -setting the parent of the "Essentials" logger to the plugin logger. - -With our changes, the plugin logger is now also called "Essentials", -resulting in an infinite loop. Make sure plugins can't change the -parent of the plugin logger to avoid this. - -diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -new file mode 100644 -index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.utils; -+ -+import org.bukkit.plugin.PluginDescriptionFile; -+ -+import java.util.logging.Level; -+import java.util.logging.LogManager; -+import java.util.logging.Logger; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Prevents plugins (e.g. Essentials) from changing the parent of the plugin logger. -+ */ -+public class PaperPluginLogger extends Logger { -+ -+ @NotNull -+ public static Logger getLogger(@NotNull PluginDescriptionFile description) { -+ Logger logger = new PaperPluginLogger(description); -+ if (!LogManager.getLogManager().addLogger(logger)) { -+ // Disable this if it's going to happen across reloads anyways... -+ //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); -+ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ } -+ -+ return logger; -+ } -+ -+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { -+ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); -+ } -+ -+ @Override -+ public void setParent(@NotNull Logger parent) { -+ if (getParent() != null) { -+ warning("Ignoring attempt to change parent of plugin logger"); -+ } else { -+ this.log(Level.FINE, "Setting plugin logger parent to {0}", parent); -+ super.setParent(parent); -+ } -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index bb2e55e97bf887a28cac7d4f9a0a23960d22cf56..04fa3991f6ce4e9dad804f28fc6c947695857089 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -42,7 +42,7 @@ public abstract class JavaPlugin extends PluginBase { - private boolean naggable = true; - private FileConfiguration newConfig = null; - private File configFile = null; -- private Logger logger = null; // Paper - PluginLogger -> Logger -+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private - - public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -276,8 +276,11 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); -- // Paper - Handle plugin prefix in implementation -- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); -+ // Paper start -+ if (this.logger == null) { -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); -+ } -+ // Paper end - } - - /** -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 5ffa98bb9c76d802a9d0ea6c572a704a2732c67c..22abd85da592c79e312928de596e5d552a45ef12 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - private JavaPlugin pluginInit; - private IllegalStateException pluginState; - private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); -+ private java.util.logging.Logger logger; // Paper - add field - - static { - ClassLoader.registerAsParallelCapable(); -@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; - -+ this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early -+ - try { - Class jarClass; - try { -@@ -220,6 +223,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - pluginState = new IllegalStateException("Initial initialization"); - this.pluginInit = javaPlugin; - -+ javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } - } diff --git a/Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch b/Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch deleted file mode 100644 index 18f2c35b4dd5..000000000000 --- a/Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Sep 2017 17:21:32 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..289a0d784a3c74caf8a7231b4dd166096b1849a1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerJumpEvent.java -@@ -0,0 +1,106 @@ -+package com.destroystokyo.paper.event.player; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the server detects the player is jumping. -+ *

-+ * Added to avoid the overhead and special case logic that many plugins use -+ * when checking for jumps via PlayerMoveEvent, this event is fired whenever -+ * the server detects that the player is jumping. -+ */ -+public class PlayerJumpEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel = false; -+ @NotNull private Location from; -+ @NotNull private Location to; -+ -+ public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) { -+ super(player); -+ this.from = from; -+ this.to = to; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

-+ * If a jump event is cancelled, the player will be moved or -+ * teleported back to the Location as defined by getFrom(). This will not -+ * fire an event -+ * -+ * @return true if this event is cancelled -+ */ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

-+ * If a jump event is cancelled, the player will be moved or -+ * teleported back to the Location as defined by getFrom(). This will not -+ * fire an event -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Gets the location this player jumped from -+ * -+ * @return Location the player jumped from -+ */ -+ @NotNull -+ public Location getFrom() { -+ return from; -+ } -+ -+ /** -+ * Sets the location to mark as where the player jumped from -+ * -+ * @param from New location to mark as the players previous location -+ */ -+ public void setFrom(@NotNull Location from) { -+ validateLocation(from); -+ this.from = from; -+ } -+ -+ /** -+ * Gets the location this player jumped to -+ * -+ * This information is based on what the client sends, it typically -+ * has little relation to the arc of the jump at any given point. -+ * -+ * @return Location the player jumped to -+ */ -+ @NotNull -+ public Location getTo() { -+ return to; -+ } -+ -+ private void validateLocation(Location loc) { -+ Preconditions.checkArgument(loc != null, "Cannot use null location!"); -+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!"); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch b/Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index ff8f83ac14b2..000000000000 --- a/Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:44:42 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - -Add a NetworkClient interface that provides access to: - - The socket address - - The protocol version - - The virtual host (the hostname/port the client used to connect - to the server) - -diff --git a/src/main/java/com/destroystokyo/paper/network/NetworkClient.java b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b851aa04f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/NetworkClient.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.network; -+ -+import java.net.InetSocketAddress; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a client connected to the server. -+ */ -+public interface NetworkClient { -+ -+ /** -+ * Returns the socket address of the client. -+ * -+ * @return The client's socket address -+ */ -+ @NotNull -+ InetSocketAddress getAddress(); -+ -+ /** -+ * Returns the protocol version of the client. -+ * -+ * @return The client's protocol version, or {@code -1} if unknown -+ * @see List of protocol -+ * version numbers -+ */ -+ int getProtocolVersion(); -+ -+ /** -+ * Returns the virtual host the client is connected to. -+ * -+ *

The virtual host refers to the hostname/port the client used to -+ * connect to the server.

-+ * -+ * @return The client's virtual host, or {@code null} if unknown -+ */ -+ @Nullable -+ InetSocketAddress getVirtualHost(); -+ -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9cf7adf244335ac7dccbdf11f605a8c6910f7414..04f1a6513711dde8576c9b5c2b04619c56b48d8a 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a player, connected or not - */ --public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified { // Paper -+public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, com.destroystokyo.paper.network.NetworkClient { // Paper - - // Paper start - @Override diff --git a/Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch b/Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index 4e9d795db36e..000000000000 --- a/Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:45:59 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e406ce639a2e88b78f82f25e71678a669d0a958b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerArmorChangeEvent.java -@@ -0,0 +1,137 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Material; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+ -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.HashSet; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import static org.bukkit.Material.*; -+ -+/** -+ * Called when the player themselves change their armor items -+ *

-+ * Not currently called for environmental factors though it MAY BE IN THE FUTURE -+ */ -+public class PlayerArmorChangeEvent extends PlayerEvent { -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ @NotNull private final SlotType slotType; -+ @Nullable private final ItemStack oldItem; -+ @Nullable private final ItemStack newItem; -+ -+ public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable ItemStack newItem) { -+ super(player); -+ this.slotType = slotType; -+ this.oldItem = oldItem; -+ this.newItem = newItem; -+ } -+ -+ /** -+ * Gets the type of slot being altered. -+ * -+ * @return type of slot being altered -+ */ -+ @NotNull -+ public SlotType getSlotType() { -+ return this.slotType; -+ } -+ -+ /** -+ * Gets the existing item that's being replaced -+ * -+ * @return old item -+ */ -+ @Nullable -+ public ItemStack getOldItem() { -+ return this.oldItem; -+ } -+ -+ /** -+ * Gets the new item that's replacing the old -+ * -+ * @return new item -+ */ -+ @Nullable -+ public ItemStack getNewItem() { -+ return this.newItem; -+ } -+ -+ @Override -+ public String toString() { -+ return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}'; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+ -+ public enum SlotType { -+ HEAD(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, CARVED_PUMPKIN, PLAYER_HEAD, SKELETON_SKULL, ZOMBIE_HEAD, CREEPER_HEAD, WITHER_SKELETON_SKULL, TURTLE_HELMET), -+ CHEST(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA), -+ LEGS(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS), -+ FEET(NETHERITE_BOOTS, DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS); -+ -+ private final Set mutableTypes = new HashSet<>(); -+ private Set immutableTypes; -+ -+ SlotType(Material... types) { -+ this.mutableTypes.addAll(Arrays.asList(types)); -+ } -+ -+ /** -+ * Gets an immutable set of all allowed material types that can be placed in an -+ * armor slot. -+ * -+ * @return immutable set of material types -+ */ -+ @NotNull -+ public Set getTypes() { -+ if (immutableTypes == null) { -+ immutableTypes = Collections.unmodifiableSet(mutableTypes); -+ } -+ -+ return immutableTypes; -+ } -+ -+ /** -+ * Gets the type of slot via the specified material -+ * -+ * @param material material to get slot by -+ * @return slot type the material will go in, or null if it won't -+ */ -+ @Nullable -+ public static SlotType getByMaterial(@NotNull Material material) { -+ for (SlotType slotType : values()) { -+ if (slotType.getTypes().contains(material)) { -+ return slotType; -+ } -+ } -+ return null; -+ } -+ -+ /** -+ * Gets whether or not this material can be equipped to a slot -+ * -+ * @param material material to check -+ * @return whether or not this material can be equipped -+ */ -+ public static boolean isEquipable(@NotNull Material material) { -+ return getByMaterial(material) != null; -+ } -+ } -+} diff --git a/Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch b/Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index 9d4f264793d0..000000000000 --- a/Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:10:01 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 0cfad6f84eda6f7bfa1fae041341ccb1021b157d..e89c8079625525667f496c06207da655fe43d749 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -269,6 +269,16 @@ public interface Block extends Metadatable { - @NotNull - BlockState getState(); - -+ // Paper start -+ /** -+ * @see #getState() optionally disables use of snapshot, to operate on real block data -+ * @param useSnapshot if this block is a TE, should we create a fully copy of the TileEntity -+ * @return BlockState with the current state of this block -+ */ -+ @NotNull -+ BlockState getState(boolean useSnapshot); -+ // Paper end -+ - /** - * Returns the biome that this block resides in - * diff --git a/Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch b/Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch deleted file mode 100644 index e86dd9b401b2..000000000000 --- a/Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,266 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:17:09 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..619ed37169c126a8c75d02699a04728bac49d10d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -@@ -0,0 +1,177 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.collect.ImmutableList; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.ArrayList; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Allows plugins to compute tab completion results asynchronously. If this event provides completions, then the standard synchronous process will not be fired to populate the results. However, the synchronous TabCompleteEvent will fire with the Async results. -+ * -+ * Only 1 process will be allowed to provide completions, the Async Event, or the standard process. -+ */ -+public class AsyncTabCompleteEvent extends Event implements Cancellable { -+ @NotNull private final CommandSender sender; -+ @NotNull private final String buffer; -+ private final boolean isCommand; -+ @Nullable -+ private final Location loc; -+ @NotNull private List completions; -+ private boolean cancelled; -+ private boolean handled = false; -+ private boolean fireSyncHandler = true; -+ -+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { -+ super(true); -+ this.sender = sender; -+ this.completions = completions; -+ this.buffer = buffer; -+ this.isCommand = isCommand; -+ this.loc = loc; -+ } -+ -+ /** -+ * Get the sender completing this command. -+ * -+ * @return the {@link CommandSender} instance -+ */ -+ @NotNull -+ public CommandSender getSender() { -+ return sender; -+ } -+ -+ /** -+ * The list of completions which will be offered to the sender, in order. -+ * This list is mutable and reflects what will be offered. -+ * -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return a list of offered completions -+ */ -+ @NotNull -+ public List getCompletions() { -+ return completions; -+ } -+ -+ /** -+ * Set the completions offered, overriding any already set. -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here -+ * -+ * @param completions the new completions -+ */ -+ public void setCompletions(@NotNull List completions) { -+ Validate.notNull(completions); -+ this.completions = new ArrayList<>(completions); -+ } -+ -+ /** -+ * Return the entire buffer which formed the basis of this completion. -+ * -+ * @return command buffer, as entered -+ */ -+ @NotNull -+ public String getBuffer() { -+ return buffer; -+ } -+ -+ /** -+ * @return True if it is a command being tab completed, false if it is a chat message. -+ */ -+ public boolean isCommand() { -+ return isCommand; -+ } -+ -+ /** -+ * @return The position looked at by the sender, or null if none -+ */ -+ @Nullable -+ public Location getLocation() { -+ return loc; -+ } -+ -+ /** -+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return Is completions considered handled. Always true if completions is not empty. -+ */ -+ public boolean isHandled() { -+ return !completions.isEmpty() || handled; -+ } -+ -+ /** -+ * Sets whether or not to consider the completion request handled. -+ * If true, the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @param handled if this completion should be marked as being handled -+ */ -+ public void setHandled(boolean handled) { -+ this.handled = handled; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Will provide no completions, and will not fire the synchronous process -+ * @param cancelled true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -index d1a9956a1573dab54c5ff2e5d67ca86cfe1dc01a..f96c4ba53ab41ea66d4f9a4d54eeabb63f992b58 100644 ---- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.server; - -+import java.util.ArrayList; - import java.util.List; - import org.apache.commons.lang.Validate; - import org.bukkit.command.CommandSender; -@@ -8,6 +9,7 @@ import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - import org.bukkit.event.player.PlayerCommandSendEvent; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - - /** - * Called when a {@link CommandSender} of any description (ie: player or -@@ -29,6 +31,13 @@ public class TabCompleteEvent extends Event implements Cancellable { - private boolean cancelled; - - public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions) { -+ // Paper start -+ this(sender, buffer, completions, sender instanceof org.bukkit.command.ConsoleCommandSender || buffer.startsWith("/"), null); -+ } -+ public TabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, @NotNull List completions, boolean isCommand, @Nullable org.bukkit.Location location) { -+ this.isCommand = isCommand; -+ this.loc = location; -+ // Paper end - Validate.notNull(sender, "sender"); - Validate.notNull(buffer, "buffer"); - Validate.notNull(completions, "completions"); -@@ -69,14 +78,35 @@ public class TabCompleteEvent extends Event implements Cancellable { - return completions; - } - -+ // Paper start -+ private final boolean isCommand; -+ private final org.bukkit.Location loc; -+ /** -+ * @return True if it is a command being tab completed, false if it is a chat message. -+ */ -+ public boolean isCommand() { -+ return isCommand; -+ } -+ -+ /** -+ * @return The position looked at by the sender, or null if none -+ */ -+ @Nullable -+ public org.bukkit.Location getLocation() { -+ return loc; -+ } -+ // Paper end -+ - /** - * Set the completions offered, overriding any already set. - * -+ * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here -+ * - * @param completions the new completions - */ - public void setCompletions(@NotNull List completions) { - Validate.notNull(completions); -- this.completions = completions; -+ this.completions = new ArrayList<>(completions); // Paper - } - - @Override diff --git a/Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch b/Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch deleted file mode 100644 index 2b6c78a2c4e0..000000000000 --- a/Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 9 Dec 2017 12:40:25 -0500 -Subject: [PATCH] Display warning on deprecated recipe API - -Any plugin still using this API will result in the server saving an inconsistent UUID to player data files, -which then triggers warnings such as "Tried to load unrecognized recipe: bukkit:9e5b92f5-e549-4f47-b0a8-9f89390ed77b removed now." -on the players login. - -Plugin authors need to define a key to keep it consistent between server restarts. - -diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index d74b3114f535e1e5e36ae007f1fe0522916a0362..d742c4058ba9aed4fbe1591fd755a06608b06e98 100644 ---- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -25,6 +25,7 @@ public class ShapedRecipe implements Recipe, Keyed { - public ShapedRecipe(@NotNull ItemStack result) { - Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); - this.key = NamespacedKey.randomKey(); -+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); - this.output = new ItemStack(result); - } - -diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -index 68447fb8c12356e779b96ec98c54119045046751..84062dd719cb8a6142dc8c806777cb208c6b42b2 100644 ---- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -@@ -26,6 +26,7 @@ public class ShapelessRecipe implements Recipe, Keyed { - public ShapelessRecipe(@NotNull ItemStack result) { - Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result."); - this.key = NamespacedKey.randomKey(); -+ new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); - this.output = new ItemStack(result); - } - diff --git a/Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch b/Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch deleted file mode 100644 index 906a8ec7c359..000000000000 --- a/Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:00:41 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7beb22d5105157940b39efe594ace9d4cb153f5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPickupExperienceEvent.java -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.ExperienceOrb; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player is attempting to pick up an experience orb -+ */ -+public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable { -+ @NotNull private final ExperienceOrb experienceOrb; -+ -+ public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) { -+ super(player); -+ this.experienceOrb = experienceOrb; -+ } -+ -+ /** -+ * @return Returns the Orb that the player is picking up -+ */ -+ @NotNull -+ public ExperienceOrb getExperienceOrb() { -+ return experienceOrb; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * If true, Cancels picking up the experience orb, leaving it in the world -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch b/Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch deleted file mode 100644 index 3a4722a77635..000000000000 --- a/Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:56:24 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0ce3e397716c28c30ed05e153babd0bfb9dd354a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.ExperienceOrb; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired anytime the server is about to merge 2 experience orbs into one -+ */ -+public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable { -+ @NotNull private final ExperienceOrb mergeTarget; -+ @NotNull private final ExperienceOrb mergeSource; -+ -+ public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) { -+ super(mergeTarget); -+ this.mergeTarget = mergeTarget; -+ this.mergeSource = mergeSource; -+ } -+ -+ /** -+ * @return The orb that will absorb the other experience orb -+ */ -+ @NotNull -+ public ExperienceOrb getMergeTarget() { -+ return mergeTarget; -+ } -+ -+ /** -+ * @return The orb that is subject to being removed and merged into the target orb -+ */ -+ @NotNull -+ public ExperienceOrb getMergeSource() { -+ return mergeSource; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * @param cancel true if you wish to cancel this event, and prevent the orbs from merging -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch b/Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index a225f3dedcba..000000000000 --- a/Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:38:07 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 21bed0d8075335538374fadfdf1cb868e4eebe80..9d1ad67b7d220ab425ac9bf6b1c8d8fb8d5f416c 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -892,12 +892,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - public void resetPlayerWeather(); - -+ // Paper start -+ /** -+ * Gives the player the amount of experience specified. -+ * -+ * @param amount Exp amount to give -+ */ -+ public default void giveExp(int amount) { -+ giveExp(amount, false); -+ } - /** - * Gives the player the amount of experience specified. - * - * @param amount Exp amount to give -+ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)} - */ -- public void giveExp(int amount); -+ public void giveExp(int amount, boolean applyMending); -+ -+ /** -+ * Applies the mending effect to any items just as picking up an orb would. -+ * -+ * Can also be called with {@link #giveExp(int, boolean)} by passing true to applyMending -+ * -+ * @param amount Exp to apply -+ * @return the remaining experience -+ */ -+ public int applyMending(int amount); -+ // Paper end - - /** - * Gives the player the amount of experience levels specified. Levels can diff --git a/Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch b/Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch deleted file mode 100644 index 0090330de9e3..000000000000 --- a/Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 16:59:43 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3ad231aa3206c8cfd5ec995249584cebab5d11f3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java -@@ -0,0 +1,105 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does. -+ * -+ * You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement". -+ * The intent of this event is to improve server performance, so it fires even if the spawning might fail later, for -+ * example when the entity would be unable to spawn due to limited space or lighting. -+ * -+ * Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions. -+ * Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event. -+ */ -+public class PreCreatureSpawnEvent extends Event implements Cancellable { -+ @NotNull private final Location location; -+ @NotNull private final EntityType type; -+ @NotNull private final CreatureSpawnEvent.SpawnReason reason; -+ private boolean shouldAbortSpawn; -+ -+ public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ this.location = Preconditions.checkNotNull(location, "Location may not be null").clone(); -+ this.type = Preconditions.checkNotNull(type, "Type may not be null"); -+ this.reason = Preconditions.checkNotNull(reason, "Reason may not be null"); -+ } -+ -+ /** -+ * @return The location this creature is being spawned at -+ */ -+ @NotNull -+ public Location getSpawnLocation() { -+ return location; -+ } -+ -+ /** -+ * @return The type of creature being spawned -+ */ -+ @NotNull -+ public EntityType getType() { -+ return type; -+ } -+ -+ /** -+ * @return Reason this creature is spawning (ie, NATURAL vs SPAWNER) -+ */ -+ @NotNull -+ public CreatureSpawnEvent.SpawnReason getReason() { -+ return reason; -+ } -+ -+ /** -+ * @return If the spawn process should be aborted vs trying more attempts -+ */ -+ public boolean shouldAbortSpawn() { -+ return shouldAbortSpawn; -+ } -+ -+ /** -+ * Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from -+ * trying more attempts after this cancellation. -+ * -+ * @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts -+ */ -+ public void setShouldAbortSpawn(boolean shouldAbortSpawn) { -+ this.shouldAbortSpawn = shouldAbortSpawn; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return If the spawn of this creature is cancelled or not -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancelling this event is more effecient than cancelling CreatureSpawnEvent -+ * @param cancel true if you wish to cancel this event, and abort the spawn of this creature -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch b/Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index a6fa8a9b726b..000000000000 --- a/Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:31:37 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..112a0dbf522b8e74ce882678434923814e6b187f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PlayerNaturallySpawnCreaturesEvent.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event -+ */ -+public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable { -+ private byte radius; -+ -+ public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) { -+ super(player); -+ this.radius = radius; -+ } -+ -+ /** -+ * @return The radius of chunks around this player to be included in natural spawn selection -+ */ -+ public byte getSpawnRadius() { -+ return radius; -+ } -+ -+ /** -+ * @param radius The radius of chunks around this player to be included in natural spawn selection -+ */ -+ public void setSpawnRadius(byte radius) { -+ this.radius = radius; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return If this players chunks will be excluded from natural spawns -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch b/Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index 42ffd3f94833..000000000000 --- a/Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:29:28 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/block/Skull.java b/src/main/java/org/bukkit/block/Skull.java -index 943d751fb3e48212fbe258845beba03c25fa22d9..a6914f01e01e9103702185f92b0209b3c84c152a 100644 ---- a/src/main/java/org/bukkit/block/Skull.java -+++ b/src/main/java/org/bukkit/block/Skull.java -@@ -7,6 +7,7 @@ import org.bukkit.block.data.BlockData; - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -+import com.destroystokyo.paper.profile.PlayerProfile; // Paper - - /** - * Represents a captured state of a skull block. -@@ -61,6 +62,20 @@ public interface Skull extends TileState { - */ - public void setOwningPlayer(@NotNull OfflinePlayer player); - -+ // Paper start -+ /** -+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. -+ * @param profile The profile to set this Skull to use, may not be null -+ */ -+ void setPlayerProfile(@NotNull PlayerProfile profile); -+ -+ /** -+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} -+ * @return The profile of the owner, if set -+ */ -+ @Nullable PlayerProfile getPlayerProfile(); -+ // Paper end -+ - /** - * Gets the rotation of the skull in the world (or facing direction if this - * is a wall mounted skull). -diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -index 496254f959345d74167a9b44d160ea1bb428c5a1..88d1c889c09adb91abb09a8e43a30c871b217da2 100644 ---- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java -@@ -1,9 +1,11 @@ - package org.bukkit.inventory.meta; - -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.OfflinePlayer; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -+ - /** - * Represents a skull that can have an owner. - */ -@@ -36,6 +38,20 @@ public interface SkullMeta extends ItemMeta { - @Deprecated - boolean setOwner(@Nullable String owner); - -+ // Paper start -+ /** -+ * Sets this skull to use the supplied Player Profile, which can include textures already prefilled. -+ * @param profile The profile to set this Skull to use, or null to clear owner -+ */ -+ void setPlayerProfile(@Nullable PlayerProfile profile); -+ -+ /** -+ * If the skull has an owner, per {@link #hasOwner()}, return the owners {@link PlayerProfile} -+ * @return The profile of the owner, if set -+ */ -+ @Nullable PlayerProfile getPlayerProfile(); -+ // Paper end -+ - /** - * Gets the owner of the skull. - * diff --git a/Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch b/Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch deleted file mode 100644 index 5511f6449a8e..000000000000 --- a/Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:08 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..71f36e9cae209ec6861835a5e76e018de959040a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/FillProfileEvent.java -@@ -0,0 +1,75 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired once a profiles additional properties (such as textures) has been filled -+ */ -+public class FillProfileEvent extends Event { -+ @NotNull private final PlayerProfile profile; -+ -+ public FillProfileEvent(@NotNull PlayerProfile profile) { -+ super(!org.bukkit.Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The Profile that had properties filled -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Same as .getPlayerProfile().getProperties() -+ * -+ * @see PlayerProfile#getProperties() -+ * @return The new properties on the profile. -+ */ -+ @NotNull -+ public Set getProperties() { -+ return profile.getProperties(); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..021bc86310a06f84b39459e0eb8927802726399c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/profile/PreFillProfileEvent.java -@@ -0,0 +1,77 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.profile; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.destroystokyo.paper.profile.ProfileProperty; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.util.Collection; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when the server is requesting to fill in properties of an incomplete profile, such as textures. -+ * -+ * Allows plugins to pre populate cached properties and avoid a call to the Mojang API -+ */ -+public class PreFillProfileEvent extends Event { -+ @NotNull private final PlayerProfile profile; -+ -+ public PreFillProfileEvent(@NotNull PlayerProfile profile) { -+ super(!org.bukkit.Bukkit.isPrimaryThread()); -+ this.profile = profile; -+ } -+ -+ /** -+ * @return The profile that needs its properties filled -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Sets the properties on the profile, avoiding the call to the Mojang API -+ * Same as .getPlayerProfile().setProperties(properties); -+ * -+ * @see PlayerProfile#setProperties(Collection) -+ * @param properties The properties to set/append -+ */ -+ public void setProperties(@NotNull Collection properties) { -+ profile.setProperties(properties); -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch b/Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index 5e8eaca58afc..000000000000 --- a/Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:14 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bb8d7c959cdea4b66455a49e74804ea4b126620d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAdvancementCriterionGrantEvent.java -@@ -0,0 +1,63 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.advancement.Advancement; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player is granted a criteria in an advancement. -+ */ -+public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Advancement advancement; -+ @NotNull private final String criterion; -+ private boolean cancel = false; -+ -+ public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) { -+ super(who); -+ this.advancement = advancement; -+ this.criterion = criterion; -+ } -+ -+ /** -+ * Get the advancement which has been affected. -+ * -+ * @return affected advancement -+ */ -+ @NotNull -+ public Advancement getAdvancement() { -+ return advancement; -+ } -+ -+ /** -+ * Get the criterion which has been granted. -+ * -+ * @return granted criterion -+ */ -+ @NotNull -+ public String getCriterion() { -+ return criterion; -+ } -+ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch b/Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 6287ef49e76f..000000000000 --- a/Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 27 Jan 2018 17:06:24 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -diff --git a/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7e4acfff16db80a75e1ff2fee1972b16955b0918 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/inventory/meta/ArmorStandMeta.java -@@ -0,0 +1,78 @@ -+package com.destroystokyo.paper.inventory.meta; -+ -+import org.bukkit.inventory.meta.ItemMeta; -+ -+public interface ArmorStandMeta extends ItemMeta { -+ -+ /** -+ * Gets whether the ArmorStand should be invisible when spawned -+ * -+ * @return true if this should be invisible -+ */ -+ boolean isInvisible(); -+ -+ /** -+ * Gets whether this ArmorStand should have no base plate when spawned -+ * -+ * @return true if it will not have a base plate -+ */ -+ boolean hasNoBasePlate(); -+ -+ /** -+ * Gets whether this ArmorStand should show arms when spawned -+ * -+ * @return true if it will show arms -+ */ -+ boolean shouldShowArms(); -+ -+ /** -+ * Gets whether this ArmorStand will be small when spawned -+ * -+ * @return true if it will be small -+ */ -+ boolean isSmall(); -+ -+ /** -+ * Gets whether this ArmorStand will be a marker when spawned -+ * The exact details of this flag are an implementation detail -+ * -+ * @return true if it will be a marker -+ */ -+ boolean isMarker(); -+ -+ /** -+ * Sets that this ArmorStand should be invisible when spawned -+ * -+ * @param invisible true if set invisible -+ */ -+ void setInvisible(boolean invisible); -+ -+ /** -+ * Sets that this ArmorStand should have no base plate when spawned -+ * -+ * @param noBasePlate true if no base plate -+ */ -+ void setNoBasePlate(boolean noBasePlate); -+ -+ /** -+ * Sets that this ArmorStand should show arms when spawned -+ * -+ * @param showArms true if show arms -+ */ -+ void setShowArms(boolean showArms); -+ -+ /** -+ * Sets that this ArmorStand should be small when spawned -+ * -+ * @param small true if small -+ */ -+ void setSmall(boolean small); -+ -+ /** -+ * Sets that this ArmorStand should be a marker when spawned -+ * The exact details of this flag are an implementation detail -+ * -+ * @param marker true if a marker -+ */ -+ void setMarker(boolean marker); -+} diff --git a/Spigot-API-Patches/0084-Optimize-Hoppers.patch b/Spigot-API-Patches/0084-Optimize-Hoppers.patch deleted file mode 100644 index 79c141af5538..000000000000 --- a/Spigot-API-Patches/0084-Optimize-Hoppers.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 18 Jan 2018 01:00:27 -0500 -Subject: [PATCH] Optimize Hoppers - -Adds data about what Item related methods were used in InventoryMoveItem event -so that the server can improve the performance of this event. - -diff --git a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -index a8c48f5a416326e96c431e5fa22edee04825530e..04d4a83bfc4f86341f9d72128458154d08c8ec43 100644 ---- a/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/InventoryMoveItemEvent.java -@@ -31,6 +31,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - private final Inventory destinationInventory; - private ItemStack itemStack; - private final boolean didSourceInitiate; -+ public boolean calledGetItem; // Paper -+ public boolean calledSetItem; // Paper - - public InventoryMoveItemEvent(@NotNull final Inventory sourceInventory, @NotNull final ItemStack itemStack, @NotNull final Inventory destinationInventory, final boolean didSourceInitiate) { - Validate.notNull(itemStack, "ItemStack cannot be null"); -@@ -58,7 +60,8 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - */ - @NotNull - public ItemStack getItem() { -- return itemStack.clone(); -+ calledGetItem = true; // Paper - record this method was used for auto detection of mode -+ return itemStack; // Paper - Removed clone, handled better in Server - } - - /** -@@ -70,6 +73,7 @@ public class InventoryMoveItemEvent extends Event implements Cancellable { - */ - public void setItem(@NotNull ItemStack itemStack) { - Validate.notNull(itemStack, "ItemStack cannot be null. Cancel the event if you want nothing to be transferred."); -+ calledSetItem = true; // Paper - record this method was used for auto detection of mode - this.itemStack = itemStack.clone(); - } - diff --git a/Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index a2a9f5270fae..000000000000 --- a/Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:43:30 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index 992d1025ca02020e87a9ab5db83d249427f41d69..a40b57edb1aeff71fc0b9767d410950da5c06283 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -2,6 +2,9 @@ package org.bukkit.event.player; - - import java.net.InetAddress; - import java.util.UUID; -+ -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - import org.jetbrains.annotations.NotNull; -@@ -15,9 +18,9 @@ public class AsyncPlayerPreLoginEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private Result result; - private net.kyori.adventure.text.Component message; // Paper -- private final String name; -+ //private String name; // Paper - Not used anymore - private final InetAddress ipAddress; -- private final UUID uniqueId; -+ //private UUID uniqueId; // Paper - Not used anymore - - @Deprecated - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress) { -@@ -25,12 +28,37 @@ public class AsyncPlayerPreLoginEvent extends Event { - } - - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { -+ // Paper start -+ this(name, ipAddress, uniqueId, Bukkit.createProfile(uniqueId, name)); -+ } -+ private PlayerProfile profile; -+ -+ /** -+ * Gets the PlayerProfile of the player logging in -+ * @return The Profile -+ */ -+ @NotNull -+ public PlayerProfile getPlayerProfile() { -+ return profile; -+ } -+ -+ /** -+ * Changes the PlayerProfile the player will login as -+ * @param profile The profile to use -+ */ -+ public void setPlayerProfile(@NotNull PlayerProfile profile) { -+ this.profile = profile; -+ } -+ -+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { - super(true); -+ this.profile = profile; -+ // Paper end - this.result = Result.ALLOWED; - this.message = net.kyori.adventure.text.Component.empty(); // Paper -- this.name = name; -+ //this.name = name; // Paper - Not used anymore - this.ipAddress = ipAddress; -- this.uniqueId = uniqueId; -+ //this.uniqueId = uniqueId; // Paper - Not used anymore - } - - /** -@@ -193,7 +221,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - */ - @NotNull - public String getName() { -- return name; -+ return profile.getName(); // Paper - } - - /** -@@ -213,7 +241,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - */ - @NotNull - public UUID getUniqueId() { -- return uniqueId; -+ return profile.getId(); // Paper - } - - @NotNull diff --git a/Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch b/Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch deleted file mode 100644 index f35ae4323f9a..000000000000 --- a/Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,381 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:55:38 +0200 -Subject: [PATCH] Add extended PaperServerListPingEvent - -Add a new event that extends the original ServerListPingEvent -and allows full control of the response sent to the client. - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..baac2e4f090a490372ef4aed92c8a5771955e921 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java -@@ -0,0 +1,334 @@ -+package com.destroystokyo.paper.event.server; -+ -+import static java.util.Objects.requireNonNull; -+ -+import com.destroystokyo.paper.network.StatusClient; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import org.bukkit.Bukkit; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.server.ServerListPingEvent; -+import org.bukkit.util.CachedServerIcon; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.NoSuchElementException; -+import java.util.UUID; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Extended version of {@link ServerListPingEvent} that allows full control -+ * of the response sent to the client. -+ */ -+public class PaperServerListPingEvent extends ServerListPingEvent implements Cancellable { -+ -+ @NotNull private final StatusClient client; -+ -+ private int numPlayers; -+ private boolean hidePlayers; -+ @NotNull private final List playerSample = new ArrayList<>(); -+ -+ @NotNull private String version; -+ private int protocolVersion; -+ -+ @Nullable private CachedServerIcon favicon; -+ -+ private boolean cancelled; -+ -+ private boolean originalPlayerCount = true; -+ private Object[] players; -+ -+ @Deprecated -+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers, -+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { -+ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); -+ this.client = client; -+ this.numPlayers = numPlayers; -+ this.version = version; -+ this.protocolVersion = protocolVersion; -+ setServerIcon(favicon); -+ } -+ -+ public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull net.kyori.adventure.text.Component motd, int numPlayers, int maxPlayers, -+ @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) { -+ super(client.getAddress().getAddress(), motd, numPlayers, maxPlayers); -+ this.client = client; -+ this.numPlayers = numPlayers; -+ this.version = version; -+ this.protocolVersion = protocolVersion; -+ setServerIcon(favicon); -+ } -+ -+ /** -+ * Returns the {@link StatusClient} pinging the server. -+ * -+ * @return The client -+ */ -+ @NotNull -+ public StatusClient getClient() { -+ return this.client; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

Returns {@code -1} if players are hidden using -+ * {@link #shouldHidePlayers()}.

-+ */ -+ @Override -+ public int getNumPlayers() { -+ if (this.hidePlayers) { -+ return -1; -+ } -+ -+ return this.numPlayers; -+ } -+ -+ /** -+ * Sets the number of players displayed in the server list. -+ * -+ *

Note that this won't have any effect if {@link #shouldHidePlayers()} -+ * is enabled.

-+ * -+ * @param numPlayers The number of online players -+ */ -+ public void setNumPlayers(int numPlayers) { -+ if (this.numPlayers != numPlayers) { -+ this.numPlayers = numPlayers; -+ this.originalPlayerCount = false; -+ } -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

Returns {@code -1} if players are hidden using -+ * {@link #shouldHidePlayers()}.

-+ */ -+ @Override -+ public int getMaxPlayers() { -+ if (this.hidePlayers) { -+ return -1; -+ } -+ -+ return super.getMaxPlayers(); -+ } -+ -+ /** -+ * Returns whether all player related information is hidden in the server -+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} -+ * and {@link #getPlayerSample()} to be skipped in the response. -+ * -+ *

The Vanilla Minecraft client will display the player count as {@code ???} -+ * when this option is enabled.

-+ * -+ * @return {@code true} if the player count is hidden -+ */ -+ public boolean shouldHidePlayers() { -+ return hidePlayers; -+ } -+ -+ /** -+ * Sets whether all player related information is hidden in the server -+ * list. This will cause {@link #getNumPlayers()}, {@link #getMaxPlayers()} -+ * and {@link #getPlayerSample()} to be skipped in the response. -+ * -+ *

The Vanilla Minecraft client will display the player count as {@code ???} -+ * when this option is enabled.

-+ * -+ * @param hidePlayers {@code true} if the player count should be hidden -+ */ -+ public void setHidePlayers(boolean hidePlayers) { -+ this.hidePlayers = hidePlayers; -+ } -+ -+ /** -+ * Returns a mutable list of {@link PlayerProfile} that will be displayed -+ * as online players on the client. -+ * -+ *

The Vanilla Minecraft client will display them when hovering the -+ * player count with the mouse.

-+ * -+ * @return The mutable player sample list -+ */ -+ @NotNull -+ public List getPlayerSample() { -+ return this.playerSample; -+ } -+ -+ /** -+ * Returns the version that will be sent as server version on the client. -+ * -+ * @return The server version -+ */ -+ @NotNull -+ public String getVersion() { -+ return version; -+ } -+ -+ /** -+ * Sets the version that will be sent as server version to the client. -+ * -+ * @param version The server version -+ */ -+ public void setVersion(@NotNull String version) { -+ this.version = requireNonNull(version, "version"); -+ } -+ -+ /** -+ * Returns the protocol version that will be sent as the protocol version -+ * of the server to the client. -+ * -+ * @return The protocol version of the server, or {@code -1} if the server -+ * has not finished initialization yet -+ */ -+ public int getProtocolVersion() { -+ return protocolVersion; -+ } -+ -+ /** -+ * Sets the protocol version that will be sent as the protocol version -+ * of the server to the client. -+ * -+ * @param protocolVersion The protocol version of the server -+ */ -+ public void setProtocolVersion(int protocolVersion) { -+ this.protocolVersion = protocolVersion; -+ } -+ -+ /** -+ * Gets the server icon sent to the client. -+ * -+ * @return The icon to send to the client, or {@code null} for none -+ */ -+ @Nullable -+ public CachedServerIcon getServerIcon() { -+ return this.favicon; -+ } -+ -+ /** -+ * Sets the server icon sent to the client. -+ * -+ * @param icon The icon to send to the client, or {@code null} for none -+ */ -+ @Override -+ public void setServerIcon(@Nullable CachedServerIcon icon) { -+ if (icon != null && icon.isEmpty()) { -+ // Represent empty icons as null -+ icon = null; -+ } -+ -+ this.favicon = icon; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

Cancelling this event will cause the connection to be closed immediately, -+ * without sending a response to the client.

-+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

Cancelling this event will cause the connection to be closed immediately, -+ * without sending a response to the client.

-+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ *

Note: For compatibility reasons, this method will return all -+ * online players, not just the ones referenced in {@link #getPlayerSample()}. -+ * Removing a player will:

-+ * -+ *
    -+ *
  • Decrement the online player count (if and only if) the player -+ * count wasn't changed by another plugin before.
  • -+ *
  • Remove all entries from {@link #getPlayerSample()} that refer to -+ * the removed player (based on their {@link UUID}).
  • -+ *
-+ */ -+ @NotNull -+ @Override -+ public Iterator iterator() { -+ if (this.players == null) { -+ this.players = getOnlinePlayers(); -+ } -+ -+ return new PlayerIterator(); -+ } -+ -+ @NotNull -+ protected Object[] getOnlinePlayers() { -+ return Bukkit.getOnlinePlayers().toArray(); -+ } -+ -+ @NotNull -+ protected Player getBukkitPlayer(@NotNull Object player) { -+ return (Player) player; -+ } -+ -+ private final class PlayerIterator implements Iterator { -+ -+ private int next; -+ private int current; -+ @Nullable private Player player; -+ -+ @Override -+ public boolean hasNext() { -+ for (; this.next < players.length; this.next++) { -+ if (players[this.next] != null) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @NotNull -+ @Override -+ public Player next() { -+ if (!hasNext()) { -+ this.player = null; -+ throw new NoSuchElementException(); -+ } -+ -+ this.current = this.next++; -+ return this.player = getBukkitPlayer(players[this.current]); -+ } -+ -+ @Override -+ public void remove() { -+ if (this.player == null) { -+ throw new IllegalStateException(); -+ } -+ -+ UUID uniqueId = this.player.getUniqueId(); -+ this.player = null; -+ -+ // Remove player from iterator -+ players[this.current] = null; -+ -+ // Remove player from sample -+ getPlayerSample().removeIf(p -> uniqueId.equals(p.getId())); -+ -+ // Decrement player count -+ if (originalPlayerCount) { -+ numPlayers--; -+ } -+ } -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..517d15238ed117f38bbd39f570874014cecf7bb5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -@@ -0,0 +1,13 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+ -+/** -+ * Represents a client requesting the current status from the server (e.g. from -+ * the server list). -+ * -+ * @see PaperServerListPingEvent -+ */ -+public interface StatusClient extends NetworkClient { -+ -+} -diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java -index 612958a331575d1da2715531ebdf6b1168f2e860..bb4f7702ced0baf0670a7a21d48ad528b7249361 100644 ---- a/src/main/java/org/bukkit/util/CachedServerIcon.java -+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java -@@ -18,4 +18,9 @@ public interface CachedServerIcon { - @Nullable - public String getData(); // Paper - -+ // Paper start -+ default boolean isEmpty() { -+ return getData() == null; -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch b/Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch deleted file mode 100644 index 5a914436aec3..000000000000 --- a/Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:28:55 -0400 -Subject: [PATCH] Player.setPlayerProfile API - -This can be useful for changing name or skins after a player has logged in. - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 9a262d412b2762a33a60b1e8762a7d9c9c3f933d..3ae4d670059f80bd057870a37f4025261e397dfa 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -4,6 +4,7 @@ import java.net.InetSocketAddress; - import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; -+import com.destroystokyo.paper.profile.PlayerProfile; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -1714,6 +1715,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED} - */ - boolean hasResourcePack(); -+ -+ /** -+ * Gets a copy of this players profile -+ * @return The players profile object -+ */ -+ @NotNull -+ PlayerProfile getPlayerProfile(); -+ -+ /** -+ * Changes the PlayerProfile for this player. This will cause this player -+ * to be reregistered to all clients that can currently see this player -+ * @param profile The new profile to use -+ */ -+ void setPlayerProfile(@NotNull PlayerProfile profile); - // Paper end - - // Spigot start diff --git a/Spigot-API-Patches/0089-getPlayerUniqueId-API.patch b/Spigot-API-Patches/0089-getPlayerUniqueId-API.patch deleted file mode 100644 index 6586351ea90e..000000000000 --- a/Spigot-API-Patches/0089-getPlayerUniqueId-API.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 22 Mar 2018 01:39:28 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -In Offline Mode, will return an Offline UUID - -This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index f5d3a7370390871d1b6075f32846d1a942b05b7f..2d7f8e128e23934a8fe26baf19198b7ffc8447bb 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -504,6 +504,20 @@ public final class Bukkit { - return server.getPlayer(id); - } - -+ // Paper start -+ /** -+ * Gets the unique ID of the player currently known as the specified player name -+ * In Offline Mode, will return an Offline UUID -+ * -+ * @param playerName the player name to look up the unique ID for -+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode -+ */ -+ @Nullable -+ public static UUID getPlayerUniqueId(@NotNull String playerName) { -+ return server.getPlayerUniqueId(playerName); -+ } -+ // Paper end -+ - /** - * Gets the plugin manager for interfacing with plugins. - * -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 38d138b217734e598581ed14065ff2015135ee9a..01657abaff86cf7bb3ffb857024c5032781b8660 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -429,6 +429,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - public Player getPlayer(@NotNull UUID id); - -+ // Paper start -+ /** -+ * Gets the unique ID of the player currently known as the specified player name -+ * In Offline Mode, will return an Offline UUID -+ * -+ * @param playerName the player name to look up the unique ID for -+ * @return A UUID, or null if that player name is not registered with Minecraft and the server is in online mode -+ */ -+ @Nullable -+ public UUID getPlayerUniqueId(@NotNull String playerName); -+ // Paper end -+ - /** - * Gets the plugin manager for interfacing with plugins. - * diff --git a/Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch deleted file mode 100644 index f21c766148fe..000000000000 --- a/Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:20 +0200 -Subject: [PATCH] Add legacy ping support to PaperServerListPingEvent - -Add a new method to StatusClient check if the client is a legacy -client that does not support all of the features provided in the -event. - -diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -index 517d15238ed117f38bbd39f570874014cecf7bb5..ffda9f6a8b094942009aa78b331d22d9dcca2802 100644 ---- a/src/main/java/com/destroystokyo/paper/network/StatusClient.java -+++ b/src/main/java/com/destroystokyo/paper/network/StatusClient.java -@@ -10,4 +10,16 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent; - */ - public interface StatusClient extends NetworkClient { - -+ /** -+ * Returns whether the client is using an older version that doesn't -+ * support all of the features in {@link PaperServerListPingEvent}. -+ * -+ *

For Vanilla, this returns {@code true} for all clients older than 1.7.

-+ * -+ * @return {@code true} if the client is using legacy ping -+ */ -+ default boolean isLegacy() { -+ return false; -+ } -+ - } diff --git a/Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch b/Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index c75d281c238f..000000000000 --- a/Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:28:43 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index d212d5123b6294f7873d72f125505a006c290b05..7430bc85301d0fcb34c6035fbe08ae245c76e043 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -461,6 +461,14 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - @Deprecated - public void setShoulderEntityRight(@Nullable Entity entity); -+ // Paper start - Add method to open already placed sign -+ /** -+ * Opens an editor window for the specified sign -+ * -+ * @param sign The sign to open -+ */ -+ void openSign(@NotNull org.bukkit.block.Sign sign); -+ // Paper end - - /** - * Make the entity drop the item in their hand. diff --git a/Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch b/Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch deleted file mode 100644 index 540eeb4d36d1..000000000000 --- a/Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Apr 2018 10:28:50 -0400 -Subject: [PATCH] Add Ban Methods to Player Objects - -Allows a more logical API for banning players. - -player.banPlayer("Breaking the rules"); - -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 58313929f81509030216a0e5e3869da63e11108e..6cf05fed701c67a2c797a4e0839c795802a238a1 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -45,6 +45,61 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - * @return true if banned, otherwise false - */ - public boolean isBanned(); -+ // Paper start -+ -+ /** -+ * Permanently Bans this player from the server -+ * -+ * @param reason Reason for Ban -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason) { -+ return banPlayer(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans this player from the server -+ * @param reason Reason for Ban -+ * @param source Source of the ban, or null for default -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable String source) { -+ return banPlayer(reason, null, source); -+ } -+ -+ /** -+ * Bans this player from the server -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires) { -+ return banPlayer(reason, expires, null); -+ } -+ -+ /** -+ * Bans this player from the server -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the ban or null for default -+ * @return Ban Entry -+ */ -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source) { -+ return banPlayer(reason, expires, source, true); -+ } -+ @NotNull -+ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.Date expires, @Nullable String source, boolean kickIfOnline) { -+ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.NAME).addBan(getName(), reason, expires, source); -+ if (kickIfOnline && isOnline()) { -+ getPlayer().kickPlayer(reason); -+ } -+ return banEntry; -+ } -+ // Paper end - - /** - * Checks if this player is whitelisted or not -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6769330f336afcd5f26c0f7286defa00bead543c..88fd4cdeaad4d27f414c6b268022cdedf73492e7 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -5,6 +5,10 @@ import java.util.UUID; - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper -+import java.util.Date; // Paper -+import org.bukkit.BanEntry; // Paper -+import org.bukkit.BanList; // Paper -+import org.bukkit.Bukkit; // Paper - import org.bukkit.DyeColor; - import org.bukkit.Effect; - import org.bukkit.GameMode; -@@ -618,6 +622,162 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - public void sendMap(@NotNull MapView map); - - // Paper start -+ /** -+ * Permanently Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for ban -+ * @return Ban Entry -+ */ -+ // For reference, Bukkit defines this as nullable, while they impl isn't, we'll follow API. -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason) { -+ return banPlayerFull(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable String source) { -+ return banPlayerFull(reason, null, source); -+ } -+ -+ /** -+ * Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires) { -+ return banPlayerFull(reason, expires, null); -+ } -+ -+ /** -+ * Bans the Profile and IP address currently used by the player. -+ * -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerFull(@Nullable String reason, @Nullable Date expires, @Nullable String source) { -+ banPlayer(reason, expires, source); -+ return banPlayerIP(reason, expires, source, true); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * -+ * @param reason Reason for ban -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, boolean kickPlayer) { -+ return banPlayerIP(reason, null, null, kickPlayer); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source, boolean kickPlayer) { -+ return banPlayerIP(reason, null, source, kickPlayer); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param kickPlayer Whether or not to kick the player afterwards -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, boolean kickPlayer) { -+ return banPlayerIP(reason, expires, null, kickPlayer); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * -+ * @param reason Reason for ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason) { -+ return banPlayerIP(reason, null, null); -+ } -+ -+ /** -+ * Permanently Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for ban -+ * @param source Source of ban, or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable String source) { -+ return banPlayerIP(reason, null, source); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires) { -+ return banPlayerIP(reason, expires, null); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the banm or null for default -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source) { -+ return banPlayerIP(reason, expires, source, true); -+ } -+ -+ /** -+ * Bans the IP address currently used by the player. -+ * Does not ban the Profile, use {@link #banPlayerFull(String, Date, String)} -+ * @param reason Reason for Ban -+ * @param expires When to expire the ban -+ * @param source Source of the banm or null for default -+ * @param kickPlayer if the targeted player should be kicked -+ * @return Ban Entry -+ */ -+ @Nullable -+ public default BanEntry banPlayerIP(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer) { -+ BanEntry banEntry = Bukkit.getServer().getBanList(BanList.Type.IP).addBan(getAddress().getAddress().getHostAddress(), reason, expires, source); -+ if (kickPlayer && isOnline()) { -+ getPlayer().kickPlayer(reason); -+ } -+ -+ return banEntry; -+ } - - /** - * Sends an Action Bar message to the client. diff --git a/Spigot-API-Patches/0093-EndermanEscapeEvent.patch b/Spigot-API-Patches/0093-EndermanEscapeEvent.patch deleted file mode 100644 index 82d22fd0ea26..000000000000 --- a/Spigot-API-Patches/0093-EndermanEscapeEvent.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:14:30 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..806112a8b5a7ce31166675f5b074ceaf42e364b6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java -@@ -0,0 +1,87 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public class EndermanEscapeEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Reason reason; -+ -+ public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) { -+ super(entity); -+ this.reason = reason; -+ } -+ -+ @NotNull -+ @Override -+ public Enderman getEntity() { -+ return (Enderman) super.getEntity(); -+ } -+ -+ /** -+ * @return The reason the enderman is trying to escape -+ */ -+ @NotNull -+ public Reason getReason() { -+ return reason; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancels the escape. -+ * -+ * If this escape normally would of resulted in damage avoidance such as indirect, -+ * the enderman will now take damage. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ public enum Reason { -+ /** -+ * The enderman has stopped attacking and ran away -+ */ -+ RUNAWAY, -+ /** -+ * The enderman has teleported away due to indirect damage (ranged) -+ */ -+ INDIRECT, -+ /** -+ * The enderman has teleported away due to a critical hit -+ */ -+ CRITICAL_HIT, -+ /** -+ * The enderman has teleported away due to the player staring at it during combat -+ */ -+ STARE, -+ /** -+ * Specific case for CRITICAL_HIT where the enderman is taking rain damage -+ */ -+ DROWN -+ } -+} diff --git a/Spigot-API-Patches/0094-Enderman.teleportRandomly.patch b/Spigot-API-Patches/0094-Enderman.teleportRandomly.patch deleted file mode 100644 index 9c226d009ced..000000000000 --- a/Spigot-API-Patches/0094-Enderman.teleportRandomly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:15 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/org/bukkit/entity/Enderman.java b/src/main/java/org/bukkit/entity/Enderman.java -index bb325d9c802e33431530bbccdcf5de5839e5fe68..821c690f8a32918bdb284ffec4af98f411f76ccc 100644 ---- a/src/main/java/org/bukkit/entity/Enderman.java -+++ b/src/main/java/org/bukkit/entity/Enderman.java -@@ -10,6 +10,17 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Enderman extends Monster { - -+ // Paper start -+ /** -+ * Try to teleport the enderman to a random nearby location. -+ * -+ * May conditionally fail if the random location was not valid -+ * @return If the enderman teleported successfully or not -+ */ -+ -+ public boolean teleportRandomly(); -+ // Paper end -+ - /** - * Gets the id and data of the block that the Enderman is carrying. - * diff --git a/Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch b/Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch deleted file mode 100644 index cde5bb214846..000000000000 --- a/Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch +++ /dev/null @@ -1,292 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:55:28 -0400 -Subject: [PATCH] Additional world.getNearbyEntities API's - -Provides more methods to get nearby entities, and filter by types and predicates - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 0f86a9c67797fd662cbbfdb808789bcab95caba4..cae848ce698337d0b254bd48938abfc1e68ad561 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1,6 +1,9 @@ - package org.bukkit; - - import java.io.File; -+import org.bukkit.generator.ChunkGenerator; -+ -+import java.util.ArrayList; - import java.util.Collection; - import java.util.HashMap; - import java.util.List; -@@ -659,6 +662,256 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Collection getEntitiesByClasses(@NotNull Class... classes); - -+ // Paper start -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyLivingEntities(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, loc, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X/Y/Z Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param radius X/Y/Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyPlayers(@NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, loc, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param radius X/Y/Z radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius) { -+ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(clazz, loc, xRadius, yRadius, zRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param radius X/Y/Z radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, loc, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, loc, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param loc Center location -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public default Collection getNearbyEntitiesByType(@Nullable Class clazz, @NotNull Location loc, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ if (clazz == null) { -+ clazz = Entity.class; -+ } -+ List nearby = new ArrayList<>(); -+ for (Entity bukkitEntity : getNearbyEntities(loc, xRadius, yRadius, zRadius)) { -+ //noinspection unchecked -+ if (clazz.isAssignableFrom(bukkitEntity.getClass()) && (predicate == null || predicate.test((T) bukkitEntity))) { -+ //noinspection unchecked -+ nearby.add((T) bukkitEntity); -+ } -+ } -+ return nearby; -+ } -+ // Paper end -+ - /** - * Get a list of all players in this World - * -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index a40b57edb1aeff71fc0b9767d410950da5c06283..184d9462ebbc500d8b81aaf14fe138d247bf2470 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -42,8 +42,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - return profile; - } - -- /** -- * Changes the PlayerProfile the player will login as -+ /* * Changes the PlayerProfile the player will login as - * @param profile The profile to use - */ - public void setPlayerProfile(@NotNull PlayerProfile profile) { diff --git a/Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch b/Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch deleted file mode 100644 index 1670d203489c..000000000000 --- a/Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 19:27:31 -0400 -Subject: [PATCH] Location.isChunkLoaded() API - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 0939a8070f9cc4f66f1679fef74862debb7d32ae..6c8b8eddcdb81f7151202eb12541308040790d45 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -533,6 +533,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - return this; - } - -+ public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - @Override - public boolean equals(Object obj) { - if (obj == null) { diff --git a/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch b/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index ee5d06483dcd..000000000000 --- a/Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 29 Aug 2017 23:58:48 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/com/destroystokyo/paper/ParticleBuilder.java b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..06f1602f5b327705f726d0a99dd6b95e1554d382 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ParticleBuilder.java -@@ -0,0 +1,478 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.collect.Lists; -+import org.bukkit.Color; -+import org.bukkit.Location; -+import org.bukkit.Particle; -+import org.bukkit.World; -+import org.bukkit.entity.Player; -+import org.bukkit.util.NumberConversions; -+ -+import java.util.Collection; -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Helps prepare a particle to be sent to players. -+ * -+ * Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API -+ */ -+public class ParticleBuilder { -+ -+ private Particle particle; -+ private List receivers; -+ private Player source; -+ private Location location; -+ private int count = 1; -+ private double offsetX = 0, offsetY = 0, offsetZ = 0; -+ private double extra = 1; -+ private Object data; -+ private boolean force = true; -+ -+ public ParticleBuilder(@NotNull Particle particle) { -+ this.particle = particle; -+ } -+ -+ /** -+ * Sends the particle to all receiving players (or all). This method is safe to use -+ * Asynchronously -+ * -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder spawn() { -+ if (this.location == null) { -+ throw new IllegalStateException("Please specify location for this particle"); -+ } -+ location.getWorld().spawnParticle(particle, receivers, source, -+ location.getX(), location.getY(), location.getZ(), -+ count, offsetX, offsetY, offsetZ, extra, data, force -+ ); -+ return this; -+ } -+ -+ /** -+ * @return The particle going to be sent -+ */ -+ @NotNull -+ public Particle particle() { -+ return particle; -+ } -+ -+ /** -+ * Changes what particle will be sent -+ * -+ * @param particle The particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder particle(@NotNull Particle particle) { -+ this.particle = particle; -+ return this; -+ } -+ -+ /** -+ * @return List of players who will receive the particle, or null for all in world -+ */ -+ @Nullable -+ public List receivers() { -+ return receivers; -+ } -+ -+ /** -+ * Example use: -+ * -+ * builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); } -+ * -+ * @return If this particle is going to be sent to someone -+ */ -+ public boolean hasReceivers() { -+ return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || ( -+ receivers != null && !receivers.isEmpty()); -+ } -+ -+ /** -+ * Sends this particle to all players in the world. This is rather silly and you should likely not -+ * be doing this. -+ * -+ * Just be a logical person and use receivers by radius or collection. -+ * -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder allPlayers() { -+ this.receivers = null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable List receivers) { -+ // Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars -+ // TODO: deprecate? -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable Collection receivers) { -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * @param receivers List of players to be receive this particle, or null for all players in the -+ * world -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(@Nullable Player... receivers) { -+ this.receivers = receivers != null ? Lists.newArrayList(receivers) : null; -+ return this; -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. If you want a more spherical check, see {@link #receivers(int, -+ * boolean)} -+ * -+ * @param radius amount to add on all axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int radius) { -+ return receivers(radius, radius); -+ } -+ -+ /** -+ * Selects all players within the specified radius around the particle location. If byDistance is -+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is -+ * true, radius is tested by distance in a spherical shape -+ * -+ * @param radius amount to add on each axis -+ * @param byDistance true to use a spherical radius, false to use a cuboid -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int radius, boolean byDistance) { -+ if (!byDistance) { -+ return receivers(radius, radius, radius); -+ } else { -+ this.receivers = Lists.newArrayList(); -+ for (Player nearbyPlayer : location.getWorld() -+ .getNearbyPlayers(location, radius, radius, radius)) { -+ Location loc = nearbyPlayer.getLocation(); -+ double x = NumberConversions.square(location.getX() - loc.getX()); -+ double y = NumberConversions.square(location.getY() - loc.getY()); -+ double z = NumberConversions.square(location.getZ() - loc.getZ()); -+ if (Math.sqrt(x + y + z) > radius) { -+ continue; -+ } -+ this.receivers.add(nearbyPlayer); -+ } -+ return this; -+ } -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. Allows specifying a different Y size than X and Z If you want a more -+ * cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check, -+ * see {@link #receivers(int, boolean)} -+ * -+ * @param xzRadius amount to add on the x/z axis -+ * @param yRadius amount to add on the y axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xzRadius, int yRadius) { -+ return receivers(xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Selects all players within the specified radius around the particle location. If byDistance is -+ * false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is -+ * true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape. -+ * -+ * @param xzRadius amount to add on the x/z axis -+ * @param yRadius amount to add on the y axis -+ * @param byDistance true to use a cylinder shape, false to use cuboid -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) { -+ if (!byDistance) { -+ return receivers(xzRadius, yRadius, xzRadius); -+ } else { -+ this.receivers = Lists.newArrayList(); -+ for (Player nearbyPlayer : location.getWorld() -+ .getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) { -+ Location loc = nearbyPlayer.getLocation(); -+ if (Math.abs(loc.getY() - this.location.getY()) > yRadius) { -+ continue; -+ } -+ double x = NumberConversions.square(location.getX() - loc.getX()); -+ double z = NumberConversions.square(location.getZ() - loc.getZ()); -+ if (x + z > NumberConversions.square(xzRadius)) { -+ continue; -+ } -+ this.receivers.add(nearbyPlayer); -+ } -+ return this; -+ } -+ } -+ -+ /** -+ * Selects all players within a cuboid selection around the particle location, within the -+ * specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int, -+ * boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)} -+ * -+ * @param xRadius amount to add on the x axis -+ * @param yRadius amount to add on the y axis -+ * @param zRadius amount to add on the z axis -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) { -+ if (location == null) { -+ throw new IllegalStateException("Please set location first"); -+ } -+ return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius)); -+ } -+ -+ /** -+ * @return The player considered the source of this particle (for Visibility concerns), or null -+ */ -+ @Nullable -+ public Player source() { -+ return source; -+ } -+ -+ /** -+ * Sets the source of this particle for visibility concerns (Vanish API) -+ * -+ * @param source The player who is considered the source -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder source(@Nullable Player source) { -+ this.source = source; -+ return this; -+ } -+ -+ /** -+ * @return Location of where the particle will spawn -+ */ -+ @Nullable -+ public Location location() { -+ return location; -+ } -+ -+ /** -+ * Sets the location of where to spawn the particle -+ * -+ * @param location The location of the particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder location(@NotNull Location location) { -+ this.location = location.clone(); -+ return this; -+ } -+ -+ /** -+ * Sets the location of where to spawn the particle -+ * -+ * @param world World to spawn particle in -+ * @param x X location -+ * @param y Y location -+ * @param z Z location -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder location(@NotNull World world, double x, double y, double z) { -+ this.location = new Location(world, x, y, z); -+ return this; -+ } -+ -+ /** -+ * @return Number of particles to spawn -+ */ -+ public int count() { -+ return count; -+ } -+ -+ /** -+ * Sets the number of particles to spawn -+ * -+ * @param count Number of particles -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder count(int count) { -+ this.count = count; -+ return this; -+ } -+ -+ /** -+ * Particle offset X. Varies by particle on how this is used -+ * -+ * @return Particle offset X. -+ */ -+ public double offsetX() { -+ return offsetX; -+ } -+ -+ /** -+ * Particle offset Y. Varies by particle on how this is used -+ * -+ * @return Particle offset Y. -+ */ -+ public double offsetY() { -+ return offsetY; -+ } -+ -+ /** -+ * Particle offset Z. Varies by particle on how this is used -+ * -+ * @return Particle offset Z. -+ */ -+ public double offsetZ() { -+ return offsetZ; -+ } -+ -+ /** -+ * Sets the particle offset. Varies by particle on how this is used -+ * -+ * @param offsetX Particle offset X -+ * @param offsetY Particle offset Y -+ * @param offsetZ Particle offset Z -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) { -+ this.offsetX = offsetX; -+ this.offsetY = offsetY; -+ this.offsetZ = offsetZ; -+ return this; -+ } -+ -+ /** -+ * Gets the Particle extra data. Varies by particle on how this is used -+ * -+ * @return the extra particle data -+ */ -+ public double extra() { -+ return extra; -+ } -+ -+ /** -+ * Sets the particle extra data. Varies by particle on how this is used -+ * -+ * @param extra the extra particle data -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder extra(double extra) { -+ this.extra = extra; -+ return this; -+ } -+ -+ /** -+ * Gets the particle custom data. Varies by particle on how this is used -+ * -+ * @param The Particle data type -+ * @return the ParticleData for this particle -+ */ -+ @Nullable -+ public T data() { -+ //noinspection unchecked -+ return (T) data; -+ } -+ -+ /** -+ * Sets the particle custom data. Varies by particle on how this is used -+ * -+ * @param data The new particle data -+ * @param The Particle data type -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder data(@Nullable T data) { -+ this.data = data; -+ return this; -+ } -+ -+ /** -+ * Sets whether the particle is forcefully shown to the player. If forced, the particle will show -+ * faraway, as far as the player's view distance allows. If false, the particle will show -+ * according to the client's particle settings. -+ * -+ * @param force true to force, false for normal -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder force(boolean force) { -+ this.force = force; -+ return this; -+ } -+ -+ /** -+ * Sets the particle Color. Only valid for REDSTONE. -+ * -+ * @param color the new particle color -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(@Nullable Color color) { -+ return color(color, 1); -+ } -+ -+ /** -+ * Sets the particle Color and size. Only valid for REDSTONE. -+ * -+ * @param color the new particle color -+ * @param size the size of the particle -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(@Nullable Color color, float size) { -+ if (particle != Particle.REDSTONE && color != null) { -+ throw new IllegalStateException("Color may only be set on REDSTONE"); -+ } -+ -+ // We don't officially support reusing these objects, but here we go -+ if (color == null) { -+ if (data instanceof Particle.DustOptions) { -+ return data(null); -+ } else { -+ return this; -+ } -+ } -+ -+ return data(new Particle.DustOptions(color, size)); -+ } -+ -+ /** -+ * Sets the particle Color. -+ * Only valid for REDSTONE. -+ * @param r red color component -+ * @param g green color component -+ * @param b blue color component -+ * @return a reference to this object. -+ */ -+ @NotNull -+ public ParticleBuilder color(int r, int g, int b) { -+ return color(Color.fromRGB(r, g, b)); -+ } -+} -diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java -index b32de827cf8d1780861c271b4215276fdaab7165..1020002ff7127877db2d7e096f2c521751bf13a7 100644 ---- a/src/main/java/org/bukkit/Particle.java -+++ b/src/main/java/org/bukkit/Particle.java -@@ -106,6 +106,17 @@ public enum Particle { - return dataType; - } - -+ // Paper start - Particle API expansion -+ /** -+ * Creates a {@link com.destroystokyo.paper.ParticleBuilder} -+ * -+ * @return a {@link com.destroystokyo.paper.ParticleBuilder} for the particle -+ */ -+ @NotNull -+ public com.destroystokyo.paper.ParticleBuilder builder() { -+ return new com.destroystokyo.paper.ParticleBuilder(this); -+ } -+ // Paper end - /** - * Options which can be applied to redstone dust particles - a particle - * color and size. -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 27bbddac946879149ec43d428417c4707f6a9a8c..fe125ae7bbd7c9dde9db7838169e4819416e148d 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -2592,7 +2592,57 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * @param data the data to use for the particle or null, - * the type of this depends on {@link Particle#getDataType()} - */ -- public void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data); -+ public default void spawnParticle(@NotNull Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); }// Paper start - Expand Particle API -+ /** -+ * Spawns the particle (the number of times specified by count) -+ * at the target location. The position of each particle will be -+ * randomized positively and negatively by the offset parameters -+ * on each axis. -+ * -+ * @param particle the particle to spawn -+ * @param receivers List of players to receive the particles, or null for all in world -+ * @param source Source of the particles to be used in visibility checks, or null if no player source -+ * @param x the position on the x axis to spawn at -+ * @param y the position on the y axis to spawn at -+ * @param z the position on the z axis to spawn at -+ * @param count the number of particles -+ * @param offsetX the maximum random offset on the X axis -+ * @param offsetY the maximum random offset on the Y axis -+ * @param offsetZ the maximum random offset on the Z axis -+ * @param extra the extra data for this particle, depends on the -+ * particle used (normally speed) -+ * @param data the data to use for the particle or null, -+ * the type of this depends on {@link Particle#getDataType()} -+ * @param Type -+ */ -+ public default void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @NotNull Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data) { spawnParticle(particle, receivers, source, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, true); } -+ /** -+ * Spawns the particle (the number of times specified by count) -+ * at the target location. The position of each particle will be -+ * randomized positively and negatively by the offset parameters -+ * on each axis. -+ * -+ * @param particle the particle to spawn -+ * @param receivers List of players to receive the particles, or null for all in world -+ * @param source Source of the particles to be used in visibility checks, or null if no player source -+ * @param x the position on the x axis to spawn at -+ * @param y the position on the y axis to spawn at -+ * @param z the position on the z axis to spawn at -+ * @param count the number of particles -+ * @param offsetX the maximum random offset on the X axis -+ * @param offsetY the maximum random offset on the Y axis -+ * @param offsetZ the maximum random offset on the Z axis -+ * @param extra the extra data for this particle, depends on the -+ * particle used (normally speed) -+ * @param data the data to use for the particle or null, -+ * the type of this depends on {@link Particle#getDataType()} -+ * @param Type -+ * @param force allows the particle to be seen further away from the player -+ * and shows to players using any vanilla client particle settings -+ */ -+ public void spawnParticle(@NotNull Particle particle, @Nullable List receivers, @Nullable Player source, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, @Nullable T data, boolean force); -+ // Paper end -+ - - /** - * Spawns the particle (the number of times specified by count) diff --git a/Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch b/Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 9f3e105c9d17..000000000000 --- a/Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:17:44 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f530a3d9314e17d1da896cac633f6a422258d9a9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EndermanAttackPlayerEvent.java -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an Enderman determines if it should attack a player or not. -+ * Starts off cancelled if the player is wearing a pumpkin head or is not looking -+ * at the Enderman, according to Vanilla rules. -+ * -+ */ -+public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable { -+ @NotNull private final Player player; -+ -+ public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) { -+ super(entity); -+ this.player = player; -+ } -+ -+ /** -+ * The enderman considering attacking -+ * -+ * @return The enderman considering attacking -+ */ -+ @NotNull -+ @Override -+ public Enderman getEntity() { -+ return (Enderman) super.getEntity(); -+ } -+ -+ /** -+ * The player the Enderman is considering attacking -+ * -+ * @return The player the Enderman is considering attacking -+ */ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * -+ * @return If cancelled, the enderman will not attack -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancels if the Enderman will attack this player -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch b/Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch deleted file mode 100644 index 6580fe3c76fd..000000000000 --- a/Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 21:33:35 -0400 -Subject: [PATCH] Close Plugin Class Loaders on Disable - -This should close more memory leaks from /reload and disabling plugins, -by closing the class loader and the jar file. - -diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java -index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..6ab9cd8213cbe35943748dcf42948d5fc048c84c 100644 ---- a/src/main/java/org/bukkit/plugin/PluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/PluginLoader.java -@@ -77,4 +77,18 @@ public interface PluginLoader { - * @param plugin Plugin to disable - */ - public void disablePlugin(@NotNull Plugin plugin); -+ // Paper start - close Classloader on disable -+ /** -+ * Disables the specified plugin -+ *

-+ * Attempting to disable a plugin that is not enabled will have no effect -+ * -+ * @param plugin Plugin to disable -+ * @param closeClassloader if the classloader for the Plugin should be closed -+ */ -+ // provide default to allow other PluginLoader implementations to work -+ default public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { -+ disablePlugin(plugin); -+ } -+ // Paper end - close Classloader on disable - } -diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java -index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..86cc5025ad98f7a752c51713b7cd6a39d5136ecc 100644 ---- a/src/main/java/org/bukkit/plugin/PluginManager.java -+++ b/src/main/java/org/bukkit/plugin/PluginManager.java -@@ -161,6 +161,18 @@ public interface PluginManager { - */ - public void disablePlugin(@NotNull Plugin plugin); - -+ // Paper start - close Classloader on disable -+ /** -+ * Disables the specified plugin -+ *

-+ * Attempting to disable a plugin that is not enabled will have no effect -+ * -+ * @param plugin Plugin to disable -+ * @param closeClassloader if the classloader for the Plugin should be closed -+ */ -+ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader); -+ // Paper end - close Classloader on disable -+ - /** - * Gets a {@link Permission} from its fully qualified name - * -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 8b33d914d29897c0276f9e2e7ce83bd2c316d5e2..a7393d2830b95d7167121b02066a3f357cee6085 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -492,17 +492,28 @@ public final class SimplePluginManager implements PluginManager { - - @Override - public void disablePlugins() { -+ disablePlugins(false); -+ } -+ -+ public void disablePlugins(boolean closeClassloaders) { -+ // Paper end - close Classloader on disable - Plugin[] plugins = getPlugins(); - for (int i = plugins.length - 1; i >= 0; i--) { -- disablePlugin(plugins[i]); -+ disablePlugin(plugins[i], closeClassloaders); // Paper - close Classloader on disable - } - } - - @Override - public void disablePlugin(@NotNull final Plugin plugin) { -+ disablePlugin(plugin, false); -+ } -+ -+ @Override -+ public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { -+ // Paper end - close Classloader on disable - if (plugin.isEnabled()) { - try { -- plugin.getPluginLoader().disablePlugin(plugin); -+ plugin.getPluginLoader().disablePlugin(plugin, closeClassloader); // Paper - close Classloader on disable - } catch (Throwable ex) { - handlePluginException("Error occurred (in the plugin loader) while disabling " - + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper -@@ -557,7 +568,7 @@ public final class SimplePluginManager implements PluginManager { - @Override - public void clearPlugins() { - synchronized (this) { -- disablePlugins(); -+ disablePlugins(true); // Paper - close Classloader on disable - plugins.clear(); - lookupNames.clear(); - dependencyGraph = GraphBuilder.directed().build(); -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 79ac529017aac059d13fe342f279e9c8faeba599..816c2b1797447ab315ceb6eda89d25f27d2bce98 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -322,7 +322,7 @@ public final class JavaPluginLoader implements PluginLoader { - } catch (Throwable ex) { - server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); - // Paper start - Disable plugins that fail to load -- disablePlugin(jPlugin); -+ server.getPluginManager().disablePlugin(jPlugin, true); // Paper - close Classloader on disable - She's dead jim - return; - // Paper end - } -@@ -335,6 +335,12 @@ public final class JavaPluginLoader implements PluginLoader { - - @Override - public void disablePlugin(@NotNull Plugin plugin) { -+ // Paper start - close Classloader on disable -+ disablePlugin(plugin, false); // Retain old behavior unless requested -+ } -+ -+ public void disablePlugin(@NotNull Plugin plugin, boolean closeClassloader) { -+ // Paper end - close Class Loader on disable - Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); - - if (plugin.isEnabled()) { -@@ -367,6 +373,16 @@ public final class JavaPluginLoader implements PluginLoader { - } catch (IOException ex) { - // - } -+ // Paper start - close Class Loader on disable -+ try { -+ if (closeClassloader) { -+ loader.close(); -+ } -+ } catch (IOException e) { -+ server.getLogger().log(Level.WARNING, "Error closing the Plugin Class Loader for " + plugin.getDescription().getFullName()); -+ e.printStackTrace(); -+ } -+ // Paper end - } - } - } diff --git a/Spigot-API-Patches/0100-WitchConsumePotionEvent.patch b/Spigot-API-Patches/0100-WitchConsumePotionEvent.patch deleted file mode 100644 index fab6106411a2..000000000000 --- a/Spigot-API-Patches/0100-WitchConsumePotionEvent.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:26:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fbbace36d69373046a7f3618ed5c1c1318b489b9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchConsumePotionEvent.java -@@ -0,0 +1,70 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Witch; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when a witch consumes the potion in their hand to buff themselves. -+ */ -+public class WitchConsumePotionEvent extends EntityEvent implements Cancellable { -+ @Nullable private ItemStack potion; -+ -+ public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { -+ super(witch); -+ this.potion = potion; -+ } -+ -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return the potion the witch will consume and have the effects applied. -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion to be consumed and applied to the witch. -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ /** -+ * @return Event was cancelled or potion was null -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled || potion == null; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6ef6367b67261c2b653a97322b9703a9409b3499 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+public class WitchThrowPotionEvent extends Event implements Cancellable { -+ public WitchThrowPotionEvent() { -+ } -+ -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0101-WitchThrowPotionEvent.patch b/Spigot-API-Patches/0101-WitchThrowPotionEvent.patch deleted file mode 100644 index a5dfe42f3569..000000000000 --- a/Spigot-API-Patches/0101-WitchThrowPotionEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:39:09 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -index 6ef6367b67261c2b653a97322b9703a9409b3499..688a596aa2b925651a92bf092e1ef4d77a47258c 100644 ---- a/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchThrowPotionEvent.java -@@ -1,29 +1,77 @@ - package com.destroystokyo.paper.event.entity; - -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Witch; - import org.bukkit.event.Cancellable; --import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - --public class WitchThrowPotionEvent extends Event implements Cancellable { -- public WitchThrowPotionEvent() { -+/** -+ * Fired when a witch throws a potion at a player -+ */ -+public class WitchThrowPotionEvent extends EntityEvent implements Cancellable { -+ @NotNull private final LivingEntity target; -+ @Nullable private ItemStack potion; -+ -+ public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) { -+ super(witch); -+ this.target = target; -+ this.potion = potion; - } - -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return The target of the potion -+ */ -+ @NotNull -+ public LivingEntity getTarget() { -+ return target; -+ } -+ -+ /** -+ * @return The potion the witch will throw at a player -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion to be thrown at a player -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } - - private static final HandlerList handlers = new HandlerList(); - -+ @NotNull - public HandlerList getHandlers() { - return handlers; - } - -+ @NotNull - public static HandlerList getHandlerList() { - return handlers; - } - - private boolean cancelled = false; - -+ /** -+ * @return Event was cancelled or potion was null -+ */ - @Override - public boolean isCancelled() { -- return cancelled; -+ return cancelled || potion == null; - } - - @Override diff --git a/Spigot-API-Patches/0104-WitchReadyPotionEvent.patch b/Spigot-API-Patches/0104-WitchReadyPotionEvent.patch deleted file mode 100644 index 572242604930..000000000000 --- a/Spigot-API-Patches/0104-WitchReadyPotionEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:08 -0400 -Subject: [PATCH] WitchReadyPotionEvent - -Control what potion the witch readies to use - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5351b523defa054ba56ae3fb591029283ca7510d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/WitchReadyPotionEvent.java -@@ -0,0 +1,80 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Material; -+import org.bukkit.entity.Witch; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class WitchReadyPotionEvent extends EntityEvent implements Cancellable { -+ private ItemStack potion; -+ -+ public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) { -+ super(witch); -+ this.potion = potion; -+ } -+ -+ /** -+ * Fires thee event, returning the desired potion, or air of cancelled -+ * @param witch the witch whom is readying to use a potion -+ * @param potion the potion to be used -+ * @return The ItemStack to be used -+ */ -+ @Nullable -+ public static ItemStack process(@NotNull Witch witch, @Nullable ItemStack potion) { -+ WitchReadyPotionEvent event = new WitchReadyPotionEvent(witch, potion); -+ if (!event.callEvent() || event.getPotion() == null) { -+ return new ItemStack(Material.AIR); -+ } -+ return event.getPotion(); -+ } -+ -+ @NotNull -+ @Override -+ public Witch getEntity() { -+ return (Witch) super.getEntity(); -+ } -+ -+ /** -+ * @return the potion the witch is readying to use -+ */ -+ @Nullable -+ public ItemStack getPotion() { -+ return potion; -+ } -+ -+ /** -+ * Sets the potion the which is going to hold and use -+ * @param potion The potion -+ */ -+ public void setPotion(@Nullable ItemStack potion) { -+ this.potion = potion != null ? potion.clone() : null; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch b/Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index b00193d7173e..000000000000 --- a/Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:59:50 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 82bd3e6701dbd7df9f0f8c3801c5ae1baba4eec5..f41701e6374ca23eca4bdb092e385053a12eb718 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -636,5 +636,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public String getI18NDisplayName() { - return Bukkit.getServer().getItemFactory().getI18NDisplayName(this); - } -+ -+ public int getMaxItemUseDuration() { -+ if (type == null || type == Material.AIR || !type.isItem()) { -+ return 0; -+ } -+ // Requires access to NMS -+ return ensureServerConversions().getMaxItemUseDuration(); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch b/Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index 0422ec9858a7..000000000000 --- a/Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 13:08:21 +0100 -Subject: [PATCH] Add EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bfc69a43c291fbed91b9d0387e4ef18b0ed1b9de ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTeleportEndGatewayEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.block.EndGateway; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.entity.EntityTeleportEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired any time an entity attempts to teleport in an end gateway -+ */ -+public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent { -+ -+ @NotNull private final EndGateway gateway; -+ -+ public EntityTeleportEndGatewayEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) { -+ super(what, from, to); -+ this.gateway = gateway; -+ } -+ -+ /** -+ * The gateway triggering the teleport -+ * -+ * @return EndGateway used -+ */ -+ @NotNull -+ public EndGateway getGateway() { -+ return gateway; -+ } -+ -+} diff --git a/Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch b/Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch deleted file mode 100644 index a362af6260f8..000000000000 --- a/Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 18 Jun 2018 00:41:46 -0500 -Subject: [PATCH] Add "getNearbyXXX" methods to Location - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index f61bf28afe99f83cdac6490bcc114509698d0aad..4cf22afc3c1f1cc19b6e5350043431215908a612 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -12,6 +12,15 @@ import org.bukkit.util.Vector; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -+// Paper start -+import java.util.Collection; -+import java.util.Collections; -+import java.util.function.Predicate; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+// Paper end -+ - /** - * Represents a 3-dimensional position in a world. - *
-@@ -558,6 +567,248 @@ public class Location implements Cloneable, ConfigurationSerializable { - centerLoc.setZ(getBlockZ() + 0.5); - return centerLoc; - } -+ -+ /** -+ * Returns a list of entities within a bounding box centered around a Location. -+ * -+ * Some implementations may impose artificial restrictions on the size of the search bounding box. -+ * -+ * @param x 1/2 the size of the box along x axis -+ * @param y 1/2 the size of the box along y axis -+ * @param z 1/2 the size of the box along z axis -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntities(double x, double y, double z) { -+ World world = this.getWorld(); -+ if (world == null) { -+ throw new IllegalArgumentException("Location has no world"); -+ } -+ return world.getNearbyEntities(this, x, y, z); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X Radius -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of living entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyLivingEntities(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.LivingEntity.class, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X/Y/Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double radius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param radius X/Y/Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xzRadius X/Z Radius -+ * @param yRadius Y Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets nearby players within the specified radius (bounding box) -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @return the collection of players near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyPlayers(double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(org.bukkit.entity.Player.class, xRadius, yRadius, zRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param radius X/Y/Z radius to search within -+ * @param the entity type -+ * @return the collection of entities of type clazz near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius) { -+ return getNearbyEntitiesByType(clazz, radius, radius, radius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius) { -+ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius) { -+ return getNearbyEntitiesByType(clazz, xRadius, yRadius, zRadius, null); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param radius X/Y/Z radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double radius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, radius, radius, radius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius, with x and x radius matching (bounding box) -+ * @param clazz Type to filter by -+ * @param xzRadius X/Z radius to search within -+ * @param yRadius Y radius to search within -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xzRadius, double yRadius, @Nullable Predicate predicate) { -+ return getNearbyEntitiesByType(clazz, xzRadius, yRadius, xzRadius, predicate); -+ } -+ -+ /** -+ * Gets all nearby entities of the specified type, within the specified radius (bounding box) -+ * @param clazz Type to filter by -+ * @param xRadius X Radius -+ * @param yRadius Y Radius -+ * @param zRadius Z Radius -+ * @param predicate a predicate used to filter results -+ * @param the entity type -+ * @return the collection of entities near location. This will always be a non-null collection. -+ */ -+ @NotNull -+ public Collection getNearbyEntitiesByType(@Nullable Class clazz, double xRadius, double yRadius, double zRadius, @Nullable Predicate predicate) { -+ World world = this.getWorld(); -+ if (world == null) { -+ throw new IllegalArgumentException("Location has no world"); -+ } -+ return world.getNearbyEntitiesByType(clazz, this, xRadius, yRadius, zRadius, predicate); -+ } - // Paper end - @Override - public boolean equals(Object obj) { diff --git a/Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch b/Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index 1620ab68a616..000000000000 --- a/Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:40:39 +0200 -Subject: [PATCH] Add EntityKnockbackByEntityEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9efecabab813f575bb447a356e5e7e952d110f30 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityKnockbackByEntityEvent.java -@@ -0,0 +1,82 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.util.Vector; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an Entity is knocked back by the hit of another Entity. The acceleration -+ * vector can be modified. If this event is cancelled, the entity is not knocked back. -+ * -+ */ -+public class EntityKnockbackByEntityEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final Entity hitBy; -+ private final float knockbackStrength; -+ @NotNull private final Vector acceleration; -+ private boolean cancelled = false; -+ -+ public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) { -+ super(entity); -+ this.hitBy = hitBy; -+ this.knockbackStrength = knockbackStrength; -+ this.acceleration = acceleration; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ /** -+ * @return the entity which was knocked back -+ */ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) super.getEntity(); -+ } -+ -+ /** -+ * @return the original knockback strength. -+ */ -+ public float getKnockbackStrength() { -+ return knockbackStrength; -+ } -+ -+ /** -+ * @return the Entity which hit -+ */ -+ @NotNull -+ public Entity getHitBy() { -+ return hitBy; -+ } -+ -+ /** -+ * @return the acceleration that will be applied -+ */ -+ @NotNull -+ public Vector getAcceleration() { -+ return acceleration; -+ } -+} diff --git a/Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch b/Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 342ef584d55c..000000000000 --- a/Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:19:19 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 879dec59f202ee95043bd7317a672cd59ab3bbbe..8b89c0701dd557bcab0c05c1593354ee704b9fe4 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -12,6 +12,7 @@ import org.bukkit.attribute.Attributable; - import org.bukkit.block.Block; - import org.bukkit.entity.memory.MemoryKey; - import org.bukkit.inventory.EntityEquipment; -+import org.bukkit.inventory.ItemStack; - import org.bukkit.potion.PotionEffect; - import org.bukkit.potion.PotionEffectType; - import org.bukkit.projectiles.ProjectileSource; -@@ -642,5 +643,32 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param delay Delay in ticks - */ - void setShieldBlockingDelay(int delay); -+ -+ /** -+ * Get's the item being actively "used" or consumed. -+ * @return The item. Will be null if no active item. -+ */ -+ @Nullable -+ ItemStack getActiveItem(); -+ -+ /** -+ * Get's remaining time a player needs to keep hands raised with an item to finish using it. -+ * @return Remaining ticks to use the item -+ */ -+ int getItemUseRemainingTime(); -+ -+ /** -+ * Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) -+ * -+ * @return Get how long the players hands have been raised (Charging Bow attack, using a potion, etc) -+ */ -+ int getHandRaisedTime(); -+ -+ /** -+ * Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) -+ * -+ * @return Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) -+ */ -+ boolean isHandRaised(); - // Paper end - } diff --git a/Spigot-API-Patches/0118-Entity-getChunk-API.patch b/Spigot-API-Patches/0118-Entity-getChunk-API.patch deleted file mode 100644 index 8eaf47d2a698..000000000000 --- a/Spigot-API-Patches/0118-Entity-getChunk-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:25:48 -0400 -Subject: [PATCH] Entity#getChunk API - -Get the chunk the entity is currently registered to - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index feb9507a972bf797144a01adeeaac83ec2bd165a..9b8823279524d1c1566176c589aa5794eb8aafbc 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -3,6 +3,7 @@ package org.bukkit.entity; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Nameable; -@@ -626,5 +627,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - * @return True if entity spawned from a mob spawner - */ - boolean fromMobSpawner(); -+ -+ /** -+ * Gets the latest chunk an entity is currently or was in. -+ * -+ * @return The current, or most recent chunk if the entity is invalid (which may load the chunk) -+ */ -+ @NotNull -+ Chunk getChunk(); - // Paper end - } diff --git a/Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch b/Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch deleted file mode 100644 index d768a1860718..000000000000 --- a/Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 1 Dec 2020 14:57:02 +0100 -Subject: [PATCH] Add an asterisk to legacy API plugins - -Not here to name and shame, only so server admins can be aware of which -plugins have and haven't been updated. - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 195b6bb328de92c4d17d1cd14e13578226b1ac3c..d6897f43a0692e031bed8a212d9a637ef548cc60 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -91,5 +91,11 @@ public interface UnsafeValues { - default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); - } -+ -+ boolean isSupportedApiVersion(String apiVersion); -+ -+ static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { -+ return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -index 4de959bbd1270d7d6ea8e5e69521bcca6abe2138..1aa58c59e1e8738bbdc77752885ff3b18b29de42 100644 ---- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java -@@ -52,9 +52,15 @@ public class PluginsCommand extends BukkitCommand { - } - - Plugin plugin = entry.getValue(); -- -+ - pluginList.append(plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED); -- pluginList.append(plugin.getDescription().getName()); -+ // Paper start - Add an asterisk to legacy plugins (so admins are aware) -+ String pluginName = plugin.getDescription().getName(); -+ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { -+ pluginName += "*"; -+ } -+ pluginList.append(pluginName); -+ // Paper end - - if (plugin.getDescription().getProvides().size() > 0) { - pluginList.append(" (").append(String.join(", ", plugin.getDescription().getProvides())).append(")"); -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 816c2b1797447ab315ceb6eda89d25f27d2bce98..f26303315c9c93356f0b04440136855dd54d32b7 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -306,7 +306,14 @@ public final class JavaPluginLoader implements PluginLoader { - Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); - - if (!plugin.isEnabled()) { -- plugin.getLogger().info("Enabling " + plugin.getDescription().getFullName()); -+ // Paper start - Add an asterisk to legacy plugins (so admins are aware) -+ String enableMsg = "Enabling " + plugin.getDescription().getFullName(); -+ if (org.bukkit.UnsafeValues.isLegacyPlugin(plugin)) { -+ enableMsg += "*"; -+ } -+ -+ plugin.getLogger().info(enableMsg); -+ // Paper end - - JavaPlugin jPlugin = (JavaPlugin) plugin; - diff --git a/Spigot-API-Patches/0120-EnderDragon-Events.patch b/Spigot-API-Patches/0120-EnderDragon-Events.patch deleted file mode 100644 index 68ed791382ba..000000000000 --- a/Spigot-API-Patches/0120-EnderDragon-Events.patch +++ /dev/null @@ -1,225 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:05 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..118c7b6772a52c250649af2a9286f483f43da385 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFireballHitEvent.java -@@ -0,0 +1,79 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.AreaEffectCloud; -+import org.bukkit.entity.DragonFireball; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+ -+import java.util.Collection; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud -+ */ -+public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable { -+ @Nullable private final Collection targets; -+ @NotNull private final AreaEffectCloud areaEffectCloud; -+ -+ public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @Nullable Collection targets, @NotNull AreaEffectCloud areaEffectCloud) { -+ super(fireball); -+ this.targets = targets; -+ this.areaEffectCloud = areaEffectCloud; -+ } -+ -+ /** -+ * The fireball involved in this event -+ */ -+ @NotNull -+ @Override -+ public DragonFireball getEntity() { -+ return (DragonFireball) super.getEntity(); -+ } -+ -+ /** -+ * The living entities hit by fireball -+ * -+ * May be null if no entities were hit -+ * -+ * @return the targets -+ */ -+ @Nullable -+ public Collection getTargets() { -+ return targets; -+ } -+ -+ /** -+ * @return The area effect cloud spawned in this collision -+ */ -+ @NotNull -+ public AreaEffectCloud getAreaEffectCloud() { -+ return areaEffectCloud; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1915177f4b8f8013656fbdb41240f6c5c88f95d7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonFlameEvent.java -@@ -0,0 +1,61 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.AreaEffectCloud; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an EnderDragon spawns an AreaEffectCloud by shooting flames -+ */ -+public class EnderDragonFlameEvent extends EntityEvent implements Cancellable { -+ @NotNull private final AreaEffectCloud areaEffectCloud; -+ -+ public EnderDragonFlameEvent(@NotNull EnderDragon enderDragon, @NotNull AreaEffectCloud areaEffectCloud) { -+ super(enderDragon); -+ this.areaEffectCloud = areaEffectCloud; -+ } -+ -+ /** -+ * The enderdragon involved in this event -+ */ -+ @NotNull -+ @Override -+ public EnderDragon getEntity() { -+ return (EnderDragon) super.getEntity(); -+ } -+ -+ /** -+ * @return The area effect cloud spawned in this collision -+ */ -+ @NotNull -+ public AreaEffectCloud getAreaEffectCloud() { -+ return areaEffectCloud; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8414bd805ec68d7b305fbf645c59f8d5b762c9ce ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EnderDragonShootFireballEvent.java -@@ -0,0 +1,61 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.DragonFireball; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when an EnderDragon shoots a fireball -+ */ -+public class EnderDragonShootFireballEvent extends EntityEvent implements Cancellable { -+ @NotNull private final DragonFireball fireball; -+ -+ public EnderDragonShootFireballEvent(@NotNull EnderDragon entity, @NotNull DragonFireball fireball) { -+ super(entity); -+ this.fireball = fireball; -+ } -+ -+ /** -+ * The enderdragon shooting the fireball -+ */ -+ @NotNull -+ @Override -+ public EnderDragon getEntity() { -+ return (EnderDragon) super.getEntity(); -+ } -+ -+ /** -+ * @return The fireball being shot -+ */ -+ @NotNull -+ public DragonFireball getFireball() { -+ return fireball; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch b/Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index 7524daea9282..000000000000 --- a/Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:10:50 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9074b2ede01f76c0560e5318246382163cc91591 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLaunchProjectileEvent.java -@@ -0,0 +1,83 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player shoots a projectile -+ */ -+public class PlayerLaunchProjectileEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Projectile projectile; -+ @NotNull private final ItemStack itemStack; -+ private boolean consumeItem = true; -+ private boolean cancelled; -+ -+ public PlayerLaunchProjectileEvent(@NotNull Player shooter, @NotNull ItemStack itemStack, @NotNull Projectile projectile) { -+ super(shooter); -+ this.itemStack = itemStack; -+ this.projectile = projectile; -+ } -+ -+ /** -+ * Gets the projectile which will be launched by this event -+ * -+ * @return the launched projectile -+ */ -+ @NotNull -+ public Projectile getProjectile() { -+ return projectile; -+ } -+ -+ /** -+ * Get the ItemStack used to fire the projectile -+ * -+ * @return The ItemStack used -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Get whether to consume the ItemStack or not -+ * -+ * @return True to consume -+ */ -+ public boolean shouldConsume() { -+ return consumeItem; -+ } -+ -+ /** -+ * Set whether to consume the ItemStack or not -+ * -+ * @param consumeItem True to consume -+ */ -+ public void setShouldConsume(boolean consumeItem) { -+ this.consumeItem = consumeItem; -+ } -+ -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch b/Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch deleted file mode 100644 index c5d8e5ddf3fc..000000000000 --- a/Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:53 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e9a76a25fa5445905a09dbc2fd5b35bff56d80b3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerElytraBoostEvent.java -@@ -0,0 +1,85 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Firework; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player boosts elytra flight with a firework -+ */ -+public class PlayerElytraBoostEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull private final ItemStack itemStack; -+ @NotNull private Firework firework; -+ private boolean consume = true; -+ -+ public PlayerElytraBoostEvent(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull Firework firework) { -+ super(player); -+ this.itemStack = itemStack; -+ this.firework = firework; -+ } -+ -+ /** -+ * Get the firework itemstack used -+ * -+ * @return ItemStack of firework -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Get the firework entity that was spawned -+ * -+ * @return Firework entity -+ */ -+ @NotNull -+ public Firework getFirework() { -+ return firework; -+ } -+ -+ /** -+ * Get whether to consume the firework or not -+ * -+ * @return True to consume -+ */ -+ public boolean shouldConsume() { -+ return consume; -+ } -+ -+ /** -+ * Set whether to consume the firework or not -+ * -+ * @param consume True to consume -+ */ -+ public void setShouldConsume(boolean consume) { -+ this.consume = consume; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0123-EntityTransformedEvent.patch b/Spigot-API-Patches/0123-EntityTransformedEvent.patch deleted file mode 100644 index c77c4a8ba626..000000000000 --- a/Spigot-API-Patches/0123-EntityTransformedEvent.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anthony MacAllister -Date: Thu, 26 Jul 2018 15:28:53 -0400 -Subject: [PATCH] EntityTransformedEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12194f1fc7f03ca6785904b6187b3dfd03b16461 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java -@@ -0,0 +1,92 @@ -+package com.destroystokyo.paper.event.entity; -+ -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.event.entity.EntityTransformEvent; -+ -+/** -+ * Fired when an entity transforms into another entity -+ *

-+ * If the event is cancelled, the entity will not transform -+ * @deprecated Bukkit has added {@link EntityTransformEvent}, you should start using that -+ */ -+@Deprecated -+public class EntityTransformedEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final Entity transformed; -+ private final TransformedReason reason; -+ -+ public EntityTransformedEvent(Entity entity, Entity transformed, TransformedReason reason) { -+ super(entity); -+ this.transformed = transformed; -+ this.reason = reason; -+ } -+ -+ /** -+ * The entity after it has transformed -+ * -+ * @return Transformed entity -+ * @deprecated see {@link EntityTransformEvent#getTransformedEntity()} -+ */ -+ @Deprecated -+ public Entity getTransformed() { -+ return transformed; -+ } -+ -+ /** -+ * @return The reason for the transformation -+ * @deprecated see {@link EntityTransformEvent#getTransformReason()} -+ */ -+ @Deprecated -+ public TransformedReason getReason() { -+ return reason; -+ } -+ -+ -+ @Override -+ public HandlerList getHandlers(){ -+ return handlers; -+ } -+ -+ public static HandlerList getHandlerList(){ -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled(){ -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel){ -+ cancelled = cancel; -+ } -+ -+ public enum TransformedReason { -+ /** -+ * When a zombie drowns -+ */ -+ DROWNED, -+ /** -+ * When a zombie villager is cured -+ */ -+ CURED, -+ /** -+ * When a villager turns to a zombie villager -+ */ -+ INFECTED, -+ /** -+ * When a mooshroom turns to a cow -+ */ -+ SHEARED, -+ /** -+ * When a pig turns to a zombiepigman -+ */ -+ LIGHTNING -+ -+ } -+} diff --git a/Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch b/Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index 30f0bf522767..000000000000 --- a/Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 15 Aug 2018 01:26:03 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index fddc063798edc8084ca695578a47485204a7f3cd..365d3a3c5fc4a47efe56225ef1eb87b5046034f4 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -360,5 +360,21 @@ public interface ArmorStand extends LivingEntity { - * @param move {@code true} if this armour stand can move, {@code false} otherwise - */ - void setCanMove(boolean move); -+ -+ /** -+ * Tests if this armor stand can tick. -+ * -+ *

The default value is defined in {@code paper.yml}.

-+ * -+ * @return {@code true} if this armour stand can tick, {@code false} otherwise -+ */ -+ boolean canTick(); -+ -+ /** -+ * Sets if this armor stand can tick. -+ * -+ * @param tick {@code true} if this armour stand can tick, {@code false} otherwise -+ */ -+ void setCanTick(final boolean tick); - // Paper end - } diff --git a/Spigot-API-Patches/0125-SkeletonHorse-Additions.patch b/Spigot-API-Patches/0125-SkeletonHorse-Additions.patch deleted file mode 100644 index 8d4dd478ab17..000000000000 --- a/Spigot-API-Patches/0125-SkeletonHorse-Additions.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:17 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9ce2948dfaa56d0adf53fe9b6117a90d7773b771 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SkeletonHorseTrapEvent.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import com.google.common.collect.ImmutableList; -+import org.bukkit.entity.HumanEntity; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.List; -+ -+/** -+ * Event called when a player gets close to a skeleton horse and triggers the lightning trap -+ */ -+public class SkeletonHorseTrapEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final List eligibleHumans; -+ -+ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) { -+ this(horse, ImmutableList.of()); -+ } -+ -+ public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse, @NotNull List eligibleHumans) { -+ super(horse); -+ this.eligibleHumans = eligibleHumans; -+ } -+ -+ @NotNull -+ @Override -+ public SkeletonHorse getEntity() { -+ return (SkeletonHorse) super.getEntity(); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ public List getEligibleHumans() { -+ return eligibleHumans; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ -diff --git a/src/main/java/org/bukkit/entity/SkeletonHorse.java b/src/main/java/org/bukkit/entity/SkeletonHorse.java -index b2c6b6a8689f6bd6ce784bbe6f571f756dd700c1..ba9983463263f77db3d3487bc12f01db4508a32b 100644 ---- a/src/main/java/org/bukkit/entity/SkeletonHorse.java -+++ b/src/main/java/org/bukkit/entity/SkeletonHorse.java -@@ -3,4 +3,12 @@ package org.bukkit.entity; - /** - * Represents a SkeletonHorse - variant of {@link AbstractHorse}. - */ --public interface SkeletonHorse extends AbstractHorse { } -+public interface SkeletonHorse extends AbstractHorse { -+ // Paper start -+ int getTrapTime(); -+ -+ boolean isTrap(); -+ -+ void setTrap(boolean trap); -+ // Paper end -+} diff --git a/Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch b/Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch deleted file mode 100644 index 271041f25607..000000000000 --- a/Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 25 Jul 2018 01:36:07 -0400 -Subject: [PATCH] Expand Location Manipulation API - -Adds set(x, y, z), add(base, x, y, z), subtract(base, x, y, z); - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index af2ee43f2c5133668c18710f526a107d94a5d898..369ce9ff6c8bb97a64a8e229115564412e6e7654 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -546,6 +546,54 @@ public class Location implements Cloneable, ConfigurationSerializable { - public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - - // Paper start -+ -+ /** -+ * Sets the position of this Location and returns itself -+ * -+ * This mutates this object, clone first. -+ * @param x X coordinate -+ * @param y Y coordinate -+ * @param z Z coordinate -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location set(double x, double y, double z) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ return this; -+ } -+ -+ /** -+ * Takes the x/y/z from base and adds the specified x/y/z to it and returns self -+ * -+ * This mutates this object, clone first. -+ * @param base The base coordinate to modify -+ * @param x X coordinate to add to base -+ * @param y Y coordinate to add to base -+ * @param z Z coordinate to add to base -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location add(@NotNull Location base, double x, double y, double z) { -+ return this.set(base.x + x, base.y + y, base.z + z); -+ } -+ -+ /** -+ * Takes the x/y/z from base and subtracts the specified x/y/z to it and returns self -+ * -+ * This mutates this object, clone first. -+ * @param base The base coordinate to modify -+ * @param x X coordinate to subtract from base -+ * @param y Y coordinate to subtract from base -+ * @param z Z coordinate to subtract from base -+ * @return self (not cloned) -+ */ -+ @NotNull -+ public Location subtract(@NotNull Location base, double x, double y, double z) { -+ return this.set(base.x - x, base.y - y, base.z - z); -+ } -+ - /** - * @return A new location where X/Y/Z are on the Block location (integer value of X/Y/Z) - */ diff --git a/Spigot-API-Patches/0127-Expand-ArmorStand-API.patch b/Spigot-API-Patches/0127-Expand-ArmorStand-API.patch deleted file mode 100644 index 036951f69dfc..000000000000 --- a/Spigot-API-Patches/0127-Expand-ArmorStand-API.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:22:44 -0400 -Subject: [PATCH] Expand ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java -index 365d3a3c5fc4a47efe56225ef1eb87b5046034f4..8ca6c9eba926f436203af211c6e274a59ddb15e8 100644 ---- a/src/main/java/org/bukkit/entity/ArmorStand.java -+++ b/src/main/java/org/bukkit/entity/ArmorStand.java -@@ -13,7 +13,7 @@ public interface ArmorStand extends LivingEntity { - * Returns the item the armor stand is currently holding. - * - * @return the held item -- * @deprecated prefer {@link EntityEquipment#getItemInHand()} -+ * @deprecated prefer {@link ArmorStand#getItem(EquipmentSlot)} // Paper - * @see #getEquipment() - */ - @NotNull -@@ -25,7 +25,7 @@ public interface ArmorStand extends LivingEntity { - * - * @param item the item to hold - * @deprecated prefer -- * {@link EntityEquipment#setItemInHand(org.bukkit.inventory.ItemStack)} -+ * {@link ArmorStand#setItem(EquipmentSlot, ItemStack)} // Paper - * @see #getEquipment() - */ - @Deprecated -@@ -376,5 +376,71 @@ public interface ArmorStand extends LivingEntity { - * @param tick {@code true} if this armour stand can tick, {@code false} otherwise - */ - void setCanTick(final boolean tick); -+ -+ /** -+ * Returns the item the armor stand has -+ * equip in the given equipment slot -+ * -+ * @param slot the equipment slot to get -+ * @return the ItemStack in the equipment slot -+ */ -+ @NotNull -+ ItemStack getItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot); -+ -+ /** -+ * Sets the item the armor stand has -+ * equip in the given equipment slot -+ * -+ * @param slot the equipment slot to set -+ * @param item the item to hold -+ */ -+ void setItem(@NotNull final org.bukkit.inventory.EquipmentSlot slot, @Nullable final ItemStack item); -+ -+ /** -+ * Get the list of disabled slots -+ * -+ * @return list of disabled slots -+ */ -+ @NotNull -+ java.util.Set getDisabledSlots(); -+ -+ /** -+ * Set the disabled slots -+ * -+ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. -+ * -+ * @param slots var-arg array of slots to lock -+ */ -+ void setDisabledSlots(@NotNull org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Disable specific slots, adding them -+ * to the currently disabled slots -+ * -+ * This makes it so a player is unable to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * Note: Once a slot is disabled, the only way to get an item back it to break the armor stand. -+ * -+ * @param slots var-arg array of slots to lock -+ */ -+ void addDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Remove the given slots from the disabled -+ * slots list, enabling them. -+ * -+ * This makes it so a player is able to interact with the Armor Stand to place, remove, or replace an item in the given slot(s) -+ * -+ * @param slots var-arg array of slots to unlock -+ */ -+ void removeDisabledSlots(@NotNull final org.bukkit.inventory.EquipmentSlot... slots); -+ -+ /** -+ * Check if a specific slot is disabled -+ * -+ * @param slot The slot to check -+ * @return {@code true} if the slot is disabled, else {@code false}. -+ */ -+ boolean isSlotDisabled(@NotNull org.bukkit.inventory.EquipmentSlot slot); - // Paper end - } diff --git a/Spigot-API-Patches/0128-AnvilDamageEvent.patch b/Spigot-API-Patches/0128-AnvilDamageEvent.patch deleted file mode 100644 index 7561b6a9dbd9..000000000000 --- a/Spigot-API-Patches/0128-AnvilDamageEvent.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:36:55 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a83c286c1c11af25fc4d16af7a42b95ce90b9dee ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/AnvilDamagedEvent.java -@@ -0,0 +1,148 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.inventory.AnvilInventory; -+import org.bukkit.inventory.InventoryView; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an anvil is damaged from being used -+ */ -+public class AnvilDamagedEvent extends InventoryEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel; -+ private DamageState damageState; -+ -+ public AnvilDamagedEvent(@NotNull InventoryView inventory, @NotNull BlockData blockData) { -+ super(inventory); -+ this.damageState = DamageState.getState(blockData); -+ } -+ -+ @NotNull -+ @Override -+ public AnvilInventory getInventory() { -+ return (AnvilInventory) super.getInventory(); -+ } -+ -+ /** -+ * Gets the new state of damage on the anvil -+ * -+ * @return Damage state -+ */ -+ @NotNull -+ public DamageState getDamageState() { -+ return damageState; -+ } -+ -+ /** -+ * Sets the new state of damage on the anvil -+ * -+ * @param damageState Damage state -+ */ -+ public void setDamageState(@NotNull DamageState damageState) { -+ this.damageState = damageState; -+ } -+ -+ /** -+ * Gets if anvil is breaking on this use -+ * -+ * @return True if breaking -+ */ -+ public boolean isBreaking() { -+ return damageState == DamageState.BROKEN; -+ } -+ -+ /** -+ * Sets if anvil is breaking on this use -+ * -+ * @param breaking True if breaking -+ */ -+ public void setBreaking(boolean breaking) { -+ if (breaking) { -+ damageState = DamageState.BROKEN; -+ } else if (damageState == DamageState.BROKEN) { -+ damageState = DamageState.DAMAGED; -+ } -+ } -+ -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Represents the amount of damage on an anvil block -+ */ -+ public enum DamageState { -+ FULL(Material.ANVIL), -+ CHIPPED(Material.CHIPPED_ANVIL), -+ DAMAGED(Material.DAMAGED_ANVIL), -+ BROKEN(Material.AIR); -+ -+ private Material material; -+ -+ DamageState(@NotNull Material material) { -+ this.material = material; -+ } -+ -+ /** -+ * Get block material of this state -+ * -+ * @return Material -+ */ -+ @NotNull -+ public Material getMaterial() { -+ return material; -+ } -+ -+ /** -+ * Get damaged state by block data -+ * -+ * @param blockData Block data -+ * @return DamageState -+ * @throws IllegalArgumentException If non anvil block data is given -+ */ -+ @NotNull -+ public static DamageState getState(@Nullable BlockData blockData) { -+ return blockData == null ? BROKEN : getState(blockData.getMaterial()); -+ } -+ -+ /** -+ * Get damaged state by block material -+ * -+ * @param material Block material -+ * @return DamageState -+ * @throws IllegalArgumentException If non anvil material is given -+ */ -+ @NotNull -+ public static DamageState getState(@Nullable Material material) { -+ if (material == null) { -+ return BROKEN; -+ } -+ for (DamageState state : values()) { -+ if (state.material == material) { -+ return state; -+ } -+ } -+ throw new IllegalArgumentException("Material not an anvil"); -+ } -+ } -+} diff --git a/Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch b/Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch deleted file mode 100644 index 2725c79f2e20..000000000000 --- a/Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 00:32:05 -0400 -Subject: [PATCH] Remove deadlock risk in firing async events - -The PluginManager incorrectly used synchronization on firing any event -that was marked as synchronous. - -This synchronized did not even protect any concurrency risk as -handlers were already thread safe in terms of mutations during event -dispatch. - -The way it was used, has commonly led to deadlocks on the server, -which results in a hard crash. - -This change removes the synchronize and adds some protection around enable/disable - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 9b8823279524d1c1566176c589aa5794eb8aafbc..707638c327077a74c777a603b9f2392f46b51c0c 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - -- /** -+ /* - * Gets the entity's current position - * - * @return a new copy of Location containing the position of this entity -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a7393d2830b95d7167121b02066a3f357cee6085..a1a805004941d67abb0b9aa1721e0370c45b5289 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -462,7 +462,7 @@ public final class SimplePluginManager implements PluginManager { - * @return true if the plugin is enabled, otherwise false - */ - @Override -- public boolean isPluginEnabled(@Nullable Plugin plugin) { -+ public synchronized boolean isPluginEnabled(@Nullable Plugin plugin) { // Paper - synchronize - if ((plugin != null) && (plugins.contains(plugin))) { - return plugin.isEnabled(); - } else { -@@ -471,7 +471,7 @@ public final class SimplePluginManager implements PluginManager { - } - - @Override -- public void enablePlugin(@NotNull final Plugin plugin) { -+ public synchronized void enablePlugin(@NotNull final Plugin plugin) { // Paper - synchronize - if (!plugin.isEnabled()) { - List pluginCommands = PluginCommandYamlParser.parse(plugin); - -@@ -509,7 +509,7 @@ public final class SimplePluginManager implements PluginManager { - } - - @Override -- public void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { -+ public synchronized void disablePlugin(@NotNull final Plugin plugin, boolean closeClassloader) { // Paper - synchronize - // Paper end - close Classloader on disable - if (plugin.isEnabled()) { - try { -@@ -579,6 +579,7 @@ public final class SimplePluginManager implements PluginManager { - defaultPerms.get(false).clear(); - } - } -+ private void fireEvent(Event event) { callEvent(event); } // Paper - support old method incase plugin uses reflection - - /** - * Calls an event with the given details. -@@ -587,23 +588,13 @@ public final class SimplePluginManager implements PluginManager { - */ - @Override - public void callEvent(@NotNull Event event) { -- if (event.isAsynchronous()) { -- if (Thread.holdsLock(this)) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); -- } -- if (server.isPrimaryThread()) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from primary server thread."); -- } -- } else { -- if (!server.isPrimaryThread()) { -- throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from another thread."); -- } -+ // Paper - replace callEvent by merging to below method -+ if (event.isAsynchronous() && server.isPrimaryThread()) { -+ throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); -+ } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { -+ throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); - } - -- fireEvent(event); -- } -- -- private void fireEvent(@NotNull Event event) { - HandlerList handlers = event.getHandlers(); - RegisteredListener[] listeners = handlers.getRegisteredListeners(); - -diff --git a/src/test/java/org/bukkit/plugin/PluginManagerTest.java b/src/test/java/org/bukkit/plugin/PluginManagerTest.java -index f188cd4f3b07027c30d41f1162db77a506b7b6bb..1941c9f49e9514c1236c5f4ea9f7af47f7be85c5 100644 ---- a/src/test/java/org/bukkit/plugin/PluginManagerTest.java -+++ b/src/test/java/org/bukkit/plugin/PluginManagerTest.java -@@ -17,7 +17,7 @@ public class PluginManagerTest { - private static final PluginManager pm = TestServer.getInstance().getPluginManager(); - - private final MutableObject store = new MutableObject(); -- -+/* // Paper start - remove unneeded test - @Test - public void testAsyncSameThread() { - final Event event = new TestEvent(true); -@@ -28,14 +28,14 @@ public class PluginManagerTest { - return; - } - throw new IllegalStateException("No exception thrown"); -- } -+ }*/ // Paper end - - @Test - public void testSyncSameThread() { - final Event event = new TestEvent(false); - pm.callEvent(event); - } -- -+/* // Paper start - remove unneeded test - @Test - public void testAsyncLocked() throws InterruptedException { - final Event event = new TestEvent(true); -@@ -129,7 +129,7 @@ public class PluginManagerTest { - if (store.value == null) { - throw new IllegalStateException("No exception thrown"); - } -- } -+ } */ // Paper - - @Test - public void testRemovePermissionByNameLower() { diff --git a/Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch b/Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch deleted file mode 100644 index 85c5c370f32f..000000000000 --- a/Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:20 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -index 7f225baa9fd3ff6f4f950ae70f9500141c674f66..25bd8153ef2ab7ab1052cf756bb599f1095732e7 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - -@@ -22,6 +23,16 @@ public class PlayerBucketEmptyEvent extends PlayerBucketEvent { - public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { - super(who, block, blockClicked, blockFace, bucket, itemInHand); - } -+ // Paper start - add EquipmentSlot -+ @Deprecated -+ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ public PlayerBucketEmptyEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ // Paper end - - @NotNull - @Override -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -index 0e4fa04ea73baaf2f9ad86725d379b569d7d6381..1e0f7ee7d198c08ce421ce105be42c4d01dc924f 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.Cancellable; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -@@ -19,6 +20,7 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - private final Block blockClicked; - private final BlockFace blockFace; - private final Material bucket; -+ private final EquipmentSlot hand; // Paper - add EquipmentSlot - - @Deprecated - public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { -@@ -26,12 +28,24 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - } - - public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand) { -+ // Paper start - add EquipmentSlot -+ this(who, block, blockClicked, blockFace, bucket, itemInHand, null); -+ } -+ -+ @Deprecated -+ public PlayerBucketEvent(@NotNull final Player who,@NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { -+ this(who, null, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ public PlayerBucketEvent(@NotNull final Player who, @NotNull final Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @Nullable final EquipmentSlot hand) { -+ // Paper end - super(who); - this.block = block; - this.blockClicked = blockClicked; - this.blockFace = blockFace; - this.itemStack = itemInHand; - this.bucket = bucket; -+ this.hand = hand == null ? player.getInventory().getItemInMainHand().equals(itemInHand) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND : hand; // Paper - add EquipmentSlot - } - - /** -@@ -93,6 +107,18 @@ public abstract class PlayerBucketEvent extends PlayerEvent implements Cancellab - return blockFace; - } - -+ // Paper start -+ /** -+ * The hand used to perform this action. -+ * -+ * @return the hand used -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ // Paper end -+ - @Override - public boolean isCancelled() { - return cancelled; -diff --git a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -index 77c3a6e5c89ffde564d63b98b2d9e36c356d79fd..56f1cc2d773d2c58207ee291bac596692980a731 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java -@@ -5,6 +5,7 @@ import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; - import org.bukkit.entity.Player; - import org.bukkit.event.HandlerList; -+import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; - -@@ -23,6 +24,18 @@ public class PlayerBucketFillEvent extends PlayerBucketEvent { - super(who, block, blockClicked, blockFace, bucket, itemInHand); - } - -+ // Paper start - add EquipmentSlot -+ @Deprecated -+ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ -+ // Paper start - add EquipmentSlot -+ public PlayerBucketFillEvent(@NotNull final Player who, @NotNull Block block, @NotNull final Block blockClicked, @NotNull final BlockFace blockFace, @NotNull final Material bucket, @NotNull final ItemStack itemInHand, @org.jetbrains.annotations.Nullable final EquipmentSlot hand) { -+ super(who, block, blockClicked, blockFace, bucket, itemInHand, hand); -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch b/Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch deleted file mode 100644 index 2bddc56f13d9..000000000000 --- a/Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 15 Jul 2018 22:17:55 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..73dabb82c7fbea3f0cccade0a2944b11a80ede06 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/TNTPrimeEvent.java -@@ -0,0 +1,114 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when TNT block is about to turn into {@link org.bukkit.entity.TNTPrimed} -+ *

-+ * Cancelling it won't turn TNT into {@link org.bukkit.entity.TNTPrimed} and leaves -+ * the TNT block as-is -+ * -+ * @author Mark Vainomaa -+ */ -+public class TNTPrimeEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private PrimeReason reason; -+ @Nullable private Entity primerEntity; -+ -+ public TNTPrimeEvent(@NotNull Block theBlock, @NotNull PrimeReason reason, @Nullable Entity primerEntity) { -+ super(theBlock); -+ this.reason = reason; -+ this.primerEntity = primerEntity; -+ } -+ -+ /** -+ * Gets the TNT prime reason -+ * -+ * @return Prime reason -+ */ -+ @NotNull -+ public PrimeReason getReason() { -+ return this.reason; -+ } -+ -+ /** -+ * Gets the TNT primer {@link Entity}. -+ * -+ * It's null if {@link #getReason()} is {@link PrimeReason#REDSTONE} or {@link PrimeReason#FIRE}. -+ * It's not null if {@link #getReason()} is {@link PrimeReason#ITEM} or {@link PrimeReason#PROJECTILE} -+ * It might be null if {@link #getReason()} is {@link PrimeReason#EXPLOSION} -+ * -+ * @return The {@link Entity} who primed the TNT -+ */ -+ @Nullable -+ public Entity getPrimerEntity() { -+ return this.primerEntity; -+ } -+ -+ /** -+ * Gets whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ * -+ * @return Whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets whether to cancel spawning {@link org.bukkit.entity.TNTPrimed} or not -+ * -+ * @param cancel whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @Nullable -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @Nullable -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ public enum PrimeReason { -+ /** -+ * When TNT prime was caused by other explosion (chain reaction) -+ */ -+ EXPLOSION, -+ -+ /** -+ * When TNT prime was caused by fire -+ */ -+ FIRE, -+ -+ /** -+ * When {@link org.bukkit.entity.Player} used {@link org.bukkit.Material#FLINT_AND_STEEL} or -+ * {@link org.bukkit.Material#FIRE_CHARGE} on given TNT block -+ */ -+ ITEM, -+ -+ /** -+ * When TNT prime was caused by an {@link Entity} shooting TNT -+ * using a bow with {@link org.bukkit.enchantments.Enchantment#ARROW_FIRE} enchantment -+ */ -+ PROJECTILE, -+ -+ /** -+ * When redstone power triggered the TNT prime -+ */ -+ REDSTONE -+ } -+} diff --git a/Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch b/Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch deleted file mode 100644 index 3616f82f03e8..000000000000 --- a/Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 4 Aug 2018 19:37:35 -0400 -Subject: [PATCH] Provide Chunk Coordinates as a Long API - -Allows you to easily access the chunks X/z as a long, and a method -to look up by the long key too. - -diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java -index beac1439c71fb28f1a3baecf56157237e12ccfd5..fa576096e908f8fbdbef53e1bd91215ac9e73ed6 100644 ---- a/src/main/java/org/bukkit/Chunk.java -+++ b/src/main/java/org/bukkit/Chunk.java -@@ -28,6 +28,32 @@ public interface Chunk extends PersistentDataHolder { - */ - int getZ(); - -+ // Paper start -+ /** -+ * @return The Chunks X and Z coordinates packed into a long -+ */ -+ default long getChunkKey() { -+ return getChunkKey(getX(), getZ()); -+ } -+ -+ /** -+ * @param loc Location to get chunk key -+ * @return Location's chunk coordinates packed into a long -+ */ -+ static long getChunkKey(@NotNull Location loc) { -+ return getChunkKey((int) Math.floor(loc.getX()) >> 4, (int) Math.floor(loc.getZ()) >> 4); -+ } -+ -+ /** -+ * @param x X Coordinate -+ * @param z Z Coordinate -+ * @return Chunk coordinates packed into a long -+ */ -+ static long getChunkKey(int x, int z) { -+ return (long) x & 0xffffffffL | ((long) z & 0xffffffffL) << 32; -+ } -+ // Paper end -+ - /** - * Gets the world containing this chunk - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 9c4f2d9e1a4011e3a9860d913e1a718030696bed..e372b3d43960ac7df58985609ef729c68fca0533 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -207,6 +207,22 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Chunk getChunkAt(@NotNull Block block); - -+ // Paper start -+ /** -+ * Gets the chunk at the specified chunk key, which is the X and Z packed into a long. -+ * -+ * See {@link Chunk#getChunkKey()} for easy access to the key, or you may calculate it as: -+ * long chunkKey = (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) >> 32; -+ * -+ * @param chunkKey The Chunk Key to look up the chunk by -+ * @return The chunk at the specified key -+ */ -+ @NotNull -+ public default Chunk getChunkAt(long chunkKey) { -+ return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); -+ } -+ // Paper end -+ - /** - * Checks if the specified {@link Chunk} is loaded - * diff --git a/Spigot-API-Patches/0133-Async-Chunks-API.patch b/Spigot-API-Patches/0133-Async-Chunks-API.patch deleted file mode 100644 index 992af6f95bee..000000000000 --- a/Spigot-API-Patches/0133-Async-Chunks-API.patch +++ /dev/null @@ -1,534 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Feb 2016 17:43:33 -0600 -Subject: [PATCH] Async Chunks API - -Adds API's to load or generate chunks asynchronously. - -Also adds utility methods to Entity to teleport asynchronously. - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index e372b3d43960ac7df58985609ef729c68fca0533..3f231c28842f02f80fd3136c36fe99b41726137f 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -221,6 +221,482 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - public default Chunk getChunkAt(long chunkKey) { - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); - } -+ -+ /** -+ * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, -+ * as well as future support -+ * -+ * Used by {@link World#getChunkAtAsync(Location,ChunkLoadCallback)} methods -+ * to request a {@link Chunk} to be loaded, with this callback receiving -+ * the chunk when it is finished. -+ * -+ * This callback will be executed on synchronously on the main thread. -+ * -+ * Timing and order this callback is fired is intentionally not defined and -+ * and subject to change. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ */ -+ @Deprecated -+ public static interface ChunkLoadCallback extends java.util.function.Consumer { -+ public void onLoad(@NotNull Chunk chunk); -+ -+ // backwards compat to old api -+ @Override -+ default void accept(@NotNull Chunk chunk) { -+ onLoad(chunk); -+ } -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(int x, int z, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(x, z, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param loc Location of the chunk -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(loc, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link ChunkLoadCallback} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @deprecated Use either the Future or the Consumer based methods -+ * @param block Block to get the containing chunk from -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ @Deprecated -+ public default void getChunkAtAsync(@NotNull Block block, @NotNull ChunkLoadCallback cb) { -+ getChunkAtAsync(block, true).thenAccept(cb::onLoad).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(int x, int z, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(x, z, true).thenAccept(cb).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param gen Should we generate a chunk if it doesn't exists or not -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(int x, int z, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(x, z, gen).thenAccept(cb).exceptionally((ex) -> { -+ Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Exception in chunk load callback", ex); -+ return null; -+ }); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param loc Location of the chunk -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Location loc, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, cb); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given {@link Location} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param loc Location of the chunk -+ * @param gen Should the chunk generate -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Location loc, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, cb); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param block Block to get the containing chunk from -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Block block, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, cb); -+ } -+ -+ /** -+ * Requests {@link Chunk} to be loaded that contains the given {@link Block} -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The {@link java.util.function.Consumer} will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param block Block to get the containing chunk from -+ * @param gen Should the chunk generate -+ * @param cb Callback to receive the chunk when it is loaded. -+ * will be executed synchronously -+ */ -+ public default void getChunkAtAsync(@NotNull Block block, boolean gen, @NotNull java.util.function.Consumer cb) { -+ getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, cb); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Location loc, boolean gen) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(@NotNull Block block, boolean gen) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x X Coord -+ * @param z Z Coord -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z) { -+ return getChunkAtAsync(x, z, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x Chunk X-coordinate of the chunk - (world coordinate / 16) -+ * @param z Chunk Z-coordinate of the chunk - (world coordinate / 16) -+ * @param gen Should we generate a chunk if it doesn't exists or not -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen) { -+ return getChunkAtAsync(x, z, gen, false); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, true, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param loc Location to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Location loc, boolean gen) { -+ return getChunkAtAsync((int)Math.floor(loc.getX()) >> 4, (int)Math.floor(loc.getZ()) >> 4, gen, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, true, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * @param block Block to load the corresponding chunk from -+ * @param gen Should the chunk generate -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(@NotNull Block block, boolean gen) { -+ return getChunkAtAsync(block.getX() >> 4, block.getZ() >> 4, gen, true); -+ } -+ -+ /** -+ * Requests a {@link Chunk} to be loaded at the given coordinates -+ * -+ * This method makes no guarantee on how fast the chunk will load, -+ * and will return the chunk to the callback at a later time. -+ * -+ * You should use this method if you need a chunk but do not need it -+ * immediately, and you wish to let the server control the speed -+ * of chunk loads, keeping performance in mind. -+ * -+ * The future will always be executed synchronously -+ * on the main Server Thread. -+ * -+ * @param x X Coord -+ * @param z Z Coord -+ * @return Future that will resolve when the chunk is loaded -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture getChunkAtAsyncUrgently(int x, int z) { -+ return getChunkAtAsync(x, z, true, true); -+ } -+ -+ @NotNull -+ java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 707638c327077a74c777a603b9f2392f46b51c0c..c137199ed0537874010f1abf311a9cbee56831ac 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -163,6 +163,33 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - public boolean teleport(@NotNull Entity destination, @NotNull TeleportCause cause); - -+ // Paper start -+ /** -+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. -+ * @param loc Location to teleport to -+ * @return A future that will be completed with the result of the teleport -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc) { -+ return teleportAsync(loc, TeleportCause.PLUGIN); -+ } -+ /** -+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. -+ * @param loc Location to teleport to -+ * @param cause Reason for teleport -+ * @return A future that will be completed with the result of the teleport -+ */ -+ @NotNull -+ public default java.util.concurrent.CompletableFuture teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause) { -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - /** - * Returns a list of entities within a bounding box centered around this - * entity diff --git a/Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch b/Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch deleted file mode 100644 index 6779d66171fb..000000000000 --- a/Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:08:34 -0400 -Subject: [PATCH] Make EnderDragon extend Mob - - -diff --git a/src/main/java/org/bukkit/entity/EnderDragon.java b/src/main/java/org/bukkit/entity/EnderDragon.java -index c14278d2c99deedddfd9c8afdc900760b0331546..92da609fb2bdf7c6396ba868410a40725fda05f0 100644 ---- a/src/main/java/org/bukkit/entity/EnderDragon.java -+++ b/src/main/java/org/bukkit/entity/EnderDragon.java -@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents an Ender Dragon - */ --public interface EnderDragon extends ComplexLivingEntity, Boss { -+public interface EnderDragon extends ComplexLivingEntity, Boss, org.bukkit.entity.Mob { // Paper - add Mob - - /** - * Represents a phase or action that an Ender Dragon can perform. diff --git a/Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index cbe8cd6f6966..000000000000 --- a/Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:04:58 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java -index fa576096e908f8fbdbef53e1bd91215ac9e73ed6..98263d896f316983609432c45b85401a2692432d 100644 ---- a/src/main/java/org/bukkit/Chunk.java -+++ b/src/main/java/org/bukkit/Chunk.java -@@ -1,6 +1,8 @@ - package org.bukkit; - - import java.util.Collection; -+import java.util.function.Predicate; -+ - import org.bukkit.block.Block; - import org.bukkit.block.BlockState; - import org.bukkit.block.data.BlockData; -@@ -103,13 +105,36 @@ public interface Chunk extends PersistentDataHolder { - @NotNull - Entity[] getEntities(); - -+ // Paper start - /** - * Get a list of all tile entities in the chunk. - * - * @return The tile entities. - */ - @NotNull -- BlockState[] getTileEntities(); -+ default BlockState[] getTileEntities() { -+ return getTileEntities(true); -+ } -+ -+ /** -+ * Get a list of all tile entities in the chunk. -+ * -+ * @param useSnapshot Take snapshots or direct references -+ * @return The tile entities. -+ */ -+ @NotNull -+ BlockState[] getTileEntities(boolean useSnapshot); -+ -+ /** -+ * Get a list of all tile entities that match a given predicate in the chunk. -+ * -+ * @param blockPredicate The predicate of blocks to return tile entities for -+ * @param useSnapshot Take snapshots or direct references -+ * @return The tile entities. -+ */ -+ @NotNull -+ Collection getTileEntities(@NotNull Predicate blockPredicate, boolean useSnapshot); -+ // Paper end - - /** - * Checks if the chunk is loaded. diff --git a/Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch deleted file mode 100644 index 536fdc2d0623..000000000000 --- a/Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:19:37 -0400 -Subject: [PATCH] Don't use snapshots for Timings Tile Entity reports - - -diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java -index ddaed81275fcc12d1671b668697acf318e96888b..203cda0f9a4dea4f28a21ea9ee8db7a7369842e3 100644 ---- a/src/main/java/co/aikar/timings/TimingHistory.java -+++ b/src/main/java/co/aikar/timings/TimingHistory.java -@@ -119,7 +119,7 @@ public class TimingHistory { - data.entityCounts.get(entity.getType()).increment(); - } - -- for (BlockState tileEntity : chunk.getTileEntities()) { -+ for (BlockState tileEntity : chunk.getTileEntities(false)) { - if (tileEntity == null) { - Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); - continue; diff --git a/Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch deleted file mode 100644 index 568d6bcd6e6f..000000000000 --- a/Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Aug 2018 21:42:10 -0700 -Subject: [PATCH] Allow Blocks to be accessed via a long key - -The key can be retrieved via methods Location#toBlockKey() and -Block#getBlockKey() - -World provides lookup for blocks by long key via method World#getBlockAtKey(long) - -The formatting for the key is as follows: - -10 bit y|27 bit z|27 bit x - -The y value is considered unsigned while z and x are considered two's complement - -Y range: [0, 1023] -X, Z range: [-67 108 864, 67 108 863] - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 369ce9ff6c8bb97a64a8e229115564412e6e7654..e700875beb76dadd55b585aca748338def286908 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable; - - // Paper start - import java.util.Collection; --import java.util.Collections; - import java.util.function.Predicate; - import org.bukkit.entity.Entity; - import org.bukkit.entity.LivingEntity; -@@ -605,6 +604,17 @@ public class Location implements Cloneable, ConfigurationSerializable { - blockLoc.setZ(getBlockZ()); - return blockLoc; - } -+ -+ // Paper Start -+ /** -+ * @return The block key for this location's block location. -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ public long toBlockKey() { -+ return Block.getBlockKey(getBlockX(), getBlockY(), getBlockZ()); -+ } -+ // Paper End -+ - /** - * @return A new location where X/Y/Z are the center of the block - */ -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 3f231c28842f02f80fd3136c36fe99b41726137f..d8674c773d61517f79d0fe77276392e47fd3e1e1 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -90,6 +90,38 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Block getBlockAt(@NotNull Location location); - -+ // Paper start -+ /** -+ * Gets the {@link Block} at the given block key -+ * -+ * @param key The block key. See {@link Block#getBlockKey()} -+ * @return Block at the key -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ @NotNull -+ public default Block getBlockAtKey(long key) { -+ int x = Block.getBlockKeyX(key); -+ int y = Block.getBlockKeyY(key); -+ int z = Block.getBlockKeyZ(key); -+ return getBlockAt(x, y, z); -+ } -+ -+ /** -+ * Gets the {@link Location} at the given block key -+ * -+ * @param key The block key. See {@link Location#toBlockKey()} -+ * @return Location at the key -+ * @see Block#getBlockKey(int, int, int) -+ */ -+ @NotNull -+ public default Location getLocationAtKey(long key) { -+ int x = Block.getBlockKeyX(key); -+ int y = Block.getBlockKeyY(key); -+ int z = Block.getBlockKeyZ(key); -+ return new Location(this, x, y, z); -+ } -+ // Paper end -+ - /** - * Gets the highest non-empty (impassable) coordinate at the given - * coordinates. -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e89c8079625525667f496c06207da655fe43d749..d6f74dbcfeb153d4b17be2827e2989f2d8160d21 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -153,6 +153,72 @@ public interface Block extends Metadatable { - */ - int getZ(); - -+ // Paper Start -+ /** -+ * Returns this block's coordinates packed into a long value. -+ * Computed via: {@code Block.getBlockKey(this.getX(), this.getY(), this.getZ())} -+ * @see Block#getBlockKey(int, int, int) -+ * @return This block's x, y, and z coordinates packed into a long value -+ */ -+ public default long getBlockKey() { -+ return Block.getBlockKey(this.getX(), this.getY(), this.getZ()); -+ } -+ -+ /** -+ * Returns the specified block coordinates packed into a long value -+ *

-+ * The return value can be computed as follows: -+ *
-+ * {@code long value = ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54);} -+ *

-+ * -+ *

-+ * And may be unpacked as follows: -+ *
-+ * {@code int x = (int) ((packed << 37) >> 37);} -+ *
-+ * {@code int y = (int) (packed >>> 54);} -+ *
-+ * {@code int z = (int) ((packed << 10) >> 37);} -+ *

-+ * -+ * @return This block's x, y, and z coordinates packed into a long value -+ */ -+ public static long getBlockKey(int x, int y, int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ /** -+ * Returns the x component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The x component from the packed value. -+ */ -+ public static int getBlockKeyX(long packed) { -+ return (int) ((packed << 37) >> 37); -+ } -+ -+ /** -+ * Returns the y component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The y component from the packed value. -+ */ -+ public static int getBlockKeyY(long packed) { -+ return (int) (packed >>> 54); -+ } -+ -+ /** -+ * Returns the z component from the packed value. -+ * @param packed The packed value, as computed by {@link Block#getBlockKey(int, int, int)} -+ * @see Block#getBlockKey(int, int, int) -+ * @return The z component from the packed value. -+ */ -+ public static int getBlockKeyZ(long packed) { -+ return (int) ((packed << 10) >> 37); -+ } -+ // Paper End -+ - /** - * Gets the Location of the block - * diff --git a/Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch b/Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch deleted file mode 100644 index 8d27bd1b1477..000000000000 --- a/Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:27 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2638bbd3e1392b3d8640be58163f6eb2789dee4a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeChangeDirectionEvent.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to change it's facing direction. -+ *

-+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to change direction. -+ */ -+public class SlimeChangeDirectionEvent extends SlimePathfindEvent implements Cancellable { -+ private float yaw; -+ -+ public SlimeChangeDirectionEvent(@NotNull Slime slime, float yaw) { -+ super(slime); -+ this.yaw = yaw; -+ } -+ -+ /** -+ * Get the new chosen yaw -+ * -+ * @return Chosen yaw -+ */ -+ public float getNewYaw() { -+ return yaw; -+ } -+ -+ /** -+ * Set the new chosen yaw -+ * -+ * @param yaw Chosen yaw -+ */ -+ public void setNewYaw(float yaw) { -+ this.yaw = yaw; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..14b67da109321ae6521eab2ac6f6945f05d02db5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimePathfindEvent.java -@@ -0,0 +1,53 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start pathfinding. -+ *

-+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimePathfindEvent extends EntityEvent implements Cancellable { -+ public SlimePathfindEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+ -+ /** -+ * The Slime that is pathfinding. -+ * -+ * @return The Slime that is pathfinding. -+ */ -+ @NotNull -+ public Slime getEntity() { -+ return (Slime) entity; -+ } -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ private boolean cancelled = false; -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c8dd49d11da5a90a1bac965a75f2b65fd825f3f7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeSwimEvent.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start jumping while swimming in water/lava. -+ *

-+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start jumping. -+ */ -+public class SlimeSwimEvent extends SlimeWanderEvent implements Cancellable { -+ public SlimeSwimEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e9ba32799ed838779e49cd4c5011b7515b3363cb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeTargetLivingEntityEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to change direction to target a LivingEntity. -+ *

-+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimeTargetLivingEntityEvent extends SlimePathfindEvent implements Cancellable { -+ @NotNull private final LivingEntity target; -+ -+ public SlimeTargetLivingEntityEvent(@NotNull Slime slime, @NotNull LivingEntity target) { -+ super(slime); -+ this.target = target; -+ } -+ -+ /** -+ * Get the targeted entity -+ * -+ * @return Targeted entity -+ */ -+ @NotNull -+ public LivingEntity getTarget() { -+ return target; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4683a7237d2ed527fc85b9b4e5b2eaaf5ae3d797 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/SlimeWanderEvent.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Slime; -+import org.bukkit.event.Cancellable; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Slime decides to start wandering. -+ *

-+ * This event does not fire for the entity's actual movement. Only when it -+ * is choosing to start moving. -+ */ -+public class SlimeWanderEvent extends SlimePathfindEvent implements Cancellable { -+ public SlimeWanderEvent(@NotNull Slime slime) { -+ super(slime); -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Slime.java b/src/main/java/org/bukkit/entity/Slime.java -index 1119e26e270bb45f517955b19d95a9ec3d113634..c4791f95d788d3a9e013dc89d8e64103ad8480a1 100644 ---- a/src/main/java/org/bukkit/entity/Slime.java -+++ b/src/main/java/org/bukkit/entity/Slime.java -@@ -14,4 +14,20 @@ public interface Slime extends Mob { - * @param sz The new size of the slime. - */ - public void setSize(int sz); -+ -+ // Paper start -+ /** -+ * Get whether this slime can randomly wander/jump around on its own -+ * -+ * @return true if can wander -+ */ -+ public boolean canWander(); -+ -+ /** -+ * Set whether this slime can randomly wander/jump around on its own -+ * -+ * @param canWander true if can wander -+ */ -+ public void setWander(boolean canWander); -+ // Paper end - } diff --git a/Spigot-API-Patches/0139-isChunkGenerated-API.patch b/Spigot-API-Patches/0139-isChunkGenerated-API.patch deleted file mode 100644 index a26301e9c38f..000000000000 --- a/Spigot-API-Patches/0139-isChunkGenerated-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: cswhite2000 <18whitechristop@gmail.com> -Date: Tue, 21 Aug 2018 19:39:46 -0700 -Subject: [PATCH] isChunkGenerated API - - -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index e700875beb76dadd55b585aca748338def286908..9c91c49ed7302c12fcb1d8e9bc58712efc199954 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -3,6 +3,7 @@ package org.bukkit; - import com.google.common.base.Preconditions; - import java.lang.ref.Reference; - import java.lang.ref.WeakReference; -+import com.google.common.base.Preconditions; // Paper - import java.util.HashMap; - import java.util.Map; - import org.bukkit.block.Block; -@@ -545,6 +546,16 @@ public class Location implements Cloneable, ConfigurationSerializable { - public boolean isChunkLoaded() { return this.getWorld().isChunkLoaded(locToBlock(x) >> 4, locToBlock(z) >> 4); } // Paper - - // Paper start -+ /** -+ * Checks if a {@link Chunk} has been generated at this location. -+ * -+ * @return true if a chunk has been generated at this location -+ */ -+ public boolean isGenerated() { -+ World world = this.getWorld(); -+ Preconditions.checkNotNull(world, "Location has no world!"); -+ return world.isChunkGenerated(locToBlock(x) >> 4, locToBlock(z) >> 4); -+ } - - /** - * Sets the position of this Location and returns itself -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index d8674c773d61517f79d0fe77276392e47fd3e1e1..cf831f96efa302f789cf26a384a091df51215a76 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -254,6 +254,17 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); - } - -+ /** -+ * Checks if a {@link Chunk} has been generated at the specified chunk key, -+ * which is the X and Z packed into a long. -+ * -+ * @param chunkKey The Chunk Key to look up the chunk by -+ * @return true if the chunk has been generated, otherwise false -+ */ -+ public default boolean isChunkGenerated(long chunkKey) { -+ return isChunkGenerated((int) chunkKey, (int) (chunkKey >> 32)); -+ } -+ - /** - * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, - * as well as future support diff --git a/Spigot-API-Patches/0140-Add-More-Creeper-API.patch b/Spigot-API-Patches/0140-Add-More-Creeper-API.patch deleted file mode 100644 index b45e2fbeba53..000000000000 --- a/Spigot-API-Patches/0140-Add-More-Creeper-API.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:16 -0500 -Subject: [PATCH] Add More Creeper API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ff10251b6ded533b08048ec533525176eff03707 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/CreeperIgniteEvent.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Creeper; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a Creeper is ignite flag is changed (armed/disarmed to explode). -+ */ -+public class CreeperIgniteEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ private boolean ignited; -+ -+ public CreeperIgniteEvent(@NotNull Creeper creeper, boolean ignited) { -+ super(creeper); -+ this.ignited = ignited; -+ } -+ -+ @NotNull -+ @Override -+ public Creeper getEntity() { -+ return (Creeper) entity; -+ } -+ -+ public boolean isIgnited() { -+ return ignited; -+ } -+ -+ public void setIgnited(boolean ignited) { -+ this.ignited = ignited; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Creeper.java b/src/main/java/org/bukkit/entity/Creeper.java -index 5793193d93d76a062fd0431475c269c4978ec993..e144f618702122bf28ebedc5cb8ce0f6ef27c107 100644 ---- a/src/main/java/org/bukkit/entity/Creeper.java -+++ b/src/main/java/org/bukkit/entity/Creeper.java -@@ -87,4 +87,20 @@ public interface Creeper extends Monster { - * griefing gamerule. - */ - public void ignite(); -+ // Paper start -+ -+ /** -+ * Set whether creeper is ignited or not (armed to explode) -+ * -+ * @param ignited New ignited state -+ */ -+ public void setIgnited(boolean ignited); -+ -+ /** -+ * Check if creeper is ignited or not (armed to explode) -+ * -+ * @return Ignited state -+ */ -+ public boolean isIgnited(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch b/Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index 5ffdc818cbcc..000000000000 --- a/Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:42 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9022f697ab244df43074e48c9150f39d44217531 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PhantomPreSpawnEvent.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+ -+/** -+ * Called when a phantom is spawned for an exhausted player -+ */ -+public class PhantomPreSpawnEvent extends PreCreatureSpawnEvent { -+ @NotNull private final Entity entity; -+ -+ public PhantomPreSpawnEvent(@NotNull Location location, @NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ super(location, EntityType.PHANTOM, reason); -+ this.entity = entity; -+ } -+ -+ /** -+ * Get the entity this phantom is spawning for -+ * -+ * @return Entity -+ */ -+ @Nullable -+ public Entity getSpawningEntity() { -+ return entity; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java -index 1a1044edc57078f96c4a95c994d0865da382c152..ed4d417c2deefb78807cb61b01df5afcd334d754 100644 ---- a/src/main/java/org/bukkit/entity/Phantom.java -+++ b/src/main/java/org/bukkit/entity/Phantom.java -@@ -1,5 +1,8 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ - /** - * Represents a phantom. - */ -@@ -14,4 +17,14 @@ public interface Phantom extends Flying { - * @param sz The new size of the phantom. - */ - public void setSize(int sz); -+ -+ // Paper start -+ /** -+ * Get the UUID of the entity that caused this phantom to spawn -+ * -+ * @return UUID -+ */ -+ @Nullable -+ public java.util.UUID getSpawningEntity(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch b/Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch deleted file mode 100644 index 965de7c24a91..000000000000 --- a/Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sotr -Date: Thu, 23 Aug 2018 16:14:25 +0800 -Subject: [PATCH] Add source block to BlockPhysicsEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -index e3a5f5824ed882058f5bac5003f66ce79733a868..c382f9fc2b8c5b959df7071007110dab737e400e 100644 ---- a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java -@@ -32,6 +32,13 @@ public class BlockPhysicsEvent extends BlockEvent implements Cancellable { - private final Block sourceBlock; - private boolean cancel = false; - -+ // Paper start - Legacy constructor, use #BlockPhysicsEvent(Block, BlockData, Block) -+ @Deprecated -+ public BlockPhysicsEvent(final Block block, final BlockData changed, final int sourceX, final int sourceY, final int sourceZ) { -+ this(block, changed, block.getWorld().getBlockAt(sourceX, sourceY, sourceZ)); -+ } -+ // Paper end -+ - public BlockPhysicsEvent(@NotNull final Block block, @NotNull final BlockData changed) { - this(block, changed, block); - } diff --git a/Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch b/Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch deleted file mode 100644 index 4d6f2e9e5744..000000000000 --- a/Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 28 Aug 2018 23:04:06 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -125,6 +125,34 @@ public interface Inventory extends Iterable { - @NotNull - public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Searches all possible inventory slots in order to remove the given ItemStacks. -+ *

-+ * Similar to {@link Inventory#removeItem(ItemStack...)} in behavior, except this -+ * method will check all possible slots in the inventory, rather than just the main -+ * storage contents. -+ *

-+ * It will try to remove 'as much as possible' from the types and amounts -+ * you give as arguments. -+ *

-+ * The returned HashMap contains what it couldn't remove, where the key is -+ * the index of the parameter, and the value is the ItemStack at that -+ * index of the varargs parameter. If all the given ItemStacks are -+ * removed, it will return an empty HashMap. -+ *

-+ * It is known that in some implementations this method will also set the -+ * inputted argument amount to the number of that item not removed from -+ * slots. -+ * -+ * @param items The ItemStacks to remove -+ * @return A HashMap containing items that couldn't be removed. -+ * @throws IllegalArgumentException if items is null -+ */ -+ @NotNull -+ public HashMap removeItemAnySlot(@NotNull ItemStack... items) throws IllegalArgumentException; -+ // Paper end -+ - /** - * Returns all ItemStacks from the inventory - * diff --git a/Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch b/Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index 96c37c9d465d..000000000000 --- a/Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:13:53 -0500 -Subject: [PATCH] Add ray tracing methods to LivingEntity - - -diff --git a/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..18a96dbb01d3b34476652264b2d6be3782a154ec ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockFace; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents information about a targeted block -+ */ -+public class TargetBlockInfo { -+ private final Block block; -+ private final BlockFace blockFace; -+ -+ public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) { -+ this.block = block; -+ this.blockFace = blockFace; -+ } -+ -+ /** -+ * Get the block that is targeted -+ * -+ * @return Targeted block -+ */ -+ @NotNull -+ public Block getBlock() { -+ return block; -+ } -+ -+ /** -+ * Get the targeted BlockFace -+ * -+ * @return Targeted blockface -+ */ -+ @NotNull -+ public BlockFace getBlockFace() { -+ return blockFace; -+ } -+ -+ /** -+ * Get the relative Block to the targeted block on the side it is targeted at -+ * -+ * @return Block relative to targeted block -+ */ -+ @NotNull -+ public Block getRelativeBlock() { -+ return block.getRelative(blockFace); -+ } -+ -+ public enum FluidMode { -+ NEVER, -+ SOURCE_ONLY, -+ ALWAYS -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8b89c0701dd557bcab0c05c1593354ee704b9fe4..8fe7ccf12339355554835542cc1068d9f6c3a435 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -82,6 +82,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - @NotNull - public Block getTargetBlock(@Nullable Set transparent, int maxDistance); - -+ // Paper start -+ /** -+ * Gets the block that the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return block that the living entity has targeted, -+ * or null if no block is within maxDistance -+ */ -+ @Nullable -+ public default Block getTargetBlock(int maxDistance) { -+ return getTargetBlock(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets the block that the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return block that the living entity has targeted, -+ * or null if no block is within maxDistance -+ */ -+ @Nullable -+ public Block getTargetBlock(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets the blockface of that block that the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return blockface of the block that the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public default org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance) { -+ return getTargetBlockFace(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets the blockface of that block that the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return blockface of the block that the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets information about the block the living entity has targeted, ignoring fluids -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return TargetBlockInfo about the block the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public default com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance) { -+ return getTargetBlockInfo(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER); -+ } -+ -+ /** -+ * Gets information about the block the living entity has targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param fluidMode whether to check fluids or not -+ * @return TargetBlockInfo about the block the living entity has targeted, -+ * or null if no block is targeted -+ */ -+ @Nullable -+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ // Paper end -+ - /** - * Gets the last two blocks along the living entity's line of sight. - *

diff --git a/Spigot-API-Patches/0145-Improve-death-events.patch b/Spigot-API-Patches/0145-Improve-death-events.patch deleted file mode 100644 index f42921460c5f..000000000000 --- a/Spigot-API-Patches/0145-Improve-death-events.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:32:28 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -index a5984ab06cce95d30e70511e125f69339b574c04..e19a3df9aa2204b44c0b029bda141ae6306f60a1 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -@@ -5,14 +5,24 @@ import org.bukkit.entity.LivingEntity; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; - - /** - * Thrown whenever a LivingEntity dies - */ --public class EntityDeathEvent extends EntityEvent { -+public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Cancellable { // Paper - make cancellable - private static final HandlerList handlers = new HandlerList(); - private final List drops; - private int dropExp = 0; -+ // Paper start - make cancellable -+ private boolean cancelled; -+ private double reviveHealth = 0; -+ private boolean shouldPlayDeathSound; -+ @Nullable private org.bukkit.Sound deathSound; -+ @Nullable private org.bukkit.SoundCategory deathSoundCategory; -+ private float deathSoundVolume; -+ private float deathSoundPitch; -+ // Paper end - - public EntityDeathEvent(@NotNull final LivingEntity entity, @NotNull final List drops) { - this(entity, drops, 0); -@@ -74,4 +84,134 @@ public class EntityDeathEvent extends EntityEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start - make cancellable -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ /** -+ * Get the amount of health that the entity should revive with after cancelling the event. -+ * Set to the entity's max health by default. -+ * -+ * @return The amount of health -+ */ -+ public double getReviveHealth() { -+ return reviveHealth; -+ } -+ -+ /** -+ * Set the amount of health that the entity should revive with after cancelling the event. -+ * Revive health value must be between 0 (exclusive) and the entity's max health (inclusive). -+ * -+ * @param reviveHealth The amount of health -+ * @throws IllegalArgumentException Thrown if the health is {@literal <= 0 or >} max health -+ */ -+ public void setReviveHealth(double reviveHealth) throws IllegalArgumentException { -+ double maxHealth = ((LivingEntity) entity).getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue(); -+ if ((maxHealth != 0 && reviveHealth <= 0) || (reviveHealth > maxHealth)) { -+ throw new IllegalArgumentException("Health must be between 0 (exclusive) and " + maxHealth + " (inclusive), but was " + reviveHealth); -+ } -+ this.reviveHealth = reviveHealth; -+ } -+ -+ -+ /** -+ * Whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! -+ * -+ * @return Whether or not the death sound should play. Event is called with this set to false if the entity is silent. -+ */ -+ public boolean shouldPlayDeathSound() { -+ return shouldPlayDeathSound; -+ } -+ -+ /** -+ * Set whether or not the death sound should play when the entity dies. If the event is cancelled it does not play! -+ * -+ * @param playDeathSound Enable or disable the death sound -+ */ -+ public void setShouldPlayDeathSound(boolean playDeathSound) { -+ this.shouldPlayDeathSound = playDeathSound; -+ } -+ -+ /** -+ * Get the sound that the entity makes when dying -+ * -+ * @return The sound that the entity makes -+ */ -+ @Nullable -+ public org.bukkit.Sound getDeathSound() { -+ return deathSound; -+ } -+ -+ /** -+ * Set the sound that the entity makes when dying -+ * -+ * @param sound The sound that the entity should make when dying -+ */ -+ public void setDeathSound(@Nullable org.bukkit.Sound sound) { -+ deathSound = sound; -+ } -+ -+ /** -+ * Get the sound category that the death sound should play in -+ * -+ * @return The sound category -+ */ -+ @Nullable -+ public org.bukkit.SoundCategory getDeathSoundCategory() { -+ return deathSoundCategory; -+ } -+ -+ /** -+ * Set the sound category that the death sound should play in. -+ * -+ * @param soundCategory The sound category -+ */ -+ public void setDeathSoundCategory(@Nullable org.bukkit.SoundCategory soundCategory) { -+ this.deathSoundCategory = soundCategory; -+ } -+ -+ /** -+ * Get the volume that the death sound will play at. -+ * -+ * @return The volume the death sound will play at -+ */ -+ public float getDeathSoundVolume() { -+ return deathSoundVolume; -+ } -+ -+ /** -+ * Set the volume the death sound should play at. If the event is cancelled this will not play the sound! -+ * -+ * @param volume The volume the death sound should play at -+ */ -+ public void setDeathSoundVolume(float volume) { -+ this.deathSoundVolume = volume; -+ } -+ -+ /** -+ * Get the pitch that the death sound will play with. -+ * -+ * @return The pitch the death sound will play with -+ */ -+ public float getDeathSoundPitch() { -+ return deathSoundPitch; -+ } -+ -+ /** -+ * GSetet the pitch that the death sound should play with. -+ * -+ * @param pitch The pitch the death sound should play with -+ */ -+ public void setDeathSoundPitch(float pitch) { -+ this.deathSoundPitch = pitch; -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0146-Mob-Pathfinding-API.patch b/Spigot-API-Patches/0146-Mob-Pathfinding-API.patch deleted file mode 100644 index 84081000699c..000000000000 --- a/Spigot-API-Patches/0146-Mob-Pathfinding-API.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 12:39:06 -0400 -Subject: [PATCH] Mob Pathfinding API - -Adds an API to allow plugins to instruct a Mob to Pathfind to a Location or Entity - -This does not do anything to stop other AI rules from changing the location, so -it is still up to the plugin to control that or override after another goal changed -the location. - -You can use EntityPathfindEvent to cancel new pathfinds from overriding your current. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e2a6f9c3881ff9d7373ac30e60009200432555aa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java -@@ -0,0 +1,212 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import java.util.List; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Handles pathfinding operations for an Entity -+ */ -+public interface Pathfinder { -+ -+ /** -+ * -+ * @return The entity that is controlled by this pathfinder -+ */ -+ @NotNull -+ Mob getEntity(); -+ -+ /** -+ * Instructs the Entity to stop trying to navigate to its current desired location -+ */ -+ void stopPathfinding(); -+ -+ /** -+ * If the entity is currently trying to navigate to a destination, this will return true -+ * @return true if the entity is navigating to a destination -+ */ -+ boolean hasPath(); -+ -+ /** -+ * @return The location the entity is trying to navigate to, or null if there is no destination -+ */ -+ @Nullable -+ PathResult getCurrentPath(); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, but does not set it -+ * as the current target. Useful for calculating what would happen before setting it. -+ * @param loc Location to navigate to -+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated -+ */ -+ @Nullable PathResult findPath(@NotNull Location loc); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * but does not set it as the current target. -+ * Useful for calculating what would happen before setting it. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated -+ */ -+ @Nullable PathResult findPath(@NotNull LivingEntity target); -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, and sets it with default speed -+ * as the current target. -+ * @param loc Location to navigate to -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull Location loc) { -+ return moveTo(loc, 1); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to, with desired speed -+ * as the current target. -+ * @param loc Location to navigate to -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull Location loc, double speed) { -+ PathResult path = findPath(loc); -+ return path != null && moveTo(path, speed); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * and sets it with default speed. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull LivingEntity target) { -+ return moveTo(target, 1); -+ } -+ -+ /** -+ * Calculates a destination for the Entity to navigate to to reach the target entity, -+ * and sets it with specified speed. -+ * -+ * The behavior of this PathResult is subject to the games pathfinding rules, and may -+ * result in the pathfinding automatically updating to follow the target Entity. -+ * -+ * However, this behavior is not guaranteed, and is subject to the games behavior. -+ * -+ * @param target the Entity to navigate to -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull LivingEntity target, double speed) { -+ PathResult path = findPath(target); -+ return path != null && moveTo(path, speed); -+ } -+ -+ /** -+ * Takes the result of a previous pathfinding calculation and sets it -+ * as the active pathfinding with default speed. -+ * -+ * @param path The Path to start following -+ * @return If the pathfinding was successfully started -+ */ -+ default boolean moveTo(@NotNull PathResult path) { -+ return moveTo(path, 1); -+ } -+ -+ /** -+ * Takes the result of a previous pathfinding calculation and sets it -+ * as the active pathfinding, -+ * -+ * @param path The Path to start following -+ * @param speed Speed multiplier to navigate at, where 1 is 'normal' -+ * @return If the pathfinding was successfully started -+ */ -+ boolean moveTo(@NotNull PathResult path, double speed); -+ -+ /** -+ * Checks if this pathfinder allows passing through closed doors. -+ * -+ * @return if this pathfinder allows passing through closed doors -+ */ -+ boolean canOpenDoors(); -+ -+ /** -+ * Allows this pathfinder to pass through closed doors, or not -+ * -+ * @param canOpenDoors if the mob can pass through closed doors, or not -+ */ -+ void setCanOpenDoors(boolean canOpenDoors); -+ -+ /** -+ * Checks if this pathfinder allows passing through open doors. -+ * -+ * @return if this pathfinder allows passing through open doors -+ */ -+ boolean canPassDoors(); -+ -+ /** -+ * Allows this pathfinder to pass through open doors, or not -+ * -+ * @param canPassDoors if the mob can pass through open doors, or not -+ */ -+ void setCanPassDoors(boolean canPassDoors); -+ -+ /** -+ * Checks if this pathfinder assumes that the mob can float -+ * -+ * @return if this pathfinder assumes that the mob can float -+ */ -+ boolean canFloat(); -+ -+ /** -+ * Makes this pathfinder assume that the mob can float, or not -+ * -+ * @param canFloat if the mob can float, or not -+ */ -+ void setCanFloat(boolean canFloat); -+ -+ /** -+ * Represents the result of a pathfinding calculation -+ */ -+ interface PathResult { -+ -+ /** -+ * All currently calculated points to follow along the path to reach the destination location -+ * -+ * Will return points the entity has already moved past, see {@link #getNextPointIndex()} -+ * @return List of points -+ */ -+ @NotNull -+ List getPoints(); -+ -+ /** -+ * @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity -+ * is trying to reach, or null if we are done with this pathfinding. -+ */ -+ int getNextPointIndex(); -+ -+ /** -+ * @return The next location in the path points the entity is trying to reach, or null if there is no next point -+ */ -+ @Nullable Location getNextPoint(); -+ -+ /** -+ * @return The closest point the path can get to the target location -+ */ -+ @Nullable Location getFinalPoint(); -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java -index be9334a8b5fba9181ad63c211697e798be63da25..b132287817d35579ca5128a1ed5c242bf229771a 100644 ---- a/src/main/java/org/bukkit/entity/Mob.java -+++ b/src/main/java/org/bukkit/entity/Mob.java -@@ -1,6 +1,7 @@ - package org.bukkit.entity; - - import org.bukkit.loot.Lootable; -+import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - - /** -@@ -8,6 +9,15 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Mob extends LivingEntity, Lootable { - -+ // Paper start -+ /** -+ * Enables access to control the pathing of an Entity -+ * @return Pathfinding Manager for this entity -+ */ -+ @NotNull -+ com.destroystokyo.paper.entity.Pathfinder getPathfinder(); -+ // Paper end -+ - /** - * Instructs this Mob to set the specified LivingEntity as its target. - *

diff --git a/Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch b/Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index e67693668d27..000000000000 --- a/Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:01:54 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 257bf4a75393d1e25839bcae0ca5551ee832c627..ec87c78d0f9379511467b6d13b9cdfa4c19d15ca 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1889,6 +1889,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param profile The new profile to use - */ - void setPlayerProfile(@NotNull PlayerProfile profile); -+ -+ /** -+ * Returns the amount of ticks the current cooldown lasts -+ * -+ * @return Amount of ticks cooldown will last -+ */ -+ float getCooldownPeriod(); -+ -+ /** -+ * Returns the percentage of attack power available based on the cooldown (zero to one). -+ * -+ * @param adjustTicks Amount of ticks to add to cooldown counter for this calculation -+ * @return Percentage of attack power available -+ */ -+ float getCooledAttackStrength(float adjustTicks); -+ -+ /** -+ * Reset the cooldown counter to 0, effectively starting the cooldown period. -+ */ -+ void resetCooldown(); - // Paper end - - // Spigot start diff --git a/Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch deleted file mode 100644 index c5b4ce2e419b..000000000000 --- a/Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:35 +0300 -Subject: [PATCH] Add an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/com/destroystokyo/paper/Namespaced.java b/src/main/java/com/destroystokyo/paper/Namespaced.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd1a34b82870684e09e18c47169bd472ecbbb91f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Namespaced.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper; -+ -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements -+ * or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements -+ * -+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

-+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ *

-+ * You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey} -+ * or {@link com.destroystokyo.paper.NamespacedTag} as needed instead. -+ */ -+public interface Namespaced { -+ /** -+ * Gets the namespace this resource is a part of -+ *

-+ * This is contractually obligated to only contain lowercase alphanumeric characters, -+ * periods, underscores, and hyphens. -+ * -+ * @return resource namespace -+ */ -+ @NotNull -+ String getNamespace(); -+ -+ /** -+ * Gets the key corresponding to this resource -+ *

-+ * This is contractually obligated to only contain lowercase alphanumeric characters, -+ * periods, underscores, hyphens, and forward slashes. -+ * -+ * @return resource key -+ */ -+ @NotNull -+ String getKey(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/NamespacedTag.java b/src/main/java/com/destroystokyo/paper/NamespacedTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..28f3fda950999a9c964a3608042ca60567ae1d6a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java -@@ -0,0 +1,142 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import java.util.Locale; -+import java.util.UUID; -+import java.util.regex.Pattern; -+import org.bukkit.plugin.Plugin; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace -+ * and a key. -+ *

-+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

-+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ * -+ */ -+// Paper - entire class, based on org.bukkit.NamespacedKey -+public final class NamespacedTag implements com.destroystokyo.paper.Namespaced { -+ -+ /** -+ * The namespace representing all inbuilt keys. -+ */ -+ public static final String MINECRAFT = "minecraft"; -+ /** -+ * The namespace representing all keys generated by Bukkit for backwards -+ * compatibility measures. -+ */ -+ public static final String BUKKIT = "bukkit"; -+ // -+ private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+"); -+ private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+"); -+ // -+ private final String namespace; -+ private final String key; -+ -+ /** -+ * Create a key in a specific namespace. -+ * -+ * @param namespace String representing a grouping of keys -+ * @param key Name for this specific key -+ * @deprecated should never be used by plugins, for internal use only!! -+ */ -+ @Deprecated -+ public NamespacedTag(@NotNull String namespace, @NotNull String key) { -+ Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace); -+ Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key); -+ -+ this.namespace = namespace; -+ this.key = key; -+ -+ String string = toString(); -+ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string); -+ } -+ -+ /** -+ * Create a key in the plugin's namespace. -+ *

-+ * Namespaces may only contain lowercase alphanumeric characters, periods, -+ * underscores, and hyphens. -+ *

-+ * Keys may only contain lowercase alphanumeric characters, periods, -+ * underscores, hyphens, and forward slashes. -+ * -+ * @param plugin the plugin to use for the namespace -+ * @param key the key to create -+ */ -+ public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) { -+ Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); -+ Preconditions.checkArgument(key != null, "Key cannot be null"); -+ -+ this.namespace = plugin.getName().toLowerCase(Locale.ROOT); -+ this.key = key.toLowerCase().toLowerCase(Locale.ROOT); -+ -+ // Check validity after normalization -+ Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace); -+ Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key); -+ -+ String string = toString(); -+ Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string); -+ } -+ -+ @NotNull -+ public String getNamespace() { -+ return namespace; -+ } -+ -+ @NotNull -+ public String getKey() { -+ return key; -+ } -+ -+ @Override -+ public int hashCode() { -+ int hash = 7; -+ hash = 47 * hash + this.namespace.hashCode(); -+ hash = 47 * hash + this.key.hashCode(); -+ return hash; -+ } -+ -+ @Override -+ public boolean equals(Object obj) { -+ if (obj == null) { -+ return false; -+ } -+ if (getClass() != obj.getClass()) { -+ return false; -+ } -+ final NamespacedTag other = (NamespacedTag) obj; -+ return this.namespace.equals(other.namespace) && this.key.equals(other.key); -+ } -+ -+ @Override -+ public String toString() { -+ return "#" + this.namespace + ":" + this.key; -+ } -+ -+ /** -+ * Return a new random key in the {@link #BUKKIT} namespace. -+ * -+ * @return new key -+ * @deprecated should never be used by plugins, for internal use only!! -+ */ -+ @Deprecated -+ public static NamespacedTag randomKey() { -+ return new NamespacedTag(BUKKIT, UUID.randomUUID().toString()); -+ } -+ -+ /** -+ * Get a key in the Minecraft namespace. -+ * -+ * @param key the key to use -+ * @return new key in the Minecraft namespace -+ */ -+ @NotNull -+ public static NamespacedTag minecraft(@NotNull String key) { -+ return new NamespacedTag(MINECRAFT, key); -+ } -+} -diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java -index c65f0d6569c130b4920a9e71ad24af6427f1f030..01bcb3a1bdb5accdf844d0178cec3d25746b3eaa 100644 ---- a/src/main/java/org/bukkit/NamespacedKey.java -+++ b/src/main/java/org/bukkit/NamespacedKey.java -@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; - * underscores, hyphens, and forward slashes. - * - */ --public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key -+public final class NamespacedKey implements net.kyori.adventure.key.Key, com.destroystokyo.paper.Namespaced { // Paper - implement Key and Namespaced - - /** - * The namespace representing all inbuilt keys. -@@ -84,11 +84,13 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap - } - - @NotNull -+ @Override // Paper - public String getNamespace() { - return namespace; - } - - @NotNull -+ @Override // Paper - public String getKey() { - return key; - } -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index 1c362636c56db0e6c118171ba367c43c4f7cff33..01b462fccce71cef3398dd43944046f322b8e57e 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -432,4 +432,87 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @SuppressWarnings("javadoc") - @NotNull - ItemMeta clone(); -+ -+ // Paper start - Add an API for CanPlaceOn and CanDestroy NBT values -+ /** -+ * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getDestroyableKeys()} as a replacement -+ */ -+ @Deprecated -+ Set getCanDestroy(); -+ -+ /** -+ * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canDestroy Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setDestroyableKeys(Collection)} as a replacement -+ */ -+ @Deprecated -+ void setCanDestroy(Set canDestroy); -+ -+ /** -+ * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #getPlaceableKeys()} as a replacement -+ */ -+ @Deprecated -+ Set getCanPlaceOn(); -+ -+ /** -+ * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canPlaceOn Set of materials -+ * @deprecated Minecraft does not limit this to the material enum, Use {@link #setPlaceableKeys(Collection)} as a replacement -+ */ -+ @Deprecated -+ void setCanPlaceOn(Set canPlaceOn); -+ -+ /** -+ * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ Set getDestroyableKeys(); -+ -+ /** -+ * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ void setDestroyableKeys(@NotNull Collection canDestroy); -+ -+ /** -+ * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @return Set of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ Set getPlaceableKeys(); -+ -+ /** -+ * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} -+ * -+ * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} -+ */ -+ @NotNull -+ void setPlaceableKeys(@NotNull Collection canPlaceOn); -+ -+ /** -+ * Checks for the existence of any keys that the item can be placed on -+ * -+ * @return true if this item has placeable keys -+ */ -+ boolean hasPlaceableKeys(); -+ -+ /** -+ * Checks for the existence of any keys that the item can destroy -+ * -+ * @return true if this item has destroyable keys -+ */ -+ boolean hasDestroyableKeys(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch b/Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch deleted file mode 100644 index 4d64579e4a69..000000000000 --- a/Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 13 Sep 2018 20:51:50 -0400 -Subject: [PATCH] Performance & Concurrency Improvements to Permissions - -Modifying of permissions was only half protected, enabling concurrency -issues to occur if permissions were modified async. - -While no plugin really should be doing that, modifying operations -are not heavily called, so they are safe to add synchronization to. - -Now, all modification API's will be synchronized ensuring safety. - -Additionally, hasPermission was victim to a common java newbie mistake -of calling if (containsKey(k)) return get(k), resulting in 2 map lookups. - -Optimized it to simply be a single get call cutting permission map -lookups in half. - -diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java -index 497775f7f8fa2eae34555ca0f0c6ba72d6cfab3f..c94e4cdb5785d5dfcb704c4adabda0b19a20ec7d 100644 ---- a/src/main/java/org/bukkit/permissions/PermissibleBase.java -+++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java -@@ -75,8 +75,11 @@ public class PermissibleBase implements Permissible { - - String name = inName.toLowerCase(java.util.Locale.ENGLISH); - -- if (isPermissionSet(name)) { -- return permissions.get(name).getValue(); -+ // Paper start -+ PermissionAttachmentInfo info = permissions.get(name); -+ if (info != null) { -+ return info.getValue(); -+ // Paper end - } else { - Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); - -@@ -96,15 +99,18 @@ public class PermissibleBase implements Permissible { - - String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); - -- if (isPermissionSet(name)) { -- return permissions.get(name).getValue(); -+ // Paper start -+ PermissionAttachmentInfo info = permissions.get(name); -+ if (info != null) { -+ return info.getValue(); - } -+ // Paper end - return perm.getDefault().getValue(isOp()); - } - - @Override - @NotNull -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { // Paper - synchronized - if (name == null) { - throw new IllegalArgumentException("Permission name cannot be null"); - } else if (plugin == null) { -@@ -123,7 +129,7 @@ public class PermissibleBase implements Permissible { - - @Override - @NotNull -- public PermissionAttachment addAttachment(@NotNull Plugin plugin) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin) { // Paper - synchronized - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } else if (!plugin.isEnabled()) { -@@ -139,7 +145,7 @@ public class PermissibleBase implements Permissible { - } - - @Override -- public void removeAttachment(@NotNull PermissionAttachment attachment) { -+ public synchronized void removeAttachment(@NotNull PermissionAttachment attachment) { // Paper - synchronized - if (attachment == null) { - throw new IllegalArgumentException("Attachment cannot be null"); - } -@@ -159,7 +165,7 @@ public class PermissibleBase implements Permissible { - } - - @Override -- public void recalculatePermissions() { -+ public synchronized void recalculatePermissions() { // Paper - synchronized - clearPermissions(); - Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); - Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent); -@@ -208,7 +214,7 @@ public class PermissibleBase implements Permissible { - - @Override - @Nullable -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { // Paper - if (name == null) { - throw new IllegalArgumentException("Permission name cannot be null"); - } else if (plugin == null) { -@@ -228,7 +234,7 @@ public class PermissibleBase implements Permissible { - - @Override - @Nullable -- public PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { -+ public synchronized PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { // Paper - synchronized - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } else if (!plugin.isEnabled()) { -@@ -248,7 +254,7 @@ public class PermissibleBase implements Permissible { - - @Override - @NotNull -- public Set getEffectivePermissions() { -+ public synchronized Set getEffectivePermissions() { // Paper - synchronized - return new HashSet(permissions.values()); - } - diff --git a/Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch b/Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch deleted file mode 100644 index 1a4eca8cc016..000000000000 --- a/Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 13 Sep 2018 21:39:26 -0400 -Subject: [PATCH] Add ItemStackRecipeChoice Draft API - -This is based on Spigots Draft API. This is subject to change - -Allows creating recipes that must match isSimilar to full item stack. - -diff --git a/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java -new file mode 100644 -index 0000000000000000000000000000000000000000..43e6576b1d1bb811f9feb22de0024d9c823cb21a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java -@@ -0,0 +1,51 @@ -+package com.destroystokyo.paper.inventory; -+ -+import org.bukkit.inventory.ItemStack; -+import org.bukkit.inventory.RecipeChoice; -+ -+import java.util.ArrayList; -+import java.util.List; -+ -+/** -+ * Allows crafting Items that require full matching itemstacks to complete the recipe for custom items -+ * @deprecated Draft API -+ */ -+@Deprecated -+public class ItemStackRecipeChoice implements RecipeChoice { -+ -+ protected final List choices = new ArrayList<>(); -+ -+ public ItemStackRecipeChoice(ItemStack choices) { -+ this.choices.add(choices); -+ } -+ -+ public ItemStackRecipeChoice(List choices) { -+ this.choices.addAll(choices); -+ } -+ -+ @Override -+ public ItemStack getItemStack() { -+ return choices.isEmpty() ? null : choices.get(0); -+ } -+ -+ @Override -+ public RecipeChoice clone() { -+ try { -+ ItemStackRecipeChoice clone = (ItemStackRecipeChoice) super.clone(); -+ clone.choices.addAll(this.choices); -+ return clone; -+ } catch (CloneNotSupportedException ex) { -+ throw new AssertionError(ex); -+ } -+ } -+ -+ @Override -+ public boolean test(ItemStack itemStack) { -+ for (ItemStack stack : choices) { -+ if (stack.isSimilar(itemStack)) { -+ return true; -+ } -+ } -+ return false; -+ } -+} diff --git a/Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch b/Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index cb4250b87c5e..000000000000 --- a/Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:01 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -diff --git a/src/main/java/org/bukkit/block/Furnace.java b/src/main/java/org/bukkit/block/Furnace.java -index c5a8c96fa2204d6b4d2409b1bfc97697d39d964e..9063cf370a0fe66c2a27086e125f9111b77366ae 100644 ---- a/src/main/java/org/bukkit/block/Furnace.java -+++ b/src/main/java/org/bukkit/block/Furnace.java -@@ -61,6 +61,26 @@ public interface Furnace extends Container { - */ - public void setCookTimeTotal(int cookTimeTotal); - -+ // Paper start -+ /** -+ * Gets the cook speed multiplier that this {@link Furnace} will cook -+ * compared to vanilla. -+ * -+ * @return the multiplier, a value between 0 and 200 -+ */ -+ public double getCookSpeedMultiplier(); -+ -+ /** -+ * Sets the speed multiplier that this {@link Furnace} will cook -+ * compared to vanilla. -+ * -+ * @param multiplier the multiplier to set, a value between 0 and 200 -+ * @throws IllegalArgumentException if value is less than 0 -+ * @throws IllegalArgumentException if value is more than 200 -+ */ -+ public void setCookSpeedMultiplier(double multiplier); -+ // Paper end -+ - @NotNull - @Override - public FurnaceInventory getInventory(); diff --git a/Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch b/Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch deleted file mode 100644 index 70ec0d47bd75..000000000000 --- a/Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:50:10 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..48cff063594840a07aeaf35513780e28ea019a76 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java -@@ -0,0 +1,29 @@ -+package com.destroystokyo.paper.event.entity; -+ -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called before an entity is spawned into a world by a spawner. -+ * -+ * This only includes the spawner's location and not the full BlockState snapshot for performance reasons. -+ * If you really need it you have to get the spawner yourself. -+ */ -+ -+public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent { -+ @NotNull private final Location spawnerLocation; -+ -+ public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) { -+ super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER); -+ this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null"); -+ } -+ -+ @NotNull -+ public Location getSpawnerLocation() { -+ return spawnerLocation; -+ } -+} diff --git a/Spigot-API-Patches/0153-Material-API-additions.patch b/Spigot-API-Patches/0153-Material-API-additions.patch deleted file mode 100644 index d19f497e7148..000000000000 --- a/Spigot-API-Patches/0153-Material-API-additions.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Oct 2018 21:14:29 -0400 -Subject: [PATCH] Material API additions - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index e4d0dc26fb2f2c4435e11b3460d8c93d6a6fc47f..2b53e68e96ea346a6f2b5cadcf9f81b2c231c408 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -87,6 +87,7 @@ import org.jetbrains.annotations.Nullable; - /** - * An enum of all material IDs accepted by the official server and client - */ -+@SuppressWarnings({"DeprecatedIsStillUsed", "deprecation"}) // Paper - public enum Material implements Keyed { - // - AIR(9648, 0), -@@ -3563,6 +3564,22 @@ public enum Material implements Keyed { - } - } - -+ // Paper start -+ -+ /** -+ * @return If the type is either AIR, CAVE_AIR or VOID_AIR -+ */ -+ public boolean isEmpty() { -+ switch (this) { -+ case AIR: -+ case CAVE_AIR: -+ case VOID_AIR: -+ return true; -+ } -+ return false; -+ } -+ // Paper end -+ - /** - * Do not use for any reason. - * diff --git a/Spigot-API-Patches/0154-Add-Material-Tags.patch b/Spigot-API-Patches/0154-Add-Material-Tags.patch deleted file mode 100644 index 7fa999bf703a..000000000000 --- a/Spigot-API-Patches/0154-Add-Material-Tags.patch +++ /dev/null @@ -1,1044 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 17 Jul 2018 01:27:15 -0400 -Subject: [PATCH] Add Material Tags - -This adds a bunch of useful and missing Tags to be able to identify items that -are related to each other by a trait. - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/MaterialSetTag.java b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a02a02aa0c87e0f0ed9e509e4dcab01565b3d92a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MaterialSetTag.java -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ */ -+ -+package com.destroystokyo.paper; -+ -+import com.google.common.collect.Lists; -+import io.papermc.paper.tag.BaseTag; -+import org.bukkit.Material; -+import org.bukkit.NamespacedKey; -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockState; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.inventory.ItemStack; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class MaterialSetTag extends BaseTag { -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Predicate filter) { -+ this(null, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); -+ } -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Collection materials) { -+ this(null, materials); -+ } -+ -+ /** -+ * @deprecated Use NamespacedKey version of constructor -+ */ -+ @Deprecated -+ public MaterialSetTag(@NotNull Material... materials) { -+ this(null, materials); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Predicate filter) { -+ this(key, Stream.of(Material.values()).filter(filter).collect(Collectors.toList())); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Material... materials) { -+ this(key, Lists.newArrayList(materials)); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials) { -+ this(key != null ? key : NamespacedKey.randomKey(), materials, ((Predicate) Material::isLegacy).negate()); -+ } -+ -+ public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection materials, @NotNull Predicate...globalPredicates) { -+ super(Material.class, key != null ? key : NamespacedKey.randomKey(), materials, globalPredicates); -+ } -+ -+ @NotNull -+ @Override -+ protected Set getAllPossibleValues() { -+ return Stream.of(Material.values()).collect(Collectors.toSet()); -+ } -+ -+ @Override -+ @NotNull -+ protected String getName(@NotNull Material value) { -+ return value.name(); -+ } -+ -+ public boolean isTagged(@NotNull BlockData block) { -+ return isTagged(block.getMaterial()); -+ } -+ -+ public boolean isTagged(@NotNull BlockState block) { -+ return isTagged(block.getType()); -+ } -+ -+ public boolean isTagged(@NotNull Block block) { -+ return isTagged(block.getType()); -+ } -+ -+ public boolean isTagged(@NotNull ItemStack item) { -+ return isTagged(item.getType()); -+ } -+ -+ public boolean isTagged(@NotNull Material material) { -+ return this.tagged.contains(material); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2b5a61a8afa8f73006676cdcb8a34640b43de1c3 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java -@@ -0,0 +1,558 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package com.destroystokyo.paper; -+ -+import org.bukkit.Material; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Tag; -+ -+/** -+ * Represents a collection tags to identify materials that share common properties. -+ * Will map to minecraft for missing tags, as well as custom ones that may be useful. -+ */ -+@SuppressWarnings({"NonFinalUtilityClass", "unused", "WeakerAccess"}) -+public class MaterialTags { -+ -+ private static NamespacedKey keyFor(String key) { -+ //noinspection deprecation -+ return new NamespacedKey("paper", key + "_settag"); -+ } -+ public static final MaterialSetTag ARROWS = new MaterialSetTag(keyFor("arrows")) -+ .endsWith("ARROW") -+ .ensureSize("ARROWS", 3); -+ -+ /** -+ * Covers all colors of beds. -+ */ -+ public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds")) -+ .endsWith("_BED") -+ .ensureSize("BEDS", 16); -+ -+ /** -+ * Covers all bucket items. -+ */ -+ public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets")) -+ .endsWith("BUCKET") -+ .ensureSize("BUCKETS", 8); -+ -+ /** -+ * Covers coal and charcoal. -+ */ -+ public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals")) -+ .add(Material.COAL, Material.CHARCOAL); -+ -+ /** -+ * Covers both cobblestone wall variants. -+ */ -+ public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls")) -+ .endsWith("COBBLESTONE_WALL") -+ .ensureSize("COBBLESTONE_WALLS", 2); -+ -+ /** -+ * Covers both cobblestone and mossy Cobblestone. -+ */ -+ public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones")) -+ .add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE); -+ -+ /** -+ * Covers all colors of concrete. -+ */ -+ public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes")) -+ .endsWith("_CONCRETE") -+ .ensureSize("CONCRETES", 16); -+ -+ /** -+ * Covers all colors of concrete powder. -+ */ -+ public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder")) -+ .endsWith("_CONCRETE_POWDER") -+ .ensureSize("CONCRETE_POWDER", 16); -+ -+ /** -+ * Covers the two types of cooked fish. -+ */ -+ public static final MaterialSetTag COOKED_FISH = new MaterialSetTag(keyFor("cooked_fish")) -+ .add(Material.COOKED_COD, Material.COOKED_SALMON); -+ -+ /** -+ * Covers all variants of doors. -+ */ -+ public static final MaterialSetTag DOORS = new MaterialSetTag(keyFor("doors")) -+ .endsWith("_DOOR") -+ .ensureSize("DOORS", 9); -+ -+ /** -+ * Covers all dyes. -+ */ -+ public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes")) -+ .endsWith("_DYE") -+ .ensureSize("DYES", 16); -+ -+ /** -+ * Covers all variants of gates. -+ */ -+ public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates")) -+ .endsWith("_GATE") -+ .ensureSize("FENCE_GATES", 8); -+ -+ /** -+ * Covers all variants of fences. -+ */ -+ public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences")) -+ .endsWith("_FENCE") -+ .ensureSize("FENCES", 9); -+ -+ /** -+ * Covers all variants of fish buckets. -+ */ -+ public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag(keyFor("fish_buckets")) -+ .add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET); -+ -+ /** -+ * Covers the non-colored glass and 16 stained glass (not panes). -+ */ -+ public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass")) -+ .endsWith("_GLASS") -+ .add(Material.GLASS) -+ .ensureSize("GLASS", 17); -+ -+ /** -+ * Covers the non-colored glass panes and stained glass panes (panes only). -+ */ -+ public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes")) -+ .endsWith("GLASS_PANE") -+ .ensureSize("GLASS_PANES", 17); -+ -+ /** -+ * Covers all glazed terracotta blocks. -+ */ -+ public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta")) -+ .endsWith("GLAZED_TERRACOTTA") -+ .ensureSize("GLAZED_TERRACOTTA", 16); -+ -+ /** -+ * Covers the colors of stained terracotta. -+ */ -+ public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag(keyFor("stained_terracotta")) -+ .endsWith("TERRACOTTA") -+ .not(Material.TERRACOTTA) -+ .notEndsWith("GLAZED_TERRACOTTA") -+ .ensureSize("STAINED_TERRACOTTA", 16); -+ -+ /** -+ * Covers terracotta along with the stained variants. -+ */ -+ public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta")) -+ .endsWith("TERRACOTTA") -+ .ensureSize("TERRACOTTA", 33); -+ -+ /** -+ * Covers both golden apples. -+ */ -+ public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples")) -+ .endsWith("GOLDEN_APPLE") -+ .ensureSize("GOLDEN_APPLES", 2); -+ -+ /** -+ * Covers the variants of horse armor. -+ */ -+ public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors")) -+ .endsWith("_HORSE_ARMOR") -+ .ensureSize("HORSE_ARMORS", 4); -+ -+ /** -+ * Covers the variants of infested blocks. -+ */ -+ public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks")) -+ .startsWith("INFESTED_") -+ .ensureSize("INFESTED_BLOCKS", 6); -+ -+ /** -+ * Covers the variants of mushroom blocks. -+ */ -+ public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag(keyFor("mushroom_blocks")) -+ .endsWith("MUSHROOM_BLOCK") -+ .add(Material.MUSHROOM_STEM) -+ .ensureSize("MUSHROOM_BLOCKS", 3); -+ -+ /** -+ * Covers all mushrooms. -+ */ -+ public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms")) -+ .add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM); -+ -+ /** -+ * Covers all music disc items. -+ */ -+ public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs")) -+ .startsWith("MUSIC_DISC_"); -+ -+ /** -+ * Covers all ores. -+ */ -+ public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores")) -+ .add(Material.ANCIENT_DEBRIS) -+ .endsWith("_ORE") -+ .ensureSize("ORES", 10); -+ -+ /** -+ * Covers all piston typed items and blocks including the piston head and moving piston. -+ */ -+ public static final MaterialSetTag PISTONS = new MaterialSetTag(keyFor("pistons")) -+ .contains("PISTON") -+ .ensureSize("PISTONS", 4); -+ -+ /** -+ * Covers all potato items. -+ */ -+ public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes")) -+ .endsWith("POTATO") -+ .ensureSize("POTATOES", 3); -+ -+ /** -+ * Covers all wooden pressure plates and the weighted pressure plates and the stone pressure plate. -+ */ -+ public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates")) -+ .endsWith("_PRESSURE_PLATE") -+ .ensureSize("PRESSURE_PLATES", 12); -+ -+ /** -+ * Covers the variants of prismarine blocks. -+ */ -+ public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine")) -+ .add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); -+ -+ /** -+ * Covers the variants of prismarine slabs. -+ */ -+ public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag(keyFor("prismarine_slabs")) -+ .add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB); -+ -+ /** -+ * Covers the variants of prismarine stairs. -+ */ -+ public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag(keyFor("prismarine_stairs")) -+ .add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS); -+ -+ /** -+ * Covers the variants of pumpkins. -+ */ -+ public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins")) -+ .add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN); -+ -+ /** -+ * Covers the variants of quartz blocks. -+ */ -+ public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag(keyFor("quartz_blocks")) -+ .add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ); -+ -+ /** -+ * Covers all uncooked fish items. -+ */ -+ public static final MaterialSetTag RAW_FISH = new MaterialSetTag(keyFor("raw_fish")) -+ .add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH); -+ -+ /** -+ * Covers the variants of red sandstone blocks. -+ */ -+ public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones")) -+ .endsWith("RED_SANDSTONE") -+ .ensureSize("RED_SANDSTONES", 4); -+ -+ /** -+ * Covers the variants of sandstone blocks. -+ */ -+ public static final MaterialSetTag SANDSTONES = new MaterialSetTag(keyFor("sandstones")) -+ .add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE); -+ -+ /** -+ * Covers sponge and wet sponge. -+ */ -+ public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges")) -+ .endsWith("SPONGE") -+ .ensureSize("SPONGES", 2); -+ -+ /** -+ * Covers the non-colored and colored shulker boxes. -+ */ -+ public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes")) -+ .endsWith("SHULKER_BOX") -+ .ensureSize("SHULKER_BOXES", 17); -+ -+ /** -+ * Covers zombie, creeper, skeleton, dragon, and player heads. -+ */ -+ public static final MaterialSetTag SKULLS = new MaterialSetTag(keyFor("skulls")) -+ .endsWith("_HEAD") -+ .endsWith("_SKULL") -+ .not(Material.PISTON_HEAD) -+ .ensureSize("SKULLS", 12); -+ -+ /** -+ * Covers all spawn egg items. -+ */ -+ public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs")) -+ .endsWith("_SPAWN_EGG") -+ .ensureSize("SPAWN_EGGS", 64); -+ -+ /** -+ * Covers all colors of stained glass. -+ */ -+ public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass")) -+ .endsWith("_STAINED_GLASS") -+ .ensureSize("STAINED_GLASS", 16); -+ -+ /** -+ * Covers all colors of stained glass panes. -+ */ -+ public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag(keyFor("stained_glass_panes")) -+ .endsWith("STAINED_GLASS_PANE") -+ .ensureSize("STAINED_GLASS_PANES", 16); -+ -+ /** -+ * Covers all variants of trapdoors. -+ */ -+ public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors")) -+ .endsWith("_TRAPDOOR") -+ .ensureSize("TRAPDOORS", 9); -+ -+ /** -+ * Covers all wood variants of doors. -+ */ -+ public static final MaterialSetTag WOODEN_DOORS = new MaterialSetTag(keyFor("wooden_doors")) -+ .endsWith("_DOOR") -+ .not(Material.IRON_DOOR) -+ .ensureSize("WOODEN_DOORS", 8); -+ -+ /** -+ * Covers all wood variants of fences. -+ */ -+ public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag(keyFor("wooden_fences")) -+ .endsWith("_FENCE") -+ .not(Material.NETHER_BRICK_FENCE) -+ .ensureSize("WOODEN_FENCES", 8); -+ -+ /** -+ * Covers all wood variants of trapdoors. -+ */ -+ public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors")) -+ .endsWith("_TRAPDOOR") -+ .not(Material.IRON_TRAPDOOR) -+ .ensureSize("WOODEN_TRAPDOORS", 8); -+ -+ /** -+ * Covers the wood variants of gates. -+ */ -+ public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates")) -+ .endsWith("_GATE") -+ .ensureSize("WOODEN_GATES", 8); -+ -+ /** -+ * Covers the variants of purpur. -+ */ -+ public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur")) -+ .startsWith("PURPUR_") -+ .ensureSize("PURPUR", 4); -+ -+ /** -+ * Covers the variants of signs. -+ */ -+ public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs")) -+ .endsWith("_SIGN") -+ .ensureSize("SIGNS", 16); -+ -+ /** -+ * Covers the variants of a regular torch. -+ */ -+ public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch")) -+ .add(Material.TORCH, Material.WALL_TORCH) -+ .ensureSize("TORCH", 2); -+ -+ /** -+ * Covers the variants of a redstone torch. -+ */ -+ public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch")) -+ .add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH) -+ .ensureSize("REDSTONE_TORCH", 2); -+ -+ /** -+ * Covers the variants of a soul torch. -+ */ -+ public static final MaterialSetTag SOUL_TORCH = new MaterialSetTag(keyFor("soul_torch")) -+ .add(Material.SOUL_TORCH, Material.SOUL_WALL_TORCH) -+ .ensureSize("SOUL_TORCH", 2); -+ -+ /** -+ * Covers the variants of torches. -+ */ -+ public static final MaterialSetTag TORCHES = new MaterialSetTag(keyFor("torches")) -+ .add(TORCH, REDSTONE_TORCH, SOUL_TORCH) -+ .ensureSize("TORCHES", 6); -+ -+ /** -+ * Covers the variants of lanterns. -+ */ -+ public static final MaterialSetTag LANTERNS = new MaterialSetTag(keyFor("lanterns")) -+ .add(Material.LANTERN, Material.SOUL_LANTERN) -+ .ensureSize("LANTERNS", 2); -+ -+ /** -+ * Covers the variants of rails. -+ */ -+ public static final MaterialSetTag RAILS = new MaterialSetTag(keyFor("rails")) -+ .endsWith("RAIL") -+ .ensureSize("RAILS", 4); -+ -+ /** -+ * Covers the variants of swords. -+ */ -+ public static final MaterialSetTag SWORDS = new MaterialSetTag(keyFor("swords")) -+ .endsWith("_SWORD") -+ .ensureSize("SWORDS", 6); -+ -+ /** -+ * Covers the variants of shovels. -+ */ -+ public static final MaterialSetTag SHOVELS = new MaterialSetTag(keyFor("shovels")) -+ .endsWith("_SHOVEL") -+ .ensureSize("SHOVELS", 6); -+ -+ /** -+ * Covers the variants of pickaxes. -+ */ -+ public static final MaterialSetTag PICKAXES = new MaterialSetTag(keyFor("pickaxes")) -+ .endsWith("_PICKAXE") -+ .ensureSize("PICKAXES", 6); -+ -+ /** -+ * Covers the variants of axes. -+ */ -+ public static final MaterialSetTag AXES = new MaterialSetTag(keyFor("axes")) -+ .endsWith("_AXE") -+ .ensureSize("AXES", 6); -+ -+ /** -+ * Covers the variants of hoes. -+ */ -+ public static final MaterialSetTag HOES = new MaterialSetTag(keyFor("hoes")) -+ .endsWith("_HOE") -+ .ensureSize("HOES", 6); -+ -+ /** -+ * Covers the variants of helmets. -+ */ -+ public static final MaterialSetTag HELMETS = new MaterialSetTag(keyFor("helmets")) -+ .endsWith("_HELMET") -+ .ensureSize("HELMETS", 7); -+ -+ /** -+ * Covers the variants of items that can be equipped in the helmet slot. -+ */ -+ public static final MaterialSetTag HEAD_EQUIPPABLE = new MaterialSetTag(keyFor("head_equippable")) -+ .endsWith("_HELMET") -+ .add(SKULLS) -+ .add(Material.CARVED_PUMPKIN) -+ .ensureSize("HEAD_EQUIPPABLE", 20); -+ -+ /** -+ * Covers the variants of chestplate. -+ */ -+ public static final MaterialSetTag CHESTPLATES = new MaterialSetTag(keyFor("chestplates")) -+ .endsWith("_CHESTPLATE") -+ .ensureSize("CHESTPLATES", 6); -+ -+ /** -+ * Covers the variants of items that can be equipped in the chest slot. -+ */ -+ public static final MaterialSetTag CHEST_EQUIPPABLE = new MaterialSetTag(keyFor("chest_equippable")) -+ .endsWith("_CHESTPLATE") -+ .add(Material.ELYTRA) -+ .ensureSize("CHEST_EQUIPPABLE", 7); -+ -+ /** -+ * Covers the variants of leggings. -+ */ -+ public static final MaterialSetTag LEGGINGS = new MaterialSetTag(keyFor("leggings")) -+ .endsWith("_LEGGINGS") -+ .ensureSize("LEGGINGS", 6); -+ -+ /** -+ * Covers the variants of boots. -+ */ -+ public static final MaterialSetTag BOOTS = new MaterialSetTag(keyFor("boots")) -+ .endsWith("_BOOTS") -+ .ensureSize("BOOTS", 6); -+ -+ /** -+ * Covers the variants of bows. -+ */ -+ public static final MaterialSetTag BOWS = new MaterialSetTag(keyFor("bows")) -+ .add(Material.BOW) -+ .add(Material.CROSSBOW) -+ .ensureSize("BOWS", 2); -+ -+ /** -+ * Covers the variants of player-throwable projectiles (not requiring a bow or any other "assistance"). -+ */ -+ public static final MaterialSetTag THROWABLE_PROJECTILES = new MaterialSetTag(keyFor("throwable_projectiles")) -+ .add(Material.EGG, Material.SNOWBALL, Material.SPLASH_POTION, Material.TRIDENT, Material.ENDER_PEARL, Material.EXPERIENCE_BOTTLE, Material.FIREWORK_ROCKET); -+ -+ /** -+ * Covers materials that can be colored, such as wool, shulker boxes, stained glass etc. -+ */ -+ @SuppressWarnings("unchecked") -+ public static final MaterialSetTag COLORABLE = new MaterialSetTag(keyFor("colorable")) -+ .add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS); -+ //.ensureSize("COLORABLE", 81); unit test don't have the vanilla item tags, so counts don't line up for real -+ -+ /** -+ * Covers the variants of coral. -+ */ -+ public static final MaterialSetTag CORAL = new MaterialSetTag(keyFor("coral")) -+ .endsWith("_CORAL") -+ .ensureSize("CORAL", 10); -+ -+ /** -+ * Covers the variants of coral fans. -+ */ -+ public static final MaterialSetTag CORAL_FANS = new MaterialSetTag(keyFor("coral_fans")) -+ .endsWith("_CORAL_FAN") -+ .endsWith("_CORAL_WALL_FAN") -+ .ensureSize("CORAL_FANS", 20); -+ -+ /** -+ * Covers the variants of coral blocks. -+ */ -+ public static final MaterialSetTag CORAL_BLOCKS = new MaterialSetTag(keyFor("coral_blocks")) -+ .endsWith("_CORAL_BLOCK") -+ .ensureSize("CORAL_BLOCKS", 10); -+ -+ /** -+ * Covers all items that can be enchanted from the enchantment table or anvil. -+ */ -+ public static final MaterialSetTag ENCHANTABLE = new MaterialSetTag(keyFor("enchantable")) -+ .add(PICKAXES, SWORDS, SHOVELS, AXES, HOES, HELMETS, CHEST_EQUIPPABLE, LEGGINGS, BOOTS, BOWS) -+ .add(Material.TRIDENT, Material.SHIELD, Material.FISHING_ROD, Material.SHEARS, Material.FLINT_AND_STEEL, Material.CARROT_ON_A_STICK, Material.WARPED_FUNGUS_ON_A_STICK) -+ .ensureSize("ENCHANTABLE", 65); -+} -diff --git a/src/main/java/io/papermc/paper/tag/BaseTag.java b/src/main/java/io/papermc/paper/tag/BaseTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4b8552e4e4c07b197fa9431fa911535b0222561e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/BaseTag.java -@@ -0,0 +1,160 @@ -+package io.papermc.paper.tag; -+ -+import com.google.common.collect.Lists; -+import org.bukkit.Keyed; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Tag; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+ -+public abstract class BaseTag> implements Tag { -+ -+ protected final NamespacedKey key; -+ protected final Set tagged; -+ private final List> globalPredicates; -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Predicate filter) { -+ this(clazz, key); -+ add(filter); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull T...values) { -+ this(clazz, key, Lists.newArrayList(values)); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values) { -+ this(clazz, key, values, o -> true); -+ } -+ -+ public BaseTag(@NotNull Class clazz, @NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { -+ this.key = key != null ? key : NamespacedKey.randomKey(); -+ this.tagged = clazz.isEnum() ? createEnumSet(clazz) : new HashSet<>(); -+ this.tagged.addAll(values); -+ this.globalPredicates = Lists.newArrayList(globalPredicates); -+ } -+ -+ private Set createEnumSet(Class enumClass) { -+ assert enumClass.isEnum(); -+ return (Set) EnumSet.noneOf((Class) enumClass); -+ } -+ -+ @NotNull -+ @Override -+ public NamespacedKey getKey() { -+ return key; -+ } -+ -+ @NotNull -+ @Override -+ public Set getValues() { -+ return tagged; -+ } -+ -+ @Override -+ public boolean isTagged(@NotNull T item) { -+ return tagged.contains(item); -+ } -+ -+ @NotNull -+ public C add(@NotNull Tag...tags) { -+ for (Tag tag : tags) { -+ add(tag.getValues()); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull T...values) { -+ this.tagged.addAll(Lists.newArrayList(values)); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull Collection collection) { -+ this.tagged.addAll(collection); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C add(@NotNull Predicate filter) { -+ return add(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); -+ } -+ -+ @NotNull -+ public C contains(@NotNull String with) { -+ return add(value -> getName(value).contains(with)); -+ } -+ -+ @NotNull -+ public C endsWith(@NotNull String with) { -+ return add(value -> getName(value).endsWith(with)); -+ } -+ -+ @NotNull -+ public C startsWith(@NotNull String with) { -+ return add(value -> getName(value).startsWith(with)); -+ } -+ -+ @NotNull -+ public C not(@NotNull Tag...tags) { -+ for (Tag tag : tags) { -+ not(tag.getValues()); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull T...values) { -+ this.tagged.removeAll(Lists.newArrayList(values)); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull Collection values) { -+ this.tagged.removeAll(values); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C not(@NotNull Predicate filter) { -+ not(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet())); -+ return (C) this; -+ } -+ -+ @NotNull -+ public C notContains(@NotNull String with) { -+ return not(value -> getName(value).contains(with)); -+ } -+ -+ @NotNull -+ public C notEndsWith(@NotNull String with) { -+ return not(value -> getName(value).endsWith(with)); -+ } -+ -+ @NotNull -+ public C notStartsWith(@NotNull String with) { -+ return not(value -> getName(value).startsWith(with)); -+ } -+ -+ @NotNull -+ public C ensureSize(@NotNull String label, int size) { -+ long actual = this.tagged.stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).count(); -+ if (size != actual) { -+ throw new IllegalStateException(key.toString() + ": " + label + " - Expected " + size + " values, got " + actual); -+ } -+ return (C) this; -+ } -+ -+ @NotNull -+ protected abstract Set getAllPossibleValues(); -+ -+ @NotNull -+ protected abstract String getName(@NotNull T value); -+} -diff --git a/src/main/java/io/papermc/paper/tag/EntitySetTag.java b/src/main/java/io/papermc/paper/tag/EntitySetTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c89c4619aaf388197834d98eb95af2f1e93db871 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/EntitySetTag.java -@@ -0,0 +1,42 @@ -+package io.papermc.paper.tag; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.EntityType; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+import java.util.Set; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+ -+public class EntitySetTag extends BaseTag { -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Predicate filter) { -+ super(EntityType.class, key, filter); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull EntityType... values) { -+ super(EntityType.class, key, values); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values) { -+ super(EntityType.class, key, values); -+ } -+ -+ public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection values, @NotNull Predicate... globalPredicates) { -+ super(EntityType.class, key, values, globalPredicates); -+ } -+ -+ @NotNull -+ @Override -+ protected Set getAllPossibleValues() { -+ return Stream.of(EntityType.values()).collect(Collectors.toSet()); -+ } -+ -+ @NotNull -+ @Override -+ protected String getName(@NotNull EntityType value) { -+ return value.name(); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/tag/EntityTags.java b/src/main/java/io/papermc/paper/tag/EntityTags.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9266c9d77e2eef7cd717dc729834a190f1fc7c1d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/tag/EntityTags.java -@@ -0,0 +1,50 @@ -+package io.papermc.paper.tag; -+ -+import org.bukkit.NamespacedKey; -+ -+import static org.bukkit.entity.EntityType.*; -+ -+public class EntityTags { -+ -+ private static NamespacedKey keyFor(String key) { -+ //noinspection deprecation -+ return new NamespacedKey("paper", key + "_settag"); -+ } -+ -+ /** -+ * Covers undead mobs -+ * @see https://minecraft.gamepedia.com/Mob#Undead_mobs -+ */ -+ public static final EntitySetTag UNDEADS = new EntitySetTag(keyFor("undeads")) -+ .add(DROWNED, HUSK, PHANTOM, SKELETON, SKELETON_HORSE, STRAY, WITHER, WITHER_SKELETON, ZOGLIN, ZOMBIE, ZOMBIE_HORSE, ZOMBIE_VILLAGER, ZOMBIFIED_PIGLIN) -+ .ensureSize("UNDEADS", 13); -+ -+ /** -+ * Covers all horses -+ */ -+ public static final EntitySetTag HORSES = new EntitySetTag(keyFor("horses")) -+ .contains("HORSE") -+ .ensureSize("HORSES", 3); -+ -+ /** -+ * Covers all minecarts -+ */ -+ public static final EntitySetTag MINECARTS = new EntitySetTag(keyFor("minecarts")) -+ .contains("MINECART") -+ .ensureSize("MINECARTS", 7); -+ -+ /** -+ * Covers mobs that split into smaller mobs -+ */ -+ public static final EntitySetTag SPLITTING_MOBS = new EntitySetTag(keyFor("splitting_mobs")) -+ .add(SLIME, MAGMA_CUBE) -+ .ensureSize("SLIMES", 2); -+ -+ /** -+ * Covers all water based mobs -+ * @see https://minecraft.gamepedia.com/Mob#Water-based_mobs -+ */ -+ public static final EntitySetTag WATER_BASED = new EntitySetTag(keyFor("water_based")) -+ .add(DOLPHIN, SQUID, GUARDIAN, ELDER_GUARDIAN, TURTLE, COD, SALMON, PUFFERFISH, TROPICAL_FISH) -+ .ensureSize("WATER_BASED", 9); -+} -diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index aacbfadc91f580cc667603c8165eacbadee38cca..3c2a6a2167eab43097f5d6ccf1550e12795fc0b6 100644 ---- a/src/main/java/org/bukkit/Tag.java -+++ b/src/main/java/org/bukkit/Tag.java -@@ -10,6 +10,10 @@ import org.jetbrains.annotations.NotNull; - * Note that whilst all tags defined within this interface must be present in - * implementations, their existence is not guaranteed across future versions. - * -+ *

Custom tags defined by Paper are not present (as constants) in this class. -+ * To access them please refer to {@link com.destroystokyo.paper.MaterialTags} -+ * and {@link io.papermc.paper.tag.EntityTags}.

-+ * - * @param the type of things grouped by this tag - */ - public interface Tag extends Keyed { -diff --git a/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..328c51471dc12e81c1a1b643455337b3fef4d14a ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/MaterialTagsTest.java -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ */ -+ -+package com.destroystokyo.paper; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.TestServer; -+import org.junit.Test; -+ -+import java.util.logging.Level; -+ -+public class MaterialTagsTest { -+ @Test -+ public void testInitialize() { -+ try { -+ TestServer.getInstance(); -+ MaterialTags.SHULKER_BOXES.getValues(); -+ assert true; -+ } catch (Throwable e) { -+ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); -+ assert false; -+ } -+ } -+} -diff --git a/src/test/java/io/papermc/paper/EntityTagsTest.java b/src/test/java/io/papermc/paper/EntityTagsTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..06bb9d1180361d3d00c699796bbacbce5bef2177 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/EntityTagsTest.java -@@ -0,0 +1,24 @@ -+package io.papermc.paper; -+ -+import com.destroystokyo.paper.MaterialTags; -+import io.papermc.paper.tag.EntityTags; -+import org.bukkit.Bukkit; -+import org.bukkit.TestServer; -+import org.junit.Test; -+ -+import java.util.logging.Level; -+ -+public class EntityTagsTest { -+ -+ @Test -+ public void testInitialize() { -+ try { -+ TestServer.getInstance(); -+ EntityTags.HORSES.getValues(); -+ assert true; -+ } catch (Throwable e) { -+ Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); -+ assert false; -+ } -+ } -+} -diff --git a/src/test/java/org/bukkit/TestServer.java b/src/test/java/org/bukkit/TestServer.java -index 61993528e6975c38d82213e9b5caf996fe777328..5f9d348241210689eaf41a39ace5948e7a237b12 100644 ---- a/src/test/java/org/bukkit/TestServer.java -+++ b/src/test/java/org/bukkit/TestServer.java -@@ -29,6 +29,16 @@ public final class TestServer implements InvocationHandler { - } - } - ); -+ // Paper start -+ methodMap.put( -+ Server.class.getMethod("getTag", String.class, NamespacedKey.class, Class.class), -+ new MethodHandler() { -+ public Object handle(TestServer server, Object[] args) { -+ return new com.destroystokyo.paper.MaterialSetTag(); -+ } -+ } -+ ); -+ // Paper end - methodMap.put( - Server.class.getMethod("getPluginManager"), - new MethodHandler() { diff --git a/Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch b/Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index 68b33503be41..000000000000 --- a/Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:09 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/org/bukkit/entity/Vex.java b/src/main/java/org/bukkit/entity/Vex.java -index 6b61c4ab773c731fe5ae9577fd13e44707be9787..c34a3ea7b4d16817b4bee25d5c69787e22ec44d8 100644 ---- a/src/main/java/org/bukkit/entity/Vex.java -+++ b/src/main/java/org/bukkit/entity/Vex.java -@@ -1,5 +1,7 @@ - package org.bukkit.entity; - -+import org.jetbrains.annotations.Nullable; -+ - /** - * Represents a Vex. - */ -@@ -22,4 +24,21 @@ public interface Vex extends Monster { - * @param charging new state - */ - void setCharging(boolean charging); -+ -+ // Paper start -+ /** -+ * Get the Mob that summoned this vex -+ * -+ * @return Mob that summoned this vex -+ */ -+ @Nullable -+ Mob getSummoner(); -+ -+ /** -+ * Set the summoner of this vex -+ * -+ * @param summoner New summoner -+ */ -+ void setSummoner(@Nullable Mob summoner); -+ // Paper end - } diff --git a/Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch b/Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index cc02ae973f76..000000000000 --- a/Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:32:53 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f52644fab1522bdf83ff4f489e9805b274421094 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/TargetEntityInfo.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.entity; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.util.Vector; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents information about a targeted entity -+ */ -+public class TargetEntityInfo { -+ private final Entity entity; -+ private final Vector hitVec; -+ -+ public TargetEntityInfo(@NotNull Entity entity, @NotNull Vector hitVec) { -+ this.entity = entity; -+ this.hitVec = hitVec; -+ } -+ -+ /** -+ * Get the entity that is targeted -+ * -+ * @return Targeted entity -+ */ -+ @NotNull -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * Get the position the entity is targeted at -+ * -+ * @return Targeted position -+ */ -+ @NotNull -+ public Vector getHitVector() { -+ return hitVec; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 8fe7ccf12339355554835542cc1068d9f6c3a435..561db9d594633e3909fd6d69dad1dc2976928d58 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -151,6 +151,50 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - */ - @Nullable - public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode); -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return entity being targeted, or null if no entity is targeted -+ */ -+ @Nullable -+ public default Entity getTargetEntity(int maxDistance) { -+ return getTargetEntity(maxDistance, false); -+ } -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param ignoreBlocks true to scan through blocks -+ * @return entity being targeted, or null if no entity is targeted -+ */ -+ @Nullable -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks); -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @return TargetEntityInfo about the entity being targeted, -+ * or null if no entity is targeted -+ */ -+ @Nullable -+ public default com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance) { -+ return getTargetEntityInfo(maxDistance, false); -+ } -+ -+ /** -+ * Gets information about the entity being targeted -+ * -+ * @param maxDistance this is the maximum distance to scan -+ * @param ignoreBlocks true to scan through blocks -+ * @return TargetEntityInfo about the entity being targeted, -+ * or null if no entity is targeted -+ */ -+ @Nullable -+ public com.destroystokyo.paper.entity.TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks); - // Paper end - - /** diff --git a/Spigot-API-Patches/0157-Add-sun-related-API.patch b/Spigot-API-Patches/0157-Add-sun-related-API.patch deleted file mode 100644 index 85efb56e4313..000000000000 --- a/Spigot-API-Patches/0157-Add-sun-related-API.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:15 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ec8e3a949a869545a8e0cb8c2f59f1a6dd8f5485..ce1a3de1d03e10b18c0098ee2778361cc9a4cb01 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1812,6 +1812,16 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - */ - public void setFullTime(long time); - -+ // Paper start -+ -+ /** -+ * Check if it is currently daytime in this world -+ * -+ * @return True if it is daytime -+ */ -+ public boolean isDayTime(); -+ // Paper end -+ - /** - * Gets the full in-game time on this world since the world generation - * -diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java -index b132287817d35579ca5128a1ed5c242bf229771a..d726453c041a980576312b6bee96a07837f37974 100644 ---- a/src/main/java/org/bukkit/entity/Mob.java -+++ b/src/main/java/org/bukkit/entity/Mob.java -@@ -16,6 +16,13 @@ public interface Mob extends LivingEntity, Lootable { - */ - @NotNull - com.destroystokyo.paper.entity.Pathfinder getPathfinder(); -+ -+ /** -+ * Check if this mob is exposed to daylight -+ * -+ * @return True if mob is exposed to daylight -+ */ -+ boolean isInDaylight(); - // Paper end - - /** diff --git a/Spigot-API-Patches/0158-Here-s-Johnny.patch b/Spigot-API-Patches/0158-Here-s-Johnny.patch deleted file mode 100644 index faaadfb5dbcd..000000000000 --- a/Spigot-API-Patches/0158-Here-s-Johnny.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:16 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/org/bukkit/entity/Vindicator.java b/src/main/java/org/bukkit/entity/Vindicator.java -index b8ea68a8f420c1ba99c0621a15e654d3ee48c8d6..c5d9e76a6a4125eb0409967a57e3836b8f2d24a0 100644 ---- a/src/main/java/org/bukkit/entity/Vindicator.java -+++ b/src/main/java/org/bukkit/entity/Vindicator.java -@@ -3,4 +3,30 @@ package org.bukkit.entity; - /** - * Represents a Vindicator. - */ --public interface Vindicator extends Illager { } -+public interface Vindicator extends Illager { -+ // Paper start -+ /** -+ * Check if this Vindicator is set to Johnny mode. -+ *

-+ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except -+ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile -+ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and -+ * magma cubes, will try to attack the vindicator in return. -+ * -+ * @return True if in Johnny mode -+ */ -+ boolean isJohnny(); -+ -+ /** -+ * Set this Vindicator's Johnny mode. -+ *

-+ * When in Johnny mode the Vindicator will be hostile to any kind of mob, except -+ * for evokers, ghasts, illusioners and other vindicators. It will even be hostile -+ * to vexes. All mobs, except for endermites, phantoms, guardians, slimes and -+ * magma cubes, will try to attack the vindicator in return. -+ * -+ * @param johnny True to enable Johnny mode -+ */ -+ void setJohnny(boolean johnny); -+ // Paper end -+} diff --git a/Spigot-API-Patches/0159-Turtle-API.patch b/Spigot-API-Patches/0159-Turtle-API.patch deleted file mode 100644 index 06abb703f495..000000000000 --- a/Spigot-API-Patches/0159-Turtle-API.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 28 Sep 2018 17:08:09 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..021356d151ed638068e3e89b8cc77b3795883233 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleGoHomeEvent.java -@@ -0,0 +1,49 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle decides to go home -+ */ -+public class TurtleGoHomeEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ -+ public TurtleGoHomeEvent(@NotNull Turtle turtle) { -+ super(turtle); -+ } -+ -+ /** -+ * The turtle going home -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a315c5185cd465dcf63c0ababef195da76dfc786 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleLayEggEvent.java -@@ -0,0 +1,87 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle lays eggs -+ */ -+public class TurtleLayEggEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull -+ private final Location location; -+ private int eggCount; -+ -+ public TurtleLayEggEvent(@NotNull Turtle turtle, @NotNull Location location, int eggCount) { -+ super(turtle); -+ this.location = location; -+ this.eggCount = eggCount; -+ } -+ -+ /** -+ * The turtle laying the eggs -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ /** -+ * Get the location where the eggs are being laid -+ * -+ * @return Location of eggs -+ */ -+ @NotNull -+ public Location getLocation() { -+ return location; -+ } -+ -+ /** -+ * Get the number of eggs being laid -+ * -+ * @return Number of eggs -+ */ -+ public int getEggCount() { -+ return eggCount; -+ } -+ -+ /** -+ * Set the number of eggs being laid -+ * -+ * @param eggCount Number of eggs -+ */ -+ public void setEggCount(int eggCount) { -+ if (eggCount < 1) { -+ cancelled = true; -+ return; -+ } -+ eggCount = Math.min(eggCount, 4); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..abeb24fccda2acfdb0dfdadacb8fe688bd97cf78 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/TurtleStartDiggingEvent.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Turtle; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a Turtle starts digging to lay eggs -+ */ -+public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ @NotNull private final Location location; -+ -+ public TurtleStartDiggingEvent(@NotNull Turtle turtle, @NotNull Location location) { -+ super(turtle); -+ this.location = location; -+ } -+ -+ /** -+ * The turtle digging -+ * -+ * @return The turtle -+ */ -+ @NotNull -+ public Turtle getEntity() { -+ return (Turtle) entity; -+ } -+ -+ /** -+ * Get the location where the turtle is digging -+ * -+ * @return Location where digging -+ */ -+ @NotNull -+ public Location getLocation() { -+ return location; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Turtle.java b/src/main/java/org/bukkit/entity/Turtle.java -index 0a4cd29930c2f1c28f5a3e6884c7dec45b5cac11..5375ea14097f4f10b2294488b92924a35a72d4d7 100644 ---- a/src/main/java/org/bukkit/entity/Turtle.java -+++ b/src/main/java/org/bukkit/entity/Turtle.java -@@ -1,6 +1,55 @@ - package org.bukkit.entity; - -+import org.bukkit.Location; -+import org.jetbrains.annotations.NotNull; -+ - /** - * Represents a turtle. - */ --public interface Turtle extends Animals { } -+public interface Turtle extends Animals { -+ // Paper start -+ -+ /** -+ * Get the turtle's home location -+ * -+ * @return Home location -+ */ -+ @NotNull -+ Location getHome(); -+ -+ /** -+ * Set the turtle's home location -+ * -+ * @param location Home location -+ */ -+ void setHome(@NotNull Location location); -+ -+ /** -+ * Check if turtle is currently pathfinding to it's home -+ * -+ * @return True if going home -+ */ -+ boolean isGoingHome(); -+ -+ /** -+ * Get if turtle is digging to lay eggs -+ * -+ * @return True if digging -+ */ -+ boolean isDigging(); -+ -+ /** -+ * Get if turtle is carrying egg -+ * -+ * @return True if carrying egg -+ */ -+ boolean hasEgg(); -+ -+ /** -+ * Set if turtle is carrying egg -+ * -+ * @param hasEgg True if carrying egg -+ */ -+ void setHasEgg(boolean hasEgg); -+ // Paper end -+} diff --git a/Spigot-API-Patches/0160-Add-spectator-target-events.patch b/Spigot-API-Patches/0160-Add-spectator-target-events.patch deleted file mode 100644 index c5d4b7c4dbc2..000000000000 --- a/Spigot-API-Patches/0160-Add-spectator-target-events.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:30:56 -0500 -Subject: [PATCH] Add spectator target events - -- PlayerStartSpectatingEntityEvent -- PlayerStopSpectatingEntityEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b8ec7ef2d4ef0683cc0d6ca86885dd9a01f47e16 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStartSpectatingEntityEvent.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Triggered when a player starts spectating an entity in spectator mode. -+ */ -+public class PlayerStartSpectatingEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final Entity currentSpectatorTarget; -+ @NotNull private final Entity newSpectatorTarget; -+ -+ public PlayerStartSpectatingEntityEvent(@NotNull Player player, @NotNull Entity currentSpectatorTarget, @NotNull Entity newSpectatorTarget) { -+ super(player); -+ this.currentSpectatorTarget = currentSpectatorTarget; -+ this.newSpectatorTarget = newSpectatorTarget; -+ } -+ -+ /** -+ * Gets the entity that the player is currently spectating or themselves if they weren't spectating anything -+ * -+ * @return The entity the player is currently spectating (before they start spectating the new target). -+ */ -+ @NotNull -+ public Entity getCurrentSpectatorTarget() { -+ return currentSpectatorTarget; -+ } -+ -+ /** -+ * Gets the new entity that the player will now be spectating -+ * -+ * @return The entity the player is now going to be spectating. -+ */ -+ @NotNull -+ public Entity getNewSpectatorTarget() { -+ return newSpectatorTarget; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -+ -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..693d119ab920a1bd0d1b5a0feb092631715ec0ad ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerStopSpectatingEntityEvent.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Triggered when a player stops spectating an entity in spectator mode. -+ */ -+public class PlayerStopSpectatingEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ @NotNull private final Entity spectatorTarget; -+ -+ public PlayerStopSpectatingEntityEvent(@NotNull Player player, @NotNull Entity spectatorTarget) { -+ super(player); -+ this.spectatorTarget = spectatorTarget; -+ } -+ -+ /** -+ * Gets the entity that the player is spectating -+ * -+ * @return The entity the player is currently spectating (before they will stop). -+ */ -+ @NotNull -+ public Entity getSpectatorTarget() { -+ return spectatorTarget; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0161-Add-more-Witch-API.patch b/Spigot-API-Patches/0161-Add-more-Witch-API.patch deleted file mode 100644 index 8fa1dd1e47e3..000000000000 --- a/Spigot-API-Patches/0161-Add-more-Witch-API.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 03:47:26 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/org/bukkit/entity/Witch.java b/src/main/java/org/bukkit/entity/Witch.java -index aa88aede6c4e66a608a63d07bc66d60357b0bee9..b7f9db08fb2e4633e1dfad5c752451f6ac23d437 100644 ---- a/src/main/java/org/bukkit/entity/Witch.java -+++ b/src/main/java/org/bukkit/entity/Witch.java -@@ -2,8 +2,53 @@ package org.bukkit.entity; - - import com.destroystokyo.paper.entity.RangedEntity; - -+// Paper start -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.Nullable; -+// Paper end -+ - /** - * Represents a Witch - */ - public interface Witch extends Raider, RangedEntity { // Paper -+ // Paper start -+ /** -+ * Check if Witch is drinking a potion -+ * -+ * @return True if drinking a potion -+ */ -+ boolean isDrinkingPotion(); -+ -+ /** -+ * Get time remaining (in ticks) the Witch is drinking a potion -+ * -+ * @return Time remaining (in ticks) -+ */ -+ int getPotionUseTimeLeft(); -+ -+ /** -+ * Set time remaining (in ticks) that the Witch is drinking a potion. -+ *

-+ * This only has an effect while the Witch is drinking a potion. -+ * -+ * @param ticks Time in ticks remaining -+ * @see #isDrinkingPotion -+ */ -+ void setPotionUseTimeLeft(int ticks); -+ -+ /** -+ * Get the potion the Witch is drinking -+ * -+ * @return The potion the witch is drinking -+ */ -+ @Nullable -+ ItemStack getDrinkingPotion(); -+ -+ /** -+ * Set the potion the Witch should drink -+ * -+ * @param potion Potion to drink -+ */ -+ void setDrinkingPotion(@Nullable ItemStack potion); -+ // Paper end - } diff --git a/Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch b/Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch deleted file mode 100644 index d6094643d298..000000000000 --- a/Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:44:54 +0000 -Subject: [PATCH] Make the default permission message configurable - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 2d7f8e128e23934a8fe26baf19198b7ffc8447bb..908b75f0b9897ce830ed7c0a2c1dd0a458a872f1 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1781,6 +1781,15 @@ public final class Bukkit { - return server.suggestPlayerNamesWhenNullTabCompletions(); - } - -+ /** -+ * -+ * @return the default no permission message used on the server -+ */ -+ @NotNull -+ public static String getPermissionMessage() { -+ return server.getPermissionMessage(); -+ } -+ - /** - * Creates a PlayerProfile for the specified uuid, with name as null - * @param uuid UUID to create profile for -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 01657abaff86cf7bb3ffb857024c5032781b8660..a68b973e7574cae3ee7be7cfc51786589280408a 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1564,6 +1564,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - boolean suggestPlayerNamesWhenNullTabCompletions(); - -+ /** -+ * -+ * @return the default no permission message used on the server -+ */ -+ @NotNull -+ String getPermissionMessage(); -+ - /** - * Creates a PlayerProfile for the specified uuid, with name as null - * @param uuid UUID to create profile for -diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 7c80dc54776d0d66f7816b77136f6dbd9b801704..c10fc8d2386301bc2caddcdb1cd18566bcaa8689 100644 ---- a/src/main/java/org/bukkit/command/Command.java -+++ b/src/main/java/org/bukkit/command/Command.java -@@ -185,7 +185,7 @@ public abstract class Command { - } - - if (permissionMessage == null) { -- target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake."); -+ target.sendMessage(Bukkit.getPermissionMessage()); // Paper - } else if (permissionMessage.length() != 0) { - for (String line : permissionMessage.replace("", permission).split("\n")) { - target.sendMessage(line); diff --git a/Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch b/Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch deleted file mode 100644 index a36772974a1c..000000000000 --- a/Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 15:53:43 +0000 -Subject: [PATCH] Support cancellation supression of EntityDismount/VehicleExit - events" - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -this is going to be the best soultion all around. - -Improvements/suggestions welcome! - -diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -index 963b9ead4ca0426b2e95c5641b0e89317c48853d..a976c32de6ad5e90b0a96a0f387136ab0f5eb52e 100644 ---- a/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -+++ b/src/main/java/org/bukkit/event/vehicle/VehicleExitEvent.java -@@ -13,10 +13,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final LivingEntity exited; -+ private final boolean isCancellable; // Paper - -- public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { -+ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited, boolean isCancellable) { // Paper - super(vehicle); - this.exited = exited; -+ // Paper start -+ this.isCancellable = isCancellable; -+ } -+ -+ public VehicleExitEvent(@NotNull final Vehicle vehicle, @NotNull final LivingEntity exited) { -+ this(vehicle, exited, true); -+ // Paper end - } - - /** -@@ -36,9 +44,18 @@ public class VehicleExitEvent extends VehicleEvent implements Cancellable { - - @Override - public void setCancelled(boolean cancel) { -+ // Paper start -+ if (cancel && !isCancellable) { -+ return; -+ } - this.cancelled = cancel; - } - -+ public boolean isCancellable() { -+ return isCancellable; -+ // paper end -+ } -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -index 00d8ec81b4ae6ca5e438161ec9135e3c1edea6f4..a7632c8f5cb1bce4be0e456ec34f4a69c5ce80f3 100644 ---- a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -+++ b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java -@@ -14,10 +14,19 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean cancelled; - private final Entity dismounted; -+ private final boolean isCancellable; // Paper - - public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted) { -- super(what); -+ // Paper start -+ this(what, dismounted, true); -+ } -+ -+ -+ public EntityDismountEvent(@NotNull Entity what, @NotNull Entity dismounted, boolean isCancellable) { -+ // Paper end -+ super( what ); - this.dismounted = dismounted; -+ this.isCancellable = isCancellable; // Paper - } - - @NotNull -@@ -32,9 +41,18 @@ public class EntityDismountEvent extends EntityEvent implements Cancellable { - - @Override - public void setCancelled(boolean cancel) { -+ // Paper start -+ if (cancel && !isCancellable) { -+ return; -+ } - this.cancelled = cancel; - } - -+ public boolean isCancellable() { -+ return isCancellable; -+ // Paper end -+ } -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Spigot-API-Patches/0164-Add-more-Zombie-API.patch b/Spigot-API-Patches/0164-Add-more-Zombie-API.patch deleted file mode 100644 index ec2c93dc4679..000000000000 --- a/Spigot-API-Patches/0164-Add-more-Zombie-API.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:51 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java -index a5b20b0454af5ea78e2bb7f16a56c38670c84efb..1217576e6f08abf0175ab800cfca058d5deda116 100644 ---- a/src/main/java/org/bukkit/entity/Zombie.java -+++ b/src/main/java/org/bukkit/entity/Zombie.java -@@ -90,4 +90,55 @@ public interface Zombie extends Monster, Ageable { - * @param time new conversion time - */ - void setConversionTime(int time); -+ // Paper start -+ /** -+ * Check if zombie is drowning -+ * -+ * @return True if zombie conversion process has begun -+ */ -+ boolean isDrowning(); -+ -+ /** -+ * Make zombie start drowning -+ * -+ * @param drownedConversionTime Amount of time until zombie converts from drowning -+ * -+ * @deprecated See {@link #setConversionTime(int)} -+ */ -+ @Deprecated -+ void startDrowning(int drownedConversionTime); -+ -+ /** -+ * Stop a zombie from starting the drowning conversion process -+ */ -+ void stopDrowning(); -+ -+ /** -+ * Set if zombie has its arms raised -+ * -+ * @param raised True to raise arms -+ */ -+ void setArmsRaised(boolean raised); -+ -+ /** -+ * Check if zombie has arms raised -+ * -+ * @return True if arms are raised -+ */ -+ boolean isArmsRaised(); -+ -+ /** -+ * Check if this zombie will burn in the sunlight -+ * -+ * @return True if zombie will burn in sunlight -+ */ -+ boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this zombie should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ void setShouldBurnInDay(boolean shouldBurnInDay); -+ // Paper end - } diff --git a/Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch b/Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch deleted file mode 100644 index fa3de628646c..000000000000 --- a/Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoNotSpamPls <7570108+DoNotSpamPls@users.noreply.github.com> -Date: Tue, 23 Oct 2018 19:32:55 +0300 -Subject: [PATCH] Change the reserved channel check to be sensible - - -diff --git a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -index 1d061412cdafa28c6940c7433747ab1dabe23de1..6fda7f3aa68e76af64362e9afed70fc6a5e92986 100644 ---- a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -+++ b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java -@@ -172,7 +172,7 @@ public class StandardMessenger implements Messenger { - public boolean isReservedChannel(@NotNull String channel) { - channel = validateAndCorrectChannel(channel); - -- return channel.contains("minecraft") && !channel.equals("minecraft:brand"); -+ return channel.equals("minecraft:register") || channel.equals("minecraft:unregister"); // Paper - } - - @Override -diff --git a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -index dce3d619a6f1791197e44277c2dee9eaf19ff56f..7e2335ed8acc692af1e70eddcf97ee7a56e30f68 100644 ---- a/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -+++ b/src/test/java/org/bukkit/plugin/messaging/StandardMessengerTest.java -@@ -25,8 +25,8 @@ public class StandardMessengerTest { - assertTrue(messenger.isReservedChannel("minecraft:register")); - assertFalse(messenger.isReservedChannel("test:register")); - assertTrue(messenger.isReservedChannel("minecraft:unregister")); -- assertFalse(messenger.isReservedChannel("test:nregister")); -- assertTrue(messenger.isReservedChannel("minecraft:something")); -+ assertFalse(messenger.isReservedChannel("test:unregister")); // Paper - fix typo -+ assertFalse(messenger.isReservedChannel("minecraft:something")); // Paper - now less strict - assertFalse(messenger.isReservedChannel("minecraft:brand")); - } - diff --git a/Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch b/Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index f1a017f4fbdd..000000000000 --- a/Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:06 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12c1c6fe9dc8dc5f5faf6dcf99f6857219ef22b8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerConnectionCloseEvent.java -@@ -0,0 +1,95 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+ -+import java.net.InetAddress; -+import java.util.UUID; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ *

-+ * This event is invoked when a player has disconnected. It is guaranteed that, -+ * if the server is in online-mode, that the provided uuid and username have been -+ * validated. -+ *

-+ * -+ *

-+ * The event is invoked for players who have not yet logged into the world, whereas -+ * {@link org.bukkit.event.player.PlayerQuitEvent} is only invoked on players who have logged into the world. -+ *

-+ * -+ *

-+ * The event is invoked for players who have already logged into the world, -+ * although whether or not the player exists in the world at the time of -+ * firing is undefined. (That is, whether the plugin can retrieve a Player object -+ * using the event parameters is undefined). However, it is guaranteed that this -+ * event is invoked AFTER {@link org.bukkit.event.player.PlayerQuitEvent}, if the player has already logged into the world. -+ *

-+ * -+ *

-+ * This event is guaranteed to never fire unless {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} has -+ * been fired beforehand, and this event may not be called in parallel with -+ * {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} for the same connection. -+ *

-+ * -+ *

-+ * Cancelling the {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} guarantees the corresponding -+ * {@code PlayerConnectionCloseEvent} is never called. -+ *

-+ * -+ *

-+ * The event may be invoked asynchronously or synchronously. Plugins should check -+ * {@link Event#isAsynchronous()} and handle accordingly. -+ *

-+ */ -+public class PlayerConnectionCloseEvent extends Event { -+ -+ private static final HandlerList HANDLERS = new HandlerList(); -+ -+ @NotNull private final UUID playerUniqueId; -+ @NotNull private final String playerName; -+ @NotNull private final InetAddress ipAddress; -+ -+ public PlayerConnectionCloseEvent(@NotNull final UUID playerUniqueId, @NotNull final String playerName, @NotNull final InetAddress ipAddress, final boolean async) { -+ super(async); -+ this.playerUniqueId = playerUniqueId; -+ this.playerName = playerName; -+ this.ipAddress = ipAddress; -+ } -+ -+ /** -+ * Returns the {@code UUID} of the player disconnecting. -+ */ -+ @NotNull -+ public UUID getPlayerUniqueId() { -+ return this.playerUniqueId; -+ } -+ -+ /** -+ * Returns the name of the player disconnecting. -+ */ -+ @NotNull -+ public String getPlayerName() { -+ return this.playerName; -+ } -+ -+ /** -+ * Returns the player's IP address. -+ */ -+ @NotNull -+ public InetAddress getIpAddress() { -+ return this.ipAddress; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLERS; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLERS; -+ } -+} diff --git a/Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index ec2b79af2dd5..000000000000 --- a/Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Jan 2019 00:31:12 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -intent to remove) and replace it with two new methods, clearly named and -documented as to their purpose. - -diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 6cf05fed701c67a2c797a4e0839c795802a238a1..3afd5f5c0208a4ee93b5dbfc2aab2b9d2e8a7544 100644 ---- a/src/main/java/org/bukkit/OfflinePlayer.java -+++ b/src/main/java/org/bukkit/OfflinePlayer.java -@@ -147,7 +147,9 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - * UTC. - * - * @return Date of last log-in for this player, or 0 -+ * @deprecated The API contract is ambiguous and the implementation may or may not return the correct value given this API ambiguity. It is instead recommended use {@link #getLastLogin()} or {@link #getLastSeen()} depending on your needs. - */ -+ @Deprecated - public long getLastPlayed(); - - /** -@@ -165,6 +167,30 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio - */ - @Nullable - public Location getBedSpawnLocation(); -+ // Paper start -+ /** -+ * Gets the last date and time that this player logged into the server. -+ *

-+ * If the player has never played before, this will return 0. Otherwise, -+ * it will be the amount of milliseconds since midnight, January 1, 1970 -+ * UTC. -+ * -+ * @return last login time -+ */ -+ public long getLastLogin(); -+ -+ /** -+ * Gets the last date and time that this player was seen on the server. -+ *

-+ * If the player has never played before, this will return 0. If the -+ * player is currently online, this will return the current time. -+ * Otherwise it will be the amount of milliseconds since midnight, -+ * January 1, 1970 UTC. -+ * -+ * @return last seen time -+ */ -+ public long getLastSeen(); -+ // Paper end - - /** - * Increments the given statistic for this player. diff --git a/Spigot-API-Patches/0168-BlockDestroyEvent.patch b/Spigot-API-Patches/0168-BlockDestroyEvent.patch deleted file mode 100644 index 4ad73d8ef143..000000000000 --- a/Spigot-API-Patches/0168-BlockDestroyEvent.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:19:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..28255dc39eab5faf324d1fe556ab12daed527ff6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/block/BlockDestroyEvent.java -@@ -0,0 +1,92 @@ -+package com.destroystokyo.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired anytime the server intends to 'destroy' a block through some triggering reason. -+ * This does not fire anytime a block is set to air, but only with more direct triggers such -+ * as physics updates, pistons, Entities changing blocks, commands set to "Destroy". -+ * -+ * This event is associated with the game playing a sound effect at the block in question, when -+ * something can be described as "intend to destroy what is there", -+ * -+ * Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event. -+ * -+ */ -+public class BlockDestroyEvent extends BlockEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull private final BlockData newState; -+ private final boolean willDrop; -+ private boolean playEffect = true; -+ -+ private boolean cancelled = false; -+ -+ public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) { -+ super(block); -+ this.newState = newState; -+ this.willDrop = willDrop; -+ } -+ -+ /** -+ * @return The new state of this block (Air, or a Fluid type) -+ */ -+ @NotNull -+ public BlockData getNewState() { -+ return newState; -+ } -+ -+ /** -+ * @return If the server is going to drop the block in question with this destroy event -+ */ -+ public boolean willDrop() { -+ return this.willDrop; -+ } -+ -+ /** -+ * @return If the server is going to play the sound effect for this destruction -+ */ -+ public boolean playEffect() { -+ return this.playEffect; -+ } -+ -+ /** -+ * @param playEffect If the server should play the sound effect for this destruction -+ */ -+ public void setPlayEffect(boolean playEffect) { -+ this.playEffect = playEffect; -+ } -+ -+ /** -+ * @return If the event is cancelled, meaning the block will not be destroyed -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * If the event is cancelled, the block will remain in its previous state. -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch b/Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch deleted file mode 100644 index 9b2dfc0c726a..000000000000 --- a/Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 28 Jan 2014 19:13:57 -0500 -Subject: [PATCH] Add ItemStack Recipe API helper methods - -Allows using ExactChoice Recipes with easier methodss - -diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index d742c4058ba9aed4fbe1591fd755a06608b06e98..222a12baa8e93ad686ab59426653f066d5876e38 100644 ---- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -145,6 +145,13 @@ public class ShapedRecipe implements Recipe, Keyed { - return this; - } - -+ // Paper start -+ @NotNull -+ public ShapedRecipe setIngredient(char key, @NotNull ItemStack item) { -+ return setIngredient(key, new RecipeChoice.ExactChoice(item)); -+ } -+ // Paper end -+ - /** - * Get a copy of the ingredients map. - * -diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -index 84062dd719cb8a6142dc8c806777cb208c6b42b2..7f6d3c71c5b3a9aa54c84a4c3b7c3614a0d477ce 100644 ---- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java -@@ -143,6 +143,40 @@ public class ShapelessRecipe implements Recipe, Keyed { - return this; - } - -+ // Paper start -+ @NotNull -+ public ShapelessRecipe addIngredient(@NotNull ItemStack item) { -+ return addIngredient(item.getAmount(), item); -+ } -+ -+ @NotNull -+ public ShapelessRecipe addIngredient(int count, @NotNull ItemStack item) { -+ Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients"); -+ while (count-- > 0) { -+ ingredients.add(new RecipeChoice.ExactChoice(item)); -+ } -+ return this; -+ } -+ -+ @NotNull -+ public ShapelessRecipe removeIngredient(@NotNull ItemStack item) { -+ return removeIngredient(1, item); -+ } -+ -+ @NotNull -+ public ShapelessRecipe removeIngredient(int count, @NotNull ItemStack item) { -+ Iterator iterator = ingredients.iterator(); -+ while (count > 0 && iterator.hasNext()) { -+ ItemStack stack = iterator.next().getItemStack(); -+ if (stack.equals(item)) { -+ iterator.remove(); -+ count--; -+ } -+ } -+ return this; -+ } -+ // Paper end -+ - /** - * Removes an ingredient from the list. - * diff --git a/Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch b/Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch deleted file mode 100644 index 4bb54b5c9291..000000000000 --- a/Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:04:43 +0200 -Subject: [PATCH] Add WhitelistToggleEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fdd5eedb2b7401439912a3a4343a920f32edc860 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * This event is fired when whitelist is toggled -+ * -+ * @author Mark Vainomaa -+ */ -+public class WhitelistToggleEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean enabled; -+ -+ public WhitelistToggleEvent(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ /** -+ * Gets whether whitelist is going to be enabled or not -+ * -+ * @return Whether whitelist is going to be enabled or not -+ */ -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0171-Annotation-Test-changes.patch b/Spigot-API-Patches/0171-Annotation-Test-changes.patch deleted file mode 100644 index 380b55d7751d..000000000000 --- a/Spigot-API-Patches/0171-Annotation-Test-changes.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 17 Mar 2019 23:04:30 +0000 -Subject: [PATCH] Annotation Test changes - - -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index c62919f18f318fec15a6c364d8b6d562c2b04762..2bb75e967d4250476a151599b68de80011d222b2 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -46,7 +46,17 @@ public class AnnotationTest { - "org/bukkit/util/io/Wrapper", - "org/bukkit/plugin/java/PluginClassLoader", - // Generic functional interface -- "org/bukkit/util/Consumer" -+ "org/bukkit/util/Consumer", -+ // Paper start -+ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull -+ "co/aikar/timings/TimingHistory$2", -+ "co/aikar/timings/TimingHistory$2$1", -+ "co/aikar/timings/TimingHistory$2$1$1", -+ "co/aikar/timings/TimingHistory$2$1$2", -+ "co/aikar/timings/TimingHistory$3", -+ "co/aikar/timings/TimingHistory$4", -+ "co/aikar/timings/TimingHistoryEntry$1" -+ // Paper end - }; - - @Test diff --git a/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch b/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch deleted file mode 100644 index cf940ce2fe6f..000000000000 --- a/Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:21:23 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index c137199ed0537874010f1abf311a9cbee56831ac..2622a2f5c9e2cb43aff7ef9eac2dcdb3fd8fad04 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -662,5 +662,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - Chunk getChunk(); -+ -+ /** -+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. -+ */ -+ @NotNull -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); - // Paper end - } diff --git a/Spigot-API-Patches/0173-Add-GS4-Query-event.patch b/Spigot-API-Patches/0173-Add-GS4-Query-event.patch deleted file mode 100644 index ffab49a92a53..000000000000 --- a/Spigot-API-Patches/0173-Add-GS4-Query-event.patch +++ /dev/null @@ -1,424 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:27 +0200 -Subject: [PATCH] Add GS4 Query event - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..77a19995f6792a182c5a43d6714e7bda0f42df5b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java -@@ -0,0 +1,412 @@ -+package com.destroystokyo.paper.event.server; -+ -+import com.google.common.base.Preconditions; -+import com.google.common.collect.ImmutableList; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+import java.net.InetAddress; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * This event is fired if server is getting queried over GS4 Query protocol -+ * -+ * Adapted from Velocity's ProxyQueryEvent -+ * -+ * @author Mark Vainomaa -+ */ -+public final class GS4QueryEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private final QueryType queryType; -+ private final InetAddress querierAddress; -+ private QueryResponse response; -+ -+ public GS4QueryEvent(@NotNull QueryType queryType, @NotNull InetAddress querierAddress, @NotNull QueryResponse response) { -+ super(true); // should always be called async -+ this.queryType = Preconditions.checkNotNull(queryType, "queryType"); -+ this.querierAddress = Preconditions.checkNotNull(querierAddress, "querierAddress"); -+ this.response = Preconditions.checkNotNull(response, "response"); -+ } -+ -+ /** -+ * Get query type -+ * @return query type -+ */ -+ @NotNull -+ public QueryType getQueryType() { -+ return queryType; -+ } -+ -+ /** -+ * Get querier address -+ * @return querier address -+ */ -+ @NotNull -+ public InetAddress getQuerierAddress() { -+ return querierAddress; -+ } -+ -+ /** -+ * Get query response -+ * @return query response -+ */ -+ @NotNull -+ public QueryResponse getResponse() { -+ return response; -+ } -+ -+ /** -+ * Set query response -+ * @param response query response -+ */ -+ public void setResponse(@NotNull QueryResponse response) { -+ this.response = Preconditions.checkNotNull(response, "response"); -+ } -+ -+ @Override -+ public String toString() { -+ return "GS4QueryEvent{" + -+ "queryType=" + queryType + -+ ", querierAddress=" + querierAddress + -+ ", response=" + response + -+ '}'; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * The type of query -+ */ -+ public enum QueryType { -+ /** -+ * Basic query asks only a subset of information, such as motd, game type (hardcoded to

MINECRAFT
), map, -+ * current players, max players, server port and server motd -+ */ -+ BASIC, -+ -+ /** -+ * Full query asks pretty much everything present on this event (only hardcoded values cannot be modified here). -+ */ -+ FULL -+ ; -+ } -+ -+ public final static class QueryResponse { -+ private final String motd; -+ private final String gameVersion; -+ private final String map; -+ private final int currentPlayers; -+ private final int maxPlayers; -+ private final String hostname; -+ private final int port; -+ private final Collection players; -+ private final String serverVersion; -+ private final Collection plugins; -+ -+ private QueryResponse(String motd, String gameVersion, String map, int currentPlayers, int maxPlayers, String hostname, int port, Collection players, String serverVersion, Collection plugins) { -+ this.motd = motd; -+ this.gameVersion = gameVersion; -+ this.map = map; -+ this.currentPlayers = currentPlayers; -+ this.maxPlayers = maxPlayers; -+ this.hostname = hostname; -+ this.port = port; -+ this.players = players; -+ this.serverVersion = serverVersion; -+ this.plugins = plugins; -+ } -+ -+ /** -+ * Get motd which will be used to reply to the query. By default it is {@link org.bukkit.Server#getMotd()}. -+ * @return motd -+ */ -+ @NotNull -+ public String getMotd() { -+ return motd; -+ } -+ -+ /** -+ * Get game version which will be used to reply to the query. By default supported Minecraft versions range is sent. -+ * @return game version -+ */ -+ @NotNull -+ public String getGameVersion() { -+ return gameVersion; -+ } -+ -+ /** -+ * Get map name which will be used to reply to the query. By default {@code world} is sent. -+ * @return map name -+ */ -+ @NotNull -+ public String getMap() { -+ return map; -+ } -+ -+ /** -+ * Get current online player count which will be used to reply to the query. -+ * @return online player count -+ */ -+ public int getCurrentPlayers() { -+ return currentPlayers; -+ } -+ -+ /** -+ * Get max player count which will be used to reply to the query. -+ * @return max player count -+ */ -+ public int getMaxPlayers() { -+ return maxPlayers; -+ } -+ -+ /** -+ * Get server (public facing) hostname -+ * @return server hostname -+ */ -+ @NotNull -+ public String getHostname() { -+ return hostname; -+ } -+ -+ /** -+ * Get server (public facing) port -+ * @return server port -+ */ -+ public int getPort() { -+ return port; -+ } -+ -+ /** -+ * Get collection of players which will be used to reply to the query. -+ * @return collection of players -+ */ -+ @NotNull -+ public Collection getPlayers() { -+ return players; -+ } -+ -+ /** -+ * Get server software (name and version) which will be used to reply to the query. -+ * @return server software -+ */ -+ @NotNull -+ public String getServerVersion() { -+ return serverVersion; -+ } -+ -+ /** -+ * Get list of plugins which will be used to reply to the query. -+ * @return collection of plugins -+ */ -+ @NotNull -+ public Collection getPlugins() { -+ return plugins; -+ } -+ -+ -+ /** -+ * Creates a new {@link Builder} instance from data represented by this response -+ * @return {@link QueryResponse} builder -+ */ -+ @NotNull -+ public Builder toBuilder() { -+ return QueryResponse.builder() -+ .motd(getMotd()) -+ .gameVersion(getGameVersion()) -+ .map(getMap()) -+ .currentPlayers(getCurrentPlayers()) -+ .maxPlayers(getMaxPlayers()) -+ .hostname(getHostname()) -+ .port(getPort()) -+ .players(getPlayers()) -+ .serverVersion(getServerVersion()) -+ .plugins(getPlugins()); -+ } -+ -+ /** -+ * Creates a new {@link Builder} instance -+ * @return {@link QueryResponse} builder -+ */ -+ @NotNull -+ public static Builder builder() { -+ return new Builder(); -+ } -+ -+ /** -+ * A builder for {@link QueryResponse} objects. -+ */ -+ public static final class Builder { -+ private String motd; -+ private String gameVersion; -+ private String map; -+ private String hostname; -+ private String serverVersion; -+ -+ private int currentPlayers; -+ private int maxPlayers; -+ private int port; -+ -+ private List players = new ArrayList<>(); -+ private List plugins = new ArrayList<>(); -+ -+ private Builder() {} -+ -+ @NotNull -+ public Builder motd(@NotNull String motd) { -+ this.motd = Preconditions.checkNotNull(motd, "motd"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder gameVersion(@NotNull String gameVersion) { -+ this.gameVersion = Preconditions.checkNotNull(gameVersion, "gameVersion"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder map(@NotNull String map) { -+ this.map = Preconditions.checkNotNull(map, "map"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder currentPlayers(int currentPlayers) { -+ Preconditions.checkArgument(currentPlayers >= 0, "currentPlayers cannot be negative"); -+ this.currentPlayers = currentPlayers; -+ return this; -+ } -+ -+ @NotNull -+ public Builder maxPlayers(int maxPlayers) { -+ Preconditions.checkArgument(maxPlayers >= 0, "maxPlayers cannot be negative"); -+ this.maxPlayers = maxPlayers; -+ return this; -+ } -+ -+ @NotNull -+ public Builder hostname(@NotNull String hostname) { -+ this.hostname = Preconditions.checkNotNull(hostname, "hostname"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder port(int port) { -+ Preconditions.checkArgument(port >= 1 && port <= 65535, "port must be between 1-65535"); -+ this.port = port; -+ return this; -+ } -+ -+ @NotNull -+ public Builder players(@NotNull Collection players) { -+ this.players.addAll(Preconditions.checkNotNull(players, "players")); -+ return this; -+ } -+ -+ @NotNull -+ public Builder players(@NotNull String... players) { -+ this.players.addAll(Arrays.asList(Preconditions.checkNotNull(players, "players"))); -+ return this; -+ } -+ -+ @NotNull -+ public Builder clearPlayers() { -+ this.players.clear(); -+ return this; -+ } -+ -+ @NotNull -+ public Builder serverVersion(@NotNull String serverVersion) { -+ this.serverVersion = Preconditions.checkNotNull(serverVersion, "serverVersion"); -+ return this; -+ } -+ -+ @NotNull -+ public Builder plugins(@NotNull Collection plugins) { -+ this.plugins.addAll(Preconditions.checkNotNull(plugins, "plugins")); -+ return this; -+ } -+ -+ @NotNull -+ public Builder plugins(@NotNull PluginInformation... plugins) { -+ this.plugins.addAll(Arrays.asList(Preconditions.checkNotNull(plugins, "plugins"))); -+ return this; -+ } -+ -+ @NotNull -+ public Builder clearPlugins() { -+ this.plugins.clear(); -+ return this; -+ } -+ -+ /** -+ * Builds new {@link QueryResponse} with supplied data -+ * @return response -+ */ -+ @NotNull -+ public QueryResponse build() { -+ return new QueryResponse( -+ Preconditions.checkNotNull(motd, "motd"), -+ Preconditions.checkNotNull(gameVersion, "gameVersion"), -+ Preconditions.checkNotNull(map, "map"), -+ currentPlayers, -+ maxPlayers, -+ Preconditions.checkNotNull(hostname, "hostname"), -+ port, -+ ImmutableList.copyOf(players), -+ Preconditions.checkNotNull(serverVersion, "serverVersion"), -+ ImmutableList.copyOf(plugins) -+ ); -+ } -+ } -+ -+ /** -+ * Plugin information -+ */ -+ public static class PluginInformation { -+ private String name; -+ private String version; -+ -+ public PluginInformation(@NotNull String name, @NotNull String version) { -+ this.name = Preconditions.checkNotNull(name, "name"); -+ this.version = Preconditions.checkNotNull(version, "version"); -+ } -+ -+ @NotNull -+ public String getName() { -+ return name; -+ } -+ -+ public void setName(@NotNull String name) { -+ this.name = name; -+ } -+ -+ public void setVersion(@NotNull String version) { -+ this.version = version; -+ } -+ -+ @NotNull -+ public String getVersion() { -+ return version; -+ } -+ -+ @NotNull -+ public static PluginInformation of(@NotNull String name, @NotNull String version) { -+ return new PluginInformation(name, version); -+ } -+ } -+ } -+} diff --git a/Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch b/Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch deleted file mode 100644 index 2eb0647eac27..000000000000 --- a/Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:33:13 -0700 -Subject: [PATCH] Add PlayerPostRespawnEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..31f34b54801f6699ce43355fa2a0a51f1ad0c997 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.Location; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired after a player has respawned -+ */ -+public class PlayerPostRespawnEvent extends PlayerEvent { -+ private final static HandlerList handlers = new HandlerList(); -+ private final Location respawnedLocation; -+ private final boolean isBedSpawn; -+ -+ public PlayerPostRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnedLocation, final boolean isBedSpawn) { -+ super(respawnPlayer); -+ this.respawnedLocation = respawnedLocation; -+ this.isBedSpawn = isBedSpawn; -+ } -+ -+ /** -+ * Returns the location of the respawned player -+ * -+ * @return location of the respawned player -+ */ -+ @NotNull -+ public Location getRespawnedLocation() { -+ return respawnedLocation.clone(); -+ } -+ -+ /** -+ * Checks if the player respawned to their bed -+ * -+ * @return whether the player respawned to their bed -+ */ -+ public boolean isBedSpawn() { -+ return isBedSpawn; -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch b/Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch deleted file mode 100644 index 28d9857af004..000000000000 --- a/Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:44:26 -0400 -Subject: [PATCH] Ignore package-private methods for nullability annotations - -This isn't API - -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 2bb75e967d4250476a151599b68de80011d222b2..03229d5f4ec36a82197beb391356d791ff67fb2f 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -168,7 +168,7 @@ public class AnnotationTest { - - private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { - // Exclude private, synthetic and deprecated methods -- if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0) { -+ if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private - return false; - } - diff --git a/Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch b/Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch deleted file mode 100644 index 36b534410afa..000000000000 --- a/Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:39:01 -0400 -Subject: [PATCH] Flip some Spigot API null annotations - -while some of these may of been true, they are extreme cases and cause -a ton of noise to plugin developers. - -These do not help plugin developers if they bring moise noise than value. - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 908b75f0b9897ce830ed7c0a2c1dd0a458a872f1..1f5bcda86990d7c336db21d9c927bbf6b1b6d74d 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1377,7 +1377,7 @@ public final class Bukkit { - * - * @return the scoreboard manager or null if no worlds are loaded. - */ -- @Nullable -+ @NotNull // Paper - public static ScoreboardManager getScoreboardManager() { - return server.getScoreboardManager(); - } -@@ -1674,7 +1674,7 @@ public final class Bukkit { - * @param clazz the class of the tag entries - * @return the tag or null - */ -- @Nullable -+ @UndefinedNullability // Paper - public static Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz) { - return server.getTag(registry, tag, clazz); - } -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index 9c91c49ed7302c12fcb1d8e9bc58712efc199954..d5d67b3d84cd88ed0f858497e68535ec0162c700 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -46,7 +46,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @param y The y-coordinate of this new location - * @param z The z-coordinate of this new location - */ -- public Location(@Nullable final World world, final double x, final double y, final double z) { -+ public Location(@UndefinedNullability final World world, final double x, final double y, final double z) { // Paper - this(world, x, y, z, 0, 0); - } - -@@ -60,7 +60,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @param yaw The absolute rotation on the x-plane, in degrees - * @param pitch The absolute rotation on the y-plane, in degrees - */ -- public Location(@Nullable final World world, final double x, final double y, final double z, final float yaw, final float pitch) { -+ public Location(@UndefinedNullability final World world, final double x, final double y, final double z, final float yaw, final float pitch) { - if (world != null) { - this.world = new WeakReference<>(world); - } -@@ -102,7 +102,7 @@ public class Location implements Cloneable, ConfigurationSerializable { - * @throws IllegalArgumentException when world is unloaded - * @see #isWorldLoaded() - */ -- @Nullable -+ @UndefinedNullability - public World getWorld() { - if (this.world == null) { - return null; -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a68b973e7574cae3ee7be7cfc51786589280408a..39188fcf95beff906c68a822f6aa5e19ad3ad08c 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1160,7 +1160,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * - * @return the scoreboard manager or null if no worlds are loaded. - */ -- @Nullable -+ @NotNull // Paper - ScoreboardManager getScoreboardManager(); - - /** -@@ -1430,7 +1430,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @param clazz the class of the tag entries - * @return the tag or null - */ -- @Nullable -+ @UndefinedNullability - Tag getTag(@NotNull String registry, @NotNull NamespacedKey tag, @NotNull Class clazz); - - /** -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index 3578f491a053154789ad696e93c70fdde74912e6..0654873eef22d1e35c7430f098ff9e8f00b870e3 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -3,6 +3,7 @@ package org.bukkit.inventory; - import org.bukkit.Color; - import org.bukkit.Material; - import org.bukkit.Server; -+import org.bukkit.UndefinedNullability; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.ItemMeta; - import org.bukkit.inventory.meta.SkullMeta; -@@ -25,7 +26,7 @@ public interface ItemFactory { - * @return a new ItemMeta that could be applied to an item stack of the - * specified material - */ -- @Nullable -+ @UndefinedNullability // Paper - ItemMeta getItemMeta(@NotNull final Material material); - - /** -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index ce9ee2d6d72069af518fc8d7d48a35c03b5f9f1f..3d63514729ddc30ff559a65815612be81e777892 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -8,6 +8,7 @@ import java.util.Set; // Paper - import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.Material; -+import org.bukkit.UndefinedNullability; - import org.bukkit.Utility; - import org.bukkit.configuration.serialization.ConfigurationSerializable; - import org.bukkit.enchantments.Enchantment; -@@ -546,7 +547,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - * - * @return a copy of the current ItemStack's ItemData - */ -- @Nullable -+ @UndefinedNullability // Paper - public ItemMeta getItemMeta() { - return this.meta == null ? Bukkit.getItemFactory().getItemMeta(this.type) : this.meta.clone(); - } diff --git a/Spigot-API-Patches/0177-Server-Tick-Events.patch b/Spigot-API-Patches/0177-Server-Tick-Events.patch deleted file mode 100644 index 9cb8b9a4c0ed..000000000000 --- a/Spigot-API-Patches/0177-Server-Tick-Events.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 21:58:55 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9fd28e03649f66f71fb7f0536a137557ec32cd25 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickEndEvent.java -@@ -0,0 +1,59 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the server has finished ticking the main loop -+ */ -+public class ServerTickEndEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int tickNumber; -+ private final double tickDuration; -+ private final long timeEnd; -+ -+ public ServerTickEndEvent(int tickNumber, double tickDuration, long timeRemaining) { -+ this.tickNumber = tickNumber; -+ this.tickDuration = tickDuration; -+ this.timeEnd = System.nanoTime() + timeRemaining; -+ } -+ -+ /** -+ * @return What tick this was since start (first tick = 1) -+ */ -+ public int getTickNumber() { -+ return tickNumber; -+ } -+ -+ /** -+ * @return Time in milliseconds of how long this tick took -+ */ -+ public double getTickDuration() { -+ return tickDuration; -+ } -+ -+ /** -+ * Amount of nanoseconds remaining before the next tick should start. -+ * -+ * If this value is negative, then that means the server has exceeded the tick time limit and TPS has been lost. -+ * -+ * Method will continously return the updated time remaining value. (return value is not static) -+ * -+ * @return Amount of nanoseconds remaining before the next tick should start -+ */ -+ public long getTimeRemaining() { -+ return this.timeEnd - System.nanoTime(); -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eac85f1f49088bb71afb01eff4d5f53887306461 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/server/ServerTickStartEvent.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.event.server; -+ -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+public class ServerTickStartEvent extends Event { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final int tickNumber; -+ -+ public ServerTickStartEvent(int tickNumber) { -+ this.tickNumber = tickNumber; -+ } -+ -+ /** -+ * @return What tick this is going be since start (first tick = 1) -+ */ -+ public int getTickNumber() { -+ return tickNumber; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch b/Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch deleted file mode 100644 index e41136bc7f75..000000000000 --- a/Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 11 Mar 2013 20:04:34 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4..8c46eaebf004823c1c31eb2c7304181487cb1332 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -36,7 +36,6 @@ public class PlayerDeathEvent extends EntityDeathEvent { - } - // Paper end - -- @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { - this(player, drops, droppedExp, 0, deathMessage); - } -@@ -56,6 +55,41 @@ public class PlayerDeathEvent extends EntityDeathEvent { - this.adventure$deathMessage = deathMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(deathMessage) : net.kyori.adventure.text.Component.empty(); // Paper - } - -+ @Deprecated // Paper -+ // Paper start -+ private List itemsToKeep = new java.util.ArrayList<>(); -+ -+ /** -+ * A mutable collection to add items that the player should retain in their inventory on death (Similar to KeepInventory game rule) -+ * -+ * You MUST remove the item from the .getDrops() collection too or it will duplicate! -+ *
{@code
-+     *    {@literal @EventHandler(ignoreCancelled = true)}
-+     *     public void onPlayerDeath(PlayerDeathEvent event) {
-+     *         for (Iterator iterator = event.getDrops().iterator(); iterator.hasNext(); ) {
-+     *             ItemStack drop = iterator.next();
-+     *             List lore = drop.getLore();
-+     *             if (lore != null && !lore.isEmpty()) {
-+     *                 if (lore.get(0).contains("(SOULBOUND)")) {
-+     *                     iterator.remove();
-+     *                     event.getItemsToKeep().add(drop);
-+     *                 }
-+     *             }
-+     *         }
-+     *     }
-+     * }
-+ * -+ * Adding an item to this list that the player did not previously have will give them the item on death. -+ * An example case could be a "Note" that "You died at X/Y/Z coordinates" -+ * -+ * @return The list to hold items to keep -+ */ -+ @NotNull -+ public List getItemsToKeep() { -+ return itemsToKeep; -+ } -+ // Paper end -+ - @NotNull - @Override - public Player getEntity() { diff --git a/Spigot-API-Patches/0179-Add-Heightmap-API.patch b/Spigot-API-Patches/0179-Add-Heightmap-API.patch deleted file mode 100644 index 73e1e8d46ffe..000000000000 --- a/Spigot-API-Patches/0179-Add-Heightmap-API.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Dec 2018 19:00:36 -0800 -Subject: [PATCH] Add Heightmap API - -Changed to use upstream's heightmap API - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/HeightmapType.java b/src/main/java/com/destroystokyo/paper/HeightmapType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..709e44ea1b14ab6917501c928e689cc6cbdf4bb4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/HeightmapType.java -@@ -0,0 +1,39 @@ -+package com.destroystokyo.paper; -+ -+import org.bukkit.*; -+ -+/** -+ * Enumeration of different heightmap types maintained by the server. Generally using these maps is much faster -+ * than using an iterative search for a block in a given x, z coordinate. -+ * -+ * @deprecated Upstream has added their own API for using the game heightmaps. See {@link org.bukkit.HeightMap} and the -+ * non-deprecated getHighestBlock methods on World such as {@link org.bukkit.World#getHighestBlockAt(Location, HeightMap)}. -+ */ -+@Deprecated -+public enum HeightmapType { -+ -+ /** -+ * The highest block used for lighting in the world. Also the block returned by {@link World#getHighestBlockYAt(int, int)}} -+ */ -+ LIGHT_BLOCKING, -+ -+ /** -+ * References the highest block in the world. -+ */ -+ ANY, -+ -+ /** -+ * References the highest solid block in a world. -+ */ -+ SOLID, -+ -+ /** -+ * References the highest solid or liquid block in a world. -+ */ -+ SOLID_OR_LIQUID, -+ -+ /** -+ * References the highest solid or liquid block in a world, excluding leaves. -+ */ -+ SOLID_OR_LIQUID_NO_LEAVES; -+} -diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java -index d5d67b3d84cd88ed0f858497e68535ec0162c700..432d5711b7ec34eafeb27df82d367612dfe1fe54 100644 ---- a/src/main/java/org/bukkit/Location.java -+++ b/src/main/java/org/bukkit/Location.java -@@ -638,6 +638,47 @@ public class Location implements Cloneable, ConfigurationSerializable { - return centerLoc; - } - -+ // Paper start - Add heightmap api -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) -+ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} -+ */ -+ @NotNull -+ public Location toHighestLocation() { -+ return this.toHighestLocation(HeightMap.WORLD_SURFACE); -+ } -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) -+ * @param heightmap The heightmap to use for finding the highest y location. -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap) -+ * @throws NullPointerException if {{@link #getWorld()}} is {@code null} -+ * @throws UnsupportedOperationException if {@link World#getHighestBlockYAt(int, int, com.destroystokyo.paper.HeightmapType)} does not support the specified heightmap -+ * @deprecated Use {@link org.bukkit.Location#toHighestLocation(HeightMap)} -+ */ -+ @NotNull -+ @Deprecated -+ public Location toHighestLocation(@NotNull final com.destroystokyo.paper.HeightmapType heightmap) { -+ final Location ret = this.clone(); -+ ret.setY(this.getWorld().getHighestBlockYAt(this, heightmap)); -+ return ret; -+ } -+ -+ /** -+ * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) -+ * @param heightMap The heightmap to use for finding the highest y location. -+ * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap) -+ */ -+ @NotNull -+ public Location toHighestLocation(@NotNull final HeightMap heightMap) { -+ final Location ret = this.clone(); -+ ret.setY(this.getWorld().getHighestBlockYAt(this, heightMap)); -+ return ret; -+ } -+ // Paper end -+ - /** - * Creates explosion at this location with given power - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 19060c7d9c74b9b2808103f3d5627444aece6ccb..f8e104d5e61e52c5fe658d7cda373f62424c7bea 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -160,6 +160,87 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public Block getHighestBlockAt(@NotNull Location location); - -+ // Paper start - Add heightmap API -+ /** -+ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. -+ *

-+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

-+ * -+ * @param x The block's x-coordinate. -+ * @param z The block's z-coordinate. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest block's y-coordinate at (x, z) that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(int, int, HeightMap)} -+ * -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ public int getHighestBlockYAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException; -+ -+ /** -+ * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions. -+ * Note that the y-coordinate of the specified location is ignored. -+ *

-+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

-+ * -+ * @param location The specified block coordinates. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest block's y-coordinate at {@code location} that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(Location, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ default int getHighestBlockYAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getHighestBlockYAt(location.getBlockX(), location.getBlockZ(), heightmap); -+ } -+ -+ /** -+ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. -+ *

-+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

-+ * @param x The block's x-coordinate. -+ * @param z The block's z-coordinate. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest {@link Block} at (x, z) that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(int, int, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ @NotNull -+ default Block getHighestBlockAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getBlockAt(x, this.getHighestBlockYAt(x, z, heightmap), z); -+ } -+ -+ /** -+ * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions. -+ * Note that the y-coordinate of the specified location is ignored. -+ *

-+ * implNote: Implementations are recommended to use an iterative search as a fallback before resorting to -+ * throwing an {@code UnsupportedOperationException}. -+ *

-+ * @param location The specified block coordinates. -+ * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType} -+ * @return The highest {@link Block} at {@code location} that matches the specified heightmap's conditions. -+ * @throws UnsupportedOperationException If the heightmap type is not supported. -+ * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(Location, HeightMap)} -+ * @see com.destroystokyo.paper.HeightmapType -+ */ -+ @Deprecated -+ @NotNull -+ default Block getHighestBlockAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ return this.getHighestBlockAt(location.getBlockX(), location.getBlockZ(), heightmap); -+ } -+ // Paper end -+ - /** - * Gets the highest coordinate corresponding to the {@link HeightMap} at the - * given coordinates. diff --git a/Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch b/Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index 2bbe92cbe988..000000000000 --- a/Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:19 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/org/bukkit/block/CreatureSpawner.java b/src/main/java/org/bukkit/block/CreatureSpawner.java -index cb447a4ad5a9dce7c98999a5d7fcd6111fc9b10e..5bbae759ce39d42886994e500fd9454ec328f804 100644 ---- a/src/main/java/org/bukkit/block/CreatureSpawner.java -+++ b/src/main/java/org/bukkit/block/CreatureSpawner.java -@@ -199,4 +199,30 @@ public interface CreatureSpawner extends TileState { - * @see #getSpawnRange() - */ - public void setSpawnRange(int spawnRange); -+ -+ // Paper start -+ /** -+ * Check if spawner is activated (a player is close enough) -+ * -+ * @return True if a player is close enough to activate it -+ */ -+ public boolean isActivated(); -+ -+ /** -+ * Resets the spawn delay timer within the min/max range -+ */ -+ public void resetTimer(); -+ -+ /** -+ * Sets the {@link EntityType} to {@link EntityType#DROPPED_ITEM} and sets the data to the given -+ * {@link org.bukkit.inventory.ItemStack ItemStack}. -+ *

-+ * {@link #setSpawnCount(int)} does not dictate the amount of items in the stack spawned, but rather how many -+ * stacks should be spawned. -+ * -+ * @param itemStack The item to spawn. Must not {@link org.bukkit.Material#isAir be air}. -+ * @see #setSpawnedType(EntityType) -+ */ -+ void setSpawnedItem(@NotNull org.bukkit.inventory.ItemStack itemStack); -+ // Paper end - } diff --git a/Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch b/Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch deleted file mode 100644 index 428810f1d8d3..000000000000 --- a/Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:41:28 -0700 -Subject: [PATCH] Add BlockSoundGroup interface - -This PR adds the getSoundGroup() method in Block which returns a BlockSoundGroup - -diff --git a/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8cf87d228a7006658d52ce0da16c2d74f4706545 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/BlockSoundGroup.java -@@ -0,0 +1,52 @@ -+package com.destroystokyo.paper.block; -+ -+import org.bukkit.Sound; -+import org.bukkit.block.Block; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Represents the sounds that a {@link Block} makes in certain situations -+ *

-+ * The sound group includes break, step, place, hit, and fall sounds. -+ */ -+public interface BlockSoundGroup { -+ /** -+ * Gets the sound that plays when breaking this block -+ * -+ * @return The break sound -+ */ -+ @NotNull -+ Sound getBreakSound(); -+ -+ /** -+ * Gets the sound that plays when stepping on this block -+ * -+ * @return The step sound -+ */ -+ @NotNull -+ Sound getStepSound(); -+ -+ /** -+ * Gets the sound that plays when placing this block -+ * -+ * @return The place sound -+ */ -+ @NotNull -+ Sound getPlaceSound(); -+ -+ /** -+ * Gets the sound that plays when hitting this block -+ * -+ * @return The hit sound -+ */ -+ @NotNull -+ Sound getHitSound(); -+ -+ /** -+ * Gets the sound that plays when this block falls -+ * -+ * @return The fall sound -+ */ -+ @NotNull -+ Sound getFallSound(); -+} -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index b090938f883c486e703cb7c036c47925f3016704..5e2aa4fb8cf8130df21d3172dd94e857317f7653 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -1,6 +1,7 @@ - package org.bukkit.block; - - import java.util.Collection; -+ - import org.bukkit.Chunk; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -560,4 +561,16 @@ public interface Block extends Metadatable { - */ - @NotNull - BoundingBox getBoundingBox(); -+ -+ // Paper start -+ /** -+ * Gets the {@link com.destroystokyo.paper.block.BlockSoundGroup} for this block. -+ *

-+ * This object contains the block, step, place, hit, and fall sounds. -+ * -+ * @return the sound group for this block -+ */ -+ @NotNull -+ com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch b/Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch deleted file mode 100644 index 24aacd2b2970..000000000000 --- a/Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 18 Oct 2019 17:39:05 +0100 -Subject: [PATCH] Increase custom payload channel message size - -Doubles the custom payload size limit imposed by bukkit, also creates a system -property to allow customizing the size `paper.maxCustomChannelName` - -diff --git a/src/main/java/org/bukkit/plugin/messaging/Messenger.java b/src/main/java/org/bukkit/plugin/messaging/Messenger.java -index 9d2c68c826f3b867d407e7f13c6394a899cc8ee8..682c77188436d696d4dafbc70cf131d5c921e94d 100644 ---- a/src/main/java/org/bukkit/plugin/messaging/Messenger.java -+++ b/src/main/java/org/bukkit/plugin/messaging/Messenger.java -@@ -24,7 +24,7 @@ public interface Messenger { - /** - * Represents the largest size that a Plugin Channel may be. - */ -- public static final int MAX_CHANNEL_SIZE = 64; -+ public static final int MAX_CHANNEL_SIZE = Integer.getInteger("paper.maxCustomChannelName", 64); // Paper - - /** - * Checks if the specified channel is a reserved name. diff --git a/Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch b/Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch deleted file mode 100644 index 1370e6830d6c..000000000000 --- a/Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:29 -0500 -Subject: [PATCH] Expose the internal current tick - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 1f5bcda86990d7c336db21d9c927bbf6b1b6d74d..3e2d644806233bb72f2f6637ec6edde4e3bcfdc9 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1823,6 +1823,10 @@ public final class Bukkit { - public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { - return server.createProfile(uuid, name); - } -+ -+ public static int getCurrentTick() { -+ return server.getCurrentTick(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 39188fcf95beff906c68a822f6aa5e19ad3ad08c..f107b5658b60e59e9d98bc86a0313f4da201c190 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1598,5 +1598,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); -+ -+ /** -+ * Get the current internal server tick -+ * -+ * @return Current tick -+ */ -+ int getCurrentTick(); - // Paper end - } diff --git a/Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch b/Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index f19bdcd5694f..000000000000 --- a/Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:31 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 7b78afe9281681cb9262fa044c1069a6121358eb..46917615ac4734bf5fa4ddea497132466eb5cc35 100644 ---- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -1,6 +1,8 @@ - package org.bukkit.event.entity; - - import java.util.List; -+ -+import org.bukkit.GameMode; - import org.bukkit.entity.Player; - import org.bukkit.inventory.ItemStack; - import org.jetbrains.annotations.NotNull; -@@ -18,6 +20,8 @@ public class PlayerDeathEvent extends EntityDeathEvent { - private boolean keepLevel = false; - private boolean keepInventory = false; - // Paper start -+ private boolean doExpDrop; -+ - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { - this(player, drops, droppedExp, 0, adventure$deathMessage, null); - } -@@ -27,12 +31,17 @@ public class PlayerDeathEvent extends EntityDeathEvent { - } - - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { -+ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, adventure$deathMessage, deathMessage, true); -+ } -+ -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage, boolean doExpDrop) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; - this.newLevel = newLevel; - this.deathMessage = deathMessage; - this.adventure$deathMessage = adventure$deathMessage; -+ this.doExpDrop = doExpDrop; - } - // Paper end - -@@ -47,6 +56,11 @@ public class PlayerDeathEvent extends EntityDeathEvent { - - @Deprecated // Paper - public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { -+ this(player, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, true); -+ } -+ -+ @Deprecated // Paper -+ public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage, boolean doExpDrop) { - super(player, drops, droppedExp); - this.newExp = newExp; - this.newTotalExp = newTotalExp; -@@ -88,6 +102,20 @@ public class PlayerDeathEvent extends EntityDeathEvent { - public List getItemsToKeep() { - return itemsToKeep; - } -+ -+ /** -+ * @return should experience be dropped from this death -+ */ -+ public boolean shouldDropExperience() { -+ return doExpDrop; -+ } -+ -+ /** -+ * @param doExpDrop sets if experience should be dropped from this death -+ */ -+ public void setShouldDropExperience(boolean doExpDrop) { -+ this.doExpDrop = doExpDrop; -+ } - // Paper end - - @NotNull diff --git a/Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch b/Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch deleted file mode 100644 index 7c52aaa44672..000000000000 --- a/Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:16 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index d4ba9c2b858204825d47fd6e91dab8c003df085a..f8c599718143fe638de422fd4625f353ee6c54ae 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -469,6 +469,18 @@ public interface Block extends Metadatable { - */ - boolean breakNaturally(@Nullable ItemStack tool); - -+ // Paper start -+ /** -+ * Breaks the block and spawns items as if a player had digged it with a -+ * specific tool -+ * -+ * @param tool The tool or item in hand used for digging -+ * @param triggerEffect Play the block break particle effect and sound -+ * @return true if the block was destroyed -+ */ -+ boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect); -+ // Paper end -+ - /** - * Simulate bone meal application to this block (if possible). - * diff --git a/Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch b/Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch deleted file mode 100644 index f605a2a11b28..000000000000 --- a/Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:08 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..085d77dde83d6ed13eb83f23cf3e51d380187c9c ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/ThrownEggHatchEvent.java -@@ -0,0 +1,115 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.Egg; -+import org.bukkit.entity.EntityType; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a thrown egg might hatch. -+ *

-+ * This event fires for all thrown eggs that may hatch, players, dispensers, etc. -+ */ -+public class ThrownEggHatchEvent extends Event { -+ private static final HandlerList handlers = new HandlerList(); -+ private final Egg egg; -+ private boolean hatching; -+ private EntityType hatchType; -+ private byte numHatches; -+ -+ public ThrownEggHatchEvent(@NotNull final Egg egg, final boolean hatching, final byte numHatches, @NotNull final EntityType hatchingType) { -+ this.egg = egg; -+ this.hatching = hatching; -+ this.numHatches = numHatches; -+ this.hatchType = hatchingType; -+ } -+ -+ /** -+ * Gets the egg involved in this event. -+ * -+ * @return the egg involved in this event -+ */ -+ @NotNull -+ public Egg getEgg() { -+ return egg; -+ } -+ -+ /** -+ * Gets whether the egg is hatching or not. Will be what the server -+ * would've done without interaction. -+ * -+ * @return boolean Whether the egg is going to hatch or not -+ */ -+ public boolean isHatching() { -+ return hatching; -+ } -+ -+ /** -+ * Sets whether the egg will hatch or not. -+ * -+ * @param hatching true if you want the egg to hatch, false if you want it -+ * not to -+ */ -+ public void setHatching(boolean hatching) { -+ this.hatching = hatching; -+ } -+ -+ /** -+ * Get the type of the mob being hatched (EntityType.CHICKEN by default) -+ * -+ * @return The type of the mob being hatched by the egg -+ */ -+ @NotNull -+ public EntityType getHatchingType() { -+ return hatchType; -+ } -+ -+ /** -+ * Change the type of mob being hatched by the egg -+ * -+ * @param hatchType The type of the mob being hatched by the egg -+ */ -+ public void setHatchingType(@NotNull EntityType hatchType) { -+ if (!hatchType.isSpawnable()) throw new IllegalArgumentException("Can't spawn that entity type from an egg!"); -+ this.hatchType = hatchType; -+ } -+ -+ /** -+ * Get the number of mob hatches from the egg. By default the number will -+ * be the number the server would've done -+ *

    -+ *
  • 7/8 chance of being 0 -+ *
  • 31/256 ~= 1/8 chance to be 1 -+ *
  • 1/256 chance to be 4 -+ *
-+ * -+ * @return The number of mobs going to be hatched by the egg -+ */ -+ public byte getNumHatches() { -+ return numHatches; -+ } -+ -+ /** -+ * Change the number of mobs coming out of the hatched egg -+ *

-+ * The boolean hatching will override this number. Ie. If hatching = -+ * false, this number will not matter -+ * -+ * @param numHatches The number of mobs coming out of the egg -+ */ -+ public void setNumHatches(byte numHatches) { -+ this.numHatches = numHatches; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0188-Entity-Jump-API.patch b/Spigot-API-Patches/0188-Entity-Jump-API.patch deleted file mode 100644 index 084181051767..000000000000 --- a/Spigot-API-Patches/0188-Entity-Jump-API.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:18 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f0067c2e953d18e1a33536980071ba3f0152ecb4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityJumpEvent.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when an entity jumps -+ *

-+ * Cancelling the event will stop the entity from jumping -+ */ -+public class EntityJumpEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ -+ public EntityJumpEvent(@NotNull LivingEntity entity) { -+ super(entity); -+ } -+ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 561db9d594633e3909fd6d69dad1dc2976928d58..a2f5639904881d9bef7d1550dbed810e4b17c8de 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -785,5 +785,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @return Whether or not this entity is using or charging an attack (Bow pulled back, drinking potion, eating food) - */ - boolean isHandRaised(); -+ -+ /** -+ * Get entity jump state. -+ *

-+ * Jump state will be true when the entity has been marked to jump. -+ * -+ * @return entity jump state. -+ */ -+ boolean isJumping(); -+ -+ /** -+ * Set entity jump state -+ *

-+ * Setting to true will mark the entity to jump. -+ *

-+ * Setting to false will unmark the entity to jump but will not stop a jump already in-progress. -+ * -+ * @param jumping entity jump state -+ */ -+ void setJumping(boolean jumping); - // Paper end - } diff --git a/Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch b/Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index f61bddb96089..000000000000 --- a/Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:34 +0100 -Subject: [PATCH] add hand to BlockMultiPlaceEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -index fe2ec79dd6084509cb8cbb8155a356f4162466fd..8460aa4f5e211fb0a6ab11f7487d38dba927e1da 100644 ---- a/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java -@@ -18,9 +18,17 @@ import org.jetbrains.annotations.NotNull; - public class BlockMultiPlaceEvent extends BlockPlaceEvent { - private final List states; - -+ @Deprecated // Paper - public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild) { -- super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild); -+ //Paper start - add hand to BlockMultiPlaceEvent -+ this(states, clicked, itemInHand, thePlayer, canBuild, org.bukkit.inventory.EquipmentSlot.HAND); -+ } -+ -+ -+ public BlockMultiPlaceEvent(@NotNull List states, @NotNull Block clicked, @NotNull ItemStack itemInHand, @NotNull Player thePlayer, boolean canBuild, @NotNull org.bukkit.inventory.EquipmentSlot hand) { -+ super(states.get(0).getBlock(), states.get(0), clicked, itemInHand, thePlayer, canBuild, hand); - this.states = ImmutableList.copyOf(states); -+ //Paper end - } - - /** diff --git a/Spigot-API-Patches/0190-Add-tick-times-API.patch b/Spigot-API-Patches/0190-Add-tick-times-API.patch deleted file mode 100644 index 17977550d777..000000000000 --- a/Spigot-API-Patches/0190-Add-tick-times-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:22:58 -0500 -Subject: [PATCH] Add tick times API - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 3e2d644806233bb72f2f6637ec6edde4e3bcfdc9..296c8fbb9239ab28f5ebbd4c322a3b9226a3ce11 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1578,6 +1578,25 @@ public final class Bukkit { - public static double[] getTPS() { - return server.getTPS(); - } -+ -+ /** -+ * Get a sample of the servers last tick times (in nanos) -+ * -+ * @return A sample of the servers last tick times (in nanos) -+ */ -+ @NotNull -+ public static long[] getTickTimes() { -+ return server.getTickTimes(); -+ } -+ -+ /** -+ * Get the average tick time (in millis) -+ * -+ * @return Average tick time (in millis) -+ */ -+ public static double getAverageTickTime() { -+ return server == null ? 0D : server.getAverageTickTime(); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index f107b5658b60e59e9d98bc86a0313f4da201c190..7195b480a16aa67f8e06fd3064b1072eafbb27b2 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1334,6 +1334,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - public double[] getTPS(); -+ -+ /** -+ * Get a sample of the servers last tick times (in nanos) -+ * -+ * @return A sample of the servers last tick times (in nanos) -+ */ -+ @NotNull -+ long[] getTickTimes(); -+ -+ /** -+ * Get the average tick time (in millis) -+ * -+ * @return Average tick time (in millis) -+ */ -+ double getAverageTickTime(); - // Paper end - - // Paper start diff --git a/Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch b/Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch deleted file mode 100644 index f98e0d9d7a6c..000000000000 --- a/Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Fri, 10 Apr 2020 21:24:35 -0400 -Subject: [PATCH] Expose MinecraftServer#isRunning - -This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading. - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 296c8fbb9239ab28f5ebbd4c322a3b9226a3ce11..86ac6702b3aeab1126b2b2879b87ef3883793d44 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1846,6 +1846,15 @@ public final class Bukkit { - public static int getCurrentTick() { - return server.getCurrentTick(); - } -+ -+ /** -+ * Checks if the server is in the process of being shutdown. -+ * -+ * @return true if server is in the process of being shutdown -+ */ -+ public static boolean isStopping() { -+ return server.isStopping(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7195b480a16aa67f8e06fd3064b1072eafbb27b2..16a74b834c4d4b907f9b11ccf9ef9804514df224 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1620,5 +1620,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return Current tick - */ - int getCurrentTick(); -+ -+ /** -+ * Checks if the server is in the process of being shutdown. -+ * -+ * @return true if server is in the process of being shutdown -+ */ -+ boolean isStopping(); - // Paper end - } diff --git a/Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch deleted file mode 100644 index 5ca0264ed8d1..000000000000 --- a/Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:38:59 -0400 -Subject: [PATCH] Disable Sync Events firing Async errors during shutdown - -This is how it use to behave on Paper, and this is totally destroying -the ability to try to shut the server down gracefully during the -shutdown process as events firing on the watchdog thread are throwing -errors. - -This isn't an issue on Spigot - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a1a805004941d67abb0b9aa1721e0370c45b5289..26685f59b235ea5b4c4fb7ae21acb5149edaa2b3 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -591,7 +591,7 @@ public final class SimplePluginManager implements PluginManager { - // Paper - replace callEvent by merging to below method - if (event.isAsynchronous() && server.isPrimaryThread()) { - throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); -- } else if (!event.isAsynchronous() && !server.isPrimaryThread()) { -+ } else if (!event.isAsynchronous() && !server.isPrimaryThread() && !server.isStopping() ) { - throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); - } - diff --git a/Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch b/Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch deleted file mode 100644 index be66a6a695a3..000000000000 --- a/Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Wed, 15 Apr 2020 01:24:55 -0400 -Subject: [PATCH] Make JavaPluginLoader thread-safe - - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index f26303315c9c93356f0b04440136855dd54d32b7..ce751577623eaad0f31e2eb7bf0842d1ab73e845 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -52,6 +52,8 @@ import org.yaml.snakeyaml.error.YAMLException; - public final class JavaPluginLoader implements PluginLoader { - final Server server; - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; -+ private final Map classLoadLock = new java.util.HashMap(); // Paper -+ private final Map classLoadLockCount = new java.util.HashMap(); // Paper - private final List loaders = new CopyOnWriteArrayList(); - private final LibraryLoader libraryLoader; - -@@ -201,12 +203,33 @@ public final class JavaPluginLoader implements PluginLoader { - - @Nullable - Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { -+ // Paper start - make MT safe -+ java.util.concurrent.locks.ReentrantReadWriteLock lock; -+ synchronized (classLoadLock) { -+ lock = classLoadLock.computeIfAbsent(name, (x) -> new java.util.concurrent.locks.ReentrantReadWriteLock()); -+ classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); -+ } -+ lock.writeLock().lock();try { -+ // Paper end - for (PluginClassLoader loader : loaders) { - try { - return loader.loadClass0(name, resolve, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, loader.plugin.getDescription())); - } catch (ClassNotFoundException cnfe) { - } - } -+ // Paper start - make MT safe -+ } finally { -+ synchronized (classLoadLock) { -+ lock.writeLock().unlock(); -+ if (classLoadLockCount.get(name) == 1) { -+ classLoadLock.remove(name); -+ classLoadLockCount.remove(name); -+ } else { -+ classLoadLockCount.compute(name, (x, prev) -> prev - 1); -+ } -+ } -+ } -+ // Paper end - return null; - } - diff --git a/Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch b/Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch deleted file mode 100644 index c156119b15f9..000000000000 --- a/Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Mon, 20 Jan 2020 21:38:34 +0100 -Subject: [PATCH] Add Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/ClientOption.java b/src/main/java/com/destroystokyo/paper/ClientOption.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9dad814cf51bc59ec5dfbf14474fea6557de38aa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ClientOption.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import org.bukkit.inventory.MainHand; -+ -+public final class ClientOption { -+ -+ public static final ClientOption SKIN_PARTS = new ClientOption<>(SkinParts.class); -+ public static final ClientOption CHAT_COLORS_ENABLED = new ClientOption<>(Boolean.class); -+ public static final ClientOption CHAT_VISIBILITY = new ClientOption<>(ChatVisibility.class); -+ public static final ClientOption LOCALE = new ClientOption<>(String.class); -+ public static final ClientOption MAIN_HAND = new ClientOption<>(MainHand.class); -+ public static final ClientOption VIEW_DISTANCE = new ClientOption<>(Integer.class); -+ -+ private final Class type; -+ -+ private ClientOption(@NotNull Class type) { -+ this.type = type; -+ } -+ -+ @NotNull -+ public Class getType() { -+ return type; -+ } -+ -+ public enum ChatVisibility { -+ FULL, -+ SYSTEM, -+ HIDDEN, -+ UNKNOWN -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/SkinParts.java b/src/main/java/com/destroystokyo/paper/SkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4a0c39405d4fbed457787e3c6ded4cc6591bc8c2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/SkinParts.java -@@ -0,0 +1,20 @@ -+package com.destroystokyo.paper; -+ -+public interface SkinParts { -+ -+ boolean hasCapeEnabled(); -+ -+ boolean hasJacketEnabled(); -+ -+ boolean hasLeftSleeveEnabled(); -+ -+ boolean hasRightSleeveEnabled(); -+ -+ boolean hasLeftPantsEnabled(); -+ -+ boolean hasRightPantsEnabled(); -+ -+ boolean hasHatsEnabled(); -+ -+ int getRaw(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f7f171c4ee0b8339b2f8fbe82442d65f17202f28 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerClientOptionsChangeEvent.java -@@ -0,0 +1,100 @@ -+package com.destroystokyo.paper.event.player; -+ -+import com.destroystokyo.paper.ClientOption; -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.SkinParts; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.MainHand; -+ -+/** -+ * Called when the player changes his client settings -+ */ -+public class PlayerClientOptionsChangeEvent extends PlayerEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private final String locale; -+ private final int viewDistance; -+ private final ChatVisibility chatVisibility; -+ private final boolean chatColors; -+ private final SkinParts skinparts; -+ private final MainHand mainHand; -+ -+ public PlayerClientOptionsChangeEvent(@NotNull Player player, @NotNull String locale, int viewDistance, @NotNull ChatVisibility chatVisibility, boolean chatColors, @NotNull SkinParts skinParts, @NotNull MainHand mainHand) { -+ super(player); -+ this.locale = locale; -+ this.viewDistance = viewDistance; -+ this.chatVisibility = chatVisibility; -+ this.chatColors = chatColors; -+ this.skinparts = skinParts; -+ this.mainHand = mainHand; -+ } -+ -+ @NotNull -+ public String getLocale() { -+ return locale; -+ } -+ -+ public boolean hasLocaleChanged() { -+ return !locale.equals(player.getClientOption(ClientOption.LOCALE)); -+ } -+ -+ public int getViewDistance() { -+ return viewDistance; -+ } -+ -+ public boolean hasViewDistanceChanged() { -+ return viewDistance != player.getClientOption(ClientOption.VIEW_DISTANCE); -+ } -+ -+ @NotNull -+ public ChatVisibility getChatVisibility() { -+ return chatVisibility; -+ } -+ -+ public boolean hasChatVisibilityChanged() { -+ return chatVisibility != player.getClientOption(ClientOption.CHAT_VISIBILITY); -+ } -+ -+ public boolean hasChatColorsEnabled() { -+ return chatColors; -+ } -+ -+ public boolean hasChatColorsEnabledChanged() { -+ return chatColors != player.getClientOption(ClientOption.CHAT_COLORS_ENABLED); -+ } -+ -+ @NotNull -+ public SkinParts getSkinParts() { -+ return skinparts; -+ } -+ -+ public boolean hasSkinPartsChanged() { -+ return skinparts.getRaw() != player.getClientOption(ClientOption.SKIN_PARTS).getRaw(); -+ } -+ -+ @NotNull -+ public MainHand getMainHand() { -+ return mainHand; -+ } -+ -+ public boolean hasMainHandChanged() { -+ return mainHand != player.getClientOption(ClientOption.MAIN_HAND); -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index ec87c78d0f9379511467b6d13b9cdfa4c19d15ca..2530c811f52f51d6338900221b4681c952c1c752 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2,6 +2,7 @@ package org.bukkit.entity; - - import java.net.InetSocketAddress; - import java.util.UUID; -+import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper - import net.kyori.adventure.text.Component; - import com.destroystokyo.paper.profile.PlayerProfile; // Paper -@@ -1909,6 +1910,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * Reset the cooldown counter to 0, effectively starting the cooldown period. - */ - void resetCooldown(); -+ -+ /** -+ * @return the client option value of the player -+ */ -+ @NotNull -+ T getClientOption(@NotNull ClientOption option); - // Paper end - - // Spigot start diff --git a/Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch b/Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index 15fa2db392ef..000000000000 --- a/Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:30:58 -0700 -Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ebdebe7b6ec6ed5aadc7ee925ba0147e61e6bc84 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerAttackEntityCooldownResetEvent.java -@@ -0,0 +1,76 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.entity.Entity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when processing a player's attack on an entity when the player's attack strength cooldown is reset -+ */ -+public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable { -+ -+ private final float cooledAttackStrength; -+ private boolean cancel = false; -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull private final Entity attackedEntity; -+ -+ public PlayerAttackEntityCooldownResetEvent(@NotNull Player who, @NotNull Entity attackedEntity, float cooledAttackStrength) { -+ super(who); -+ this.attackedEntity = attackedEntity; -+ this.cooledAttackStrength = cooledAttackStrength; -+ } -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static @NotNull HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

-+ * If an attack cooldown event is cancelled, the players attack strength will remain at the same value instead of being reset. -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ /** -+ * Cancelling this event will prevent the target player from having their cooldown reset from attacking this entity -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Get the value of the players cooldown attack strength when they initiated the attack -+ * -+ * @return returns the original player cooldown value -+ */ -+ public float getCooledAttackStrength() { -+ return cooledAttackStrength; -+ } -+ -+ /** -+ * Returns the entity attacked by the player -+ * -+ * @return the entity attacked by the player -+ */ -+ @NotNull -+ public Entity getAttackedEntity() { -+ return attackedEntity; -+ } -+} diff --git a/Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch deleted file mode 100644 index 800d5364e2f8..000000000000 --- a/Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wesley Smith -Date: Fri, 24 Apr 2020 18:30:26 -0400 -Subject: [PATCH] Fix Potion#toItemStack swapping the extended and upgraded - constructor values. - -While the Potion class is deprecated, it is still used in some plugins for cross-version potion handling. This issue has existed for a long time, and has caused many heaches along the way. - -diff --git a/src/main/java/org/bukkit/potion/Potion.java b/src/main/java/org/bukkit/potion/Potion.java -index b9dbbfd07dea643d7ac749822548571968adaa94..ac02ae4fc179483b4ac3d1adc41684a8426197eb 100644 ---- a/src/main/java/org/bukkit/potion/Potion.java -+++ b/src/main/java/org/bukkit/potion/Potion.java -@@ -267,7 +267,7 @@ public class Potion { - } - ItemStack itemStack = new ItemStack(material, amount); - PotionMeta meta = (PotionMeta) itemStack.getItemMeta(); -- meta.setBasePotionData(new PotionData(type, level == 2, extended)); -+ meta.setBasePotionData(new PotionData(type, extended, level == 2)); // Paper - fix swapped values - itemStack.setItemMeta(meta); - return itemStack; - } diff --git a/Spigot-API-Patches/0197-Villager-Restocks-API.patch b/Spigot-API-Patches/0197-Villager-Restocks-API.patch deleted file mode 100644 index e2dcfc314495..000000000000 --- a/Spigot-API-Patches/0197-Villager-Restocks-API.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:03 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index ef48ad9b28750ab7b33071f6b8e354e922731909..d1579153092c1b80350155110f1b9926b1a1ef57 100644 ---- a/src/main/java/org/bukkit/entity/Villager.java -+++ b/src/main/java/org/bukkit/entity/Villager.java -@@ -77,6 +77,20 @@ public interface Villager extends AbstractVillager { - */ - public void setVillagerExperience(int experience); - -+ // Paper start -+ /** -+ * Gets the amount of times a villager has restocked their trades today -+ * @return The amount of trade restocks. -+ */ -+ public int getRestocksToday(); -+ -+ /** -+ * Sets the amount of times a villager has restocked their trades today -+ * @param restocksToday new restock count -+ */ -+ public void setRestocksToday(int restocksToday); -+ // Paper end -+ - /** - * Attempts to make this villager sleep at the given location. - *
diff --git a/Spigot-API-Patches/0198-Expose-game-version.patch b/Spigot-API-Patches/0198-Expose-game-version.patch deleted file mode 100644 index 560d2370a182..000000000000 --- a/Spigot-API-Patches/0198-Expose-game-version.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Fri, 1 May 2020 17:39:02 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 86ac6702b3aeab1126b2b2879b87ef3883793d44..12214ce2af7363d40cf44652e46f05c5c1f2fe5a 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -118,6 +118,18 @@ public final class Bukkit { - return server.getBukkitVersion(); - } - -+ // Paper start - expose game version -+ /** -+ * Gets the version of game this server implements -+ * -+ * @return version of game -+ */ -+ @NotNull -+ public static String getMinecraftVersion() { -+ return server.getMinecraftVersion(); -+ } -+ // Paper end -+ - /** - * Gets a view of all currently logged in players. This {@linkplain - * Collections#unmodifiableCollection(Collection) view} is a reused -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 16a74b834c4d4b907f9b11ccf9ef9804514df224..360decea2eb6de4c567fa4cceea8f19bceff6823 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -97,6 +97,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public String getBukkitVersion(); - -+ // Paper start - expose game version -+ /** -+ * Gets the version of game this server implements -+ * -+ * @return version of game -+ */ -+ @NotNull -+ String getMinecraftVersion(); -+ // Paper end -+ - /** - * Gets a view of all currently logged in players. This {@linkplain - * Collections#unmodifiableCollection(Collection) view} is a reused diff --git a/Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch b/Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch deleted file mode 100644 index 3b3612713f65..000000000000 --- a/Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sat, 25 Apr 2020 23:31:28 +0200 -Subject: [PATCH] Add item slot convenience methods - - -diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java -index 4af562426aa38faeb6822abb0c878a3ac346b383..b95e563b5454306a9188ae3295309ee86a756477 100644 ---- a/src/main/java/org/bukkit/inventory/AnvilInventory.java -+++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java -@@ -49,4 +49,64 @@ public interface AnvilInventory extends Inventory { - * @param levels the maximum experience cost - */ - void setMaximumRepairCost(int levels); -+ -+ // Paper start -+ /** -+ * Gets the item in the left input slot. -+ * -+ * @return item in the first slot -+ */ -+ @Nullable -+ default ItemStack getFirstItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the item in the left input slot. -+ * -+ * @param firstItem item to set -+ */ -+ default void setFirstItem(@Nullable ItemStack firstItem) { -+ setItem(0, firstItem); -+ } -+ -+ /** -+ * Gets the item in the right input slot. -+ * -+ * @return item in the second slot -+ */ -+ @Nullable -+ default ItemStack getSecondItem() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the item in the right input slot. -+ * -+ * @param secondItem item to set -+ */ -+ default void setSecondItem(@Nullable ItemStack secondItem) { -+ setItem(1, secondItem); -+ } -+ -+ /** -+ * Gets the item in the result slot. -+ * -+ * @return item in the result slot -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(2); -+ } -+ -+ /** -+ * Sets the item in the result slot. -+ * Note that the client might not be able to take out the item if it does not match the input items. -+ * -+ * @param result item to set -+ */ -+ default void setResult(@Nullable ItemStack result) { -+ setItem(2, result); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -index 9048892c8768c6b4d6cea03da73339f13bfbe82e..1c750108f55a0a31ad23433b333e0ea486a63ff2 100644 ---- a/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -+++ b/src/main/java/org/bukkit/inventory/GrindstoneInventory.java -@@ -1,6 +1,68 @@ - package org.bukkit.inventory; - -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Interface to the inventory of a Grindstone. - */ --public interface GrindstoneInventory extends Inventory { } -+public interface GrindstoneInventory extends Inventory { -+ -+ // Paper start -+ /** -+ * Gets the upper input item. -+ * -+ * @return upper input item -+ */ -+ @Nullable -+ default ItemStack getUpperItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the upper input item. -+ * -+ * @param upperItem item to set -+ */ -+ default void setUpperItem(@Nullable ItemStack upperItem) { -+ setItem(0, upperItem); -+ } -+ -+ /** -+ * Gets the lower input item. -+ * -+ * @return lower input item -+ */ -+ @Nullable -+ default ItemStack getLowerItem() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the lower input item. -+ * -+ * @param lowerItem item to set -+ */ -+ default void setLowerItem(@Nullable ItemStack lowerItem) { -+ setItem(1, lowerItem); -+ } -+ -+ /** -+ * Gets the result. -+ * -+ * @return result -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(2); -+ } -+ -+ /** -+ * Sets the result. -+ * -+ * @param result item to set -+ */ -+ default void setResult(@Nullable ItemStack result) { -+ setItem(2, result); -+ } -+ // Paper end -+} -diff --git a/src/main/java/org/bukkit/inventory/LecternInventory.java b/src/main/java/org/bukkit/inventory/LecternInventory.java -index 4a0c43acc2714e095973eb78536041bb1a179ddc..acf2244f77133df53eb5f862c8e713c85192f13d 100644 ---- a/src/main/java/org/bukkit/inventory/LecternInventory.java -+++ b/src/main/java/org/bukkit/inventory/LecternInventory.java -@@ -11,4 +11,25 @@ public interface LecternInventory extends Inventory { - @Nullable - @Override - public Lectern getHolder(); -+ -+ // Paper start -+ /** -+ * Gets the lectern's held book. -+ * -+ * @return book set in the lectern -+ */ -+ @Nullable -+ default ItemStack getBook() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the lectern's held book. -+ * -+ * @param book the new book -+ */ -+ default void setBook(@Nullable ItemStack book) { -+ setItem(0, book); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/SmithingInventory.java b/src/main/java/org/bukkit/inventory/SmithingInventory.java -index 96d526b7b153e56c9a97de42ce3270b6638510e4..a41ca6bd2672db2810dd70c4925b84a4f081af05 100644 ---- a/src/main/java/org/bukkit/inventory/SmithingInventory.java -+++ b/src/main/java/org/bukkit/inventory/SmithingInventory.java -@@ -30,4 +30,44 @@ public interface SmithingInventory extends Inventory { - */ - @Nullable - Recipe getRecipe(); -+ -+ // Paper start -+ /** -+ * Gets the input equipment (first slot). -+ * -+ * @return input equipment item -+ */ -+ @Nullable -+ default ItemStack getInputEquipment() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the input equipment (first slot). -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputEquipment(@Nullable ItemStack itemStack) { -+ setItem(0, itemStack); -+ } -+ -+ /** -+ * Gets the input mineral (second slot). -+ * -+ * @return input mineral item -+ */ -+ @Nullable -+ default ItemStack getInputMineral() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the input mineral (second slot). -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputMineral(@Nullable ItemStack itemStack) { -+ setItem(1, itemStack); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/StonecutterInventory.java b/src/main/java/org/bukkit/inventory/StonecutterInventory.java -index dbb034fae3b8bfaf40e6341460e274c21e321a3b..e7a8e7188bf8b9840de56dc80c2b79d64a9389cb 100644 ---- a/src/main/java/org/bukkit/inventory/StonecutterInventory.java -+++ b/src/main/java/org/bukkit/inventory/StonecutterInventory.java -@@ -1,6 +1,49 @@ - package org.bukkit.inventory; - -+import org.jetbrains.annotations.Nullable; // Paper -+ - /** - * Interface to the inventory of a Stonecutter. - */ --public interface StonecutterInventory extends Inventory { } -+public interface StonecutterInventory extends Inventory { -+ -+ // Paper start -+ /** -+ * Gets the input item. -+ * -+ * @return input item -+ */ -+ @Nullable -+ default ItemStack getInputItem() { -+ return getItem(0); -+ } -+ -+ /** -+ * Sets the input item. -+ * -+ * @param itemStack item to set -+ */ -+ default void setInputItem(@Nullable ItemStack itemStack) { -+ setItem(0, itemStack); -+ } -+ -+ /** -+ * Gets the result item. -+ * -+ * @return result -+ */ -+ @Nullable -+ default ItemStack getResult() { -+ return getItem(1); -+ } -+ -+ /** -+ * Sets the result item. -+ * -+ * @param itemStack item to set -+ */ -+ default void setResult(@Nullable ItemStack itemStack) { -+ setItem(1, itemStack); -+ } -+ // Paper end -+} diff --git a/Spigot-API-Patches/0200-Add-Mob-Goal-API.patch b/Spigot-API-Patches/0200-Add-Mob-Goal-API.patch deleted file mode 100644 index a93d7da4fefc..000000000000 --- a/Spigot-API-Patches/0200-Add-Mob-Goal-API.patch +++ /dev/null @@ -1,481 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Fri, 3 Jan 2020 16:24:46 +0100 -Subject: [PATCH] Add Mob Goal API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c57c5416c88e2070a082403ab0dda9d7f08d2a57 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java -@@ -0,0 +1,66 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.EnumSet; -+ -+import org.bukkit.entity.Mob; -+ -+/** -+ * Represents an AI goal of an entity -+ */ -+public interface Goal { -+ -+ /** -+ * Checks if this goal should be activated -+ * -+ * @return if this goal should be activated -+ */ -+ boolean shouldActivate(); -+ -+ /** -+ * Checks if this goal should stay active, defaults to {@link Goal#shouldActivate()} -+ * -+ * @return if this goal should stay active -+ */ -+ default boolean shouldStayActive() { -+ return shouldActivate(); -+ } -+ -+ /** -+ * Called when this goal gets activated -+ */ -+ default void start() { -+ } -+ -+ /** -+ * Called when this goal gets stopped -+ */ -+ default void stop() { -+ } -+ -+ /** -+ * Called each tick the goal is activated -+ */ -+ default void tick() { -+ } -+ -+ /** -+ * A unique key that identifies this type of goal. Plugins should use their own namespace, not the minecraft -+ * namespace. Additionally, this key also specifies to what mobs this goal can be applied to -+ * -+ * @return the goal key -+ */ -+ @NotNull -+ GoalKey getKey(); -+ -+ /** -+ * Returns a list of all applicable flags for this goal.
-+ * -+ * This method is only called on construction. -+ * -+ * @return the subtypes. -+ */ -+ @NotNull -+ EnumSet getTypes(); -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9cd98c6fcfa3eb439d9013ef76ef4661175a0e5a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.google.common.base.Objects; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.StringJoiner; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.Mob; -+ -+/** -+ * -+ * Used to identify a Goal. Consists of a {@link NamespacedKey} and the type of mob the goal can be applied to -+ * -+ * @param the type of mob the goal can be applied to -+ */ -+public class GoalKey { -+ -+ private final Class entityClass; -+ private final NamespacedKey namespacedKey; -+ -+ private GoalKey(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { -+ this.entityClass = entityClass; -+ this.namespacedKey = namespacedKey; -+ } -+ -+ @NotNull -+ public Class getEntityClass() { -+ return entityClass; -+ } -+ -+ @NotNull -+ public NamespacedKey getNamespacedKey() { -+ return namespacedKey; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ GoalKey goalKey = (GoalKey) o; -+ return Objects.equal(entityClass, goalKey.entityClass) && -+ Objects.equal(namespacedKey, goalKey.namespacedKey); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(entityClass, namespacedKey); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", GoalKey.class.getSimpleName() + "[", "]") -+ .add("entityClass=" + entityClass) -+ .add("namespacedKey=" + namespacedKey) -+ .toString(); -+ } -+ -+ @NotNull -+ public static GoalKey of(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { -+ return new GoalKey<>(entityClass, namespacedKey); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7024c8f484d2460abf3abfe65a29771d814105ec ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+/** -+ * Represents the subtype of a goal. Used by minecraft to disable certain types of goals if needed. -+ */ -+public enum GoalType { -+ -+ MOVE, -+ LOOK, -+ JUMP, -+ TARGET, -+ /** -+ * Used to map vanilla goals, that are a behavior goal but don't have a type set... -+ */ -+ UNKNOWN_BEHAVIOR, -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef66a8f5e9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.Collection; -+ -+import org.bukkit.entity.Mob; -+ -+/** -+ * Represents a part of the "brain" of a mob. It tracks all tasks (running or not), allows adding and removing goals -+ */ -+public interface MobGoals { -+ -+ void addGoal(@NotNull T mob, int priority, @NotNull Goal goal); -+ -+ void removeGoal(@NotNull T mob, @NotNull Goal goal); -+ -+ void removeAllGoals(@NotNull T mob); -+ -+ void removeAllGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ void removeGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ boolean hasGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ @Nullable -+ Goal getGoal(@NotNull T mob, @NotNull GoalKey key); -+ -+ @NotNull -+ Collection> getGoals(@NotNull T mob, @NotNull GoalKey key); -+ -+ @NotNull -+ Collection> getAllGoals(@NotNull T mob); -+ -+ @NotNull -+ Collection> getAllGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getRunningGoals(@NotNull T mob); -+ -+ @NotNull -+ Collection> getRunningGoals(@NotNull T mob, @NotNull GoalType type); -+ -+ @NotNull -+ Collection> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type); -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b42091752981a1f309ab350e9a394092cb334824 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java -@@ -0,0 +1,209 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.destroystokyo.paper.entity.RangedEntity; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.*; -+ -+/** -+ * Represents a vanilla goal. Plugins should never implement this.
-+ * Generated by VanillaPathfinderTest in paper-server -+ */ -+public interface VanillaGoal extends Goal { -+ -+ GoalKey BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack")); -+ GoalKey BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry")); -+ GoalKey BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive")); -+ GoalKey BEE_GO_TO_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_hive")); -+ GoalKey BEE_GO_TO_KNOWN_FLOWER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_go_to_known_flower")); -+ GoalKey BEE_GROW_CROP = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_grow_crop")); -+ GoalKey BEE_HURT_BY_OTHER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_hurt_by_other")); -+ GoalKey BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive")); -+ GoalKey BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate")); -+ GoalKey BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander")); -+ GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); -+ GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); -+ GoalKey CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity")); -+ GoalKey CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner")); -+ GoalKey DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure")); -+ GoalKey DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player")); -+ GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); -+ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); -+ GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); -+ GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); -+ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); -+ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); -+ GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); -+ GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); -+ GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); -+ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); -+ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); -+ GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); -+ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); -+ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); -+ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); -+ GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); -+ GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); -+ GoalKey FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed")); -+ GoalKey FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries")); -+ GoalKey FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float")); -+ GoalKey FOX_FOLLOW_PARENT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_follow_parent")); -+ GoalKey FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player")); -+ GoalKey FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack")); -+ GoalKey FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic")); -+ GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); -+ GoalKey FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce")); -+ GoalKey FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items")); -+ GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); -+ GoalKey FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village")); -+ GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); -+ GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); -+ GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); -+ GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); -+ GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); -+ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); -+ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); -+ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); -+ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); -+ GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); -+ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); -+ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); -+ GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); -+ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); -+ GoalKey OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity")); -+ GoalKey OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt")); -+ GoalKey PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack")); -+ GoalKey PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid")); -+ GoalKey PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed")); -+ GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); -+ GoalKey PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back")); -+ GoalKey PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player")); -+ GoalKey PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic")); -+ GoalKey PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll")); -+ GoalKey PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit")); -+ GoalKey PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze")); -+ GoalKey PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player")); -+ GoalKey PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy")); -+ GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor")); -+ GoalKey PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); -+ GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); -+ GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); -+ GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); -+ GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); -+ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); -+ GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); -+ GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); -+ GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); -+ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); -+ GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); -+ GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); -+ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); -+ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); -+ GoalKey RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack")); -+ GoalKey SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack")); -+ GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); -+ GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); -+ GoalKey SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek")); -+ GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); -+ GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); -+ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); -+ GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); -+ GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); -+ GoalKey SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction")); -+ GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); -+ GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); -+ GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); -+ GoalKey STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava")); -+ GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); -+ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); -+ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); -+ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); -+ GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); -+ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); -+ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); -+ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); -+ GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); -+ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); -+ GoalKey VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack")); -+ GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); -+ GoalKey VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move")); -+ GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); -+ GoalKey VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door")); -+ GoalKey VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack")); -+ GoalKey VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack")); -+ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); -+ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); -+ GoalKey ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg")); -+ GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); -+ GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); -+ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); -+ GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); -+ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); -+ GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); -+ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); -+ GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); -+ GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); -+ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); -+ GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); -+ GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); -+ GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); -+ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); -+ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); -+ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); -+ GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); -+ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); -+ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); -+ GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); -+ GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); -+ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); -+ GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); -+ GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); -+ GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); -+ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); -+ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); -+ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); -+ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); -+ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); -+ GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); -+ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); -+ GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); -+ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); -+ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); -+ GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); -+ GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); -+ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); -+ GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); -+ GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); -+ GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); -+ GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); -+ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); -+ GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); -+ GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); -+ GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); -+ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); -+ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); -+ GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); -+ GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); -+ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); -+ GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); -+ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); -+ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); -+ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); -+ GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); -+ GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); -+ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); -+ GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); -+ GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 12214ce2af7363d40cf44652e46f05c5c1f2fe5a..77d352450f6bc5293efec3b75e08b857e2626fe7 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1867,6 +1867,16 @@ public final class Bukkit { - public static boolean isStopping() { - return server.isStopping(); - } -+ -+ /** -+ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager -+ * -+ * @return the mob goals manager -+ */ -+ @NotNull -+ public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return server.getMobGoals(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 360decea2eb6de4c567fa4cceea8f19bceff6823..4b1f515f2228f16c1ce793bd45510243d758236f 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1637,5 +1637,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - * @return true if server is in the process of being shutdown - */ - boolean isStopping(); -+ -+ /** -+ * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager -+ * -+ * @return the mob goals manager -+ */ -+ @NotNull -+ com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); - // Paper end - } diff --git a/Spigot-API-Patches/0201-World-view-distance-api.patch b/Spigot-API-Patches/0201-World-view-distance-api.patch deleted file mode 100644 index 17a9a94f12fc..000000000000 --- a/Spigot-API-Patches/0201-World-view-distance-api.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:28:01 -0700 -Subject: [PATCH] World view distance api - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 7bf85151efddcbd561afb0fb2d423aa97ac176c1..61dfb057d94d89477d11b9e8d4be7c16032e25a9 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -3447,6 +3447,34 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - int getViewDistance(); - // Spigot end - -+ // Paper start - view distance api -+ /** -+ * Sets the view distance for this world. -+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setViewDistance(int viewDistance); -+ -+ /** -+ * Returns the no-tick view distance for this world. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @return The no-tick view distance for this world. -+ */ -+ int getNoTickViewDistance(); -+ -+ /** -+ * Sets the no-tick view distance for this world. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setNoTickViewDistance(int viewDistance); -+ // Paper end - view distance api -+ - // Spigot start - public class Spigot { - diff --git a/Spigot-API-Patches/0202-Add-villager-reputation-API.patch b/Spigot-API-Patches/0202-Add-villager-reputation-API.patch deleted file mode 100644 index cef4ea602789..000000000000 --- a/Spigot-API-Patches/0202-Add-villager-reputation-API.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:13:49 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1cc9ef255df888cb7dd7f7f2c5014e818d1be613 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/Reputation.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.entity.villager; -+ -+import com.google.common.base.Preconditions; -+import java.util.Map; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A reputation score for a player on a villager. -+ */ -+public final class Reputation { -+ private static final ReputationType[] REPUTATION_TYPES = ReputationType.values(); // Avoid allocation -+ @NotNull -+ private final int[] reputation; -+ -+ public Reputation() { -+ this(new int[REPUTATION_TYPES.length]); -+ } -+ -+ // Package level to avoid plugins creating reputations with "magic values". -+ Reputation(@NotNull int[] reputation) { -+ this.reputation = reputation; -+ } -+ -+ public Reputation(@NotNull final Map reputation) { -+ this(); -+ Preconditions.checkNotNull(reputation, "reputation cannot be null"); -+ -+ for (Map.Entry entry : reputation.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ /** -+ * Gets the reputation value for a specific {@link ReputationType}. -+ * -+ * @param type The {@link ReputationType type} of reputation to get. -+ * @return The value of the {@link ReputationType type}. -+ */ -+ public int getReputation(@NotNull ReputationType type) { -+ Preconditions.checkNotNull(type, "the reputation type cannot be null"); -+ return reputation[type.ordinal()]; -+ } -+ -+ /** -+ * Sets the reputation value for a specific {@link ReputationType}. -+ * -+ * @param type The {@link ReputationType type} of reputation to set. -+ * @param value The value of the {@link ReputationType type}. -+ */ -+ public void setReputation(@NotNull ReputationType type, int value) { -+ Preconditions.checkNotNull(type, "the reputation type cannot be null"); -+ reputation[type.ordinal()] = value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5600fcdc9795a9f49091db48d73bbd4964b8b737 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationType.java -@@ -0,0 +1,36 @@ -+package com.destroystokyo.paper.entity.villager; -+ -+/** -+ * A type of reputation gained with a {@link org.bukkit.entity.Villager Villager}. -+ *

-+ * All types but {@link #MAJOR_POSITIVE} are shared to other villagers. -+ */ -+public enum ReputationType { -+ /** -+ * A gossip with a majorly negative effect. This is only gained through killing a nearby -+ * villager. -+ */ -+ MAJOR_NEGATIVE, -+ -+ /** -+ * A gossip with a minor negative effect. This is only gained through damaging a villager. -+ */ -+ MINOR_NEGATIVE, -+ -+ /** -+ * A gossip with a minor positive effect. This is only gained through curing a zombie -+ * villager. -+ */ -+ MINOR_POSITIVE, -+ -+ /** -+ * A gossip with a major positive effect. This is only gained through curing a zombie -+ * villager. -+ */ -+ MAJOR_POSITIVE, -+ -+ /** -+ * A gossip with a minor positive effect. This is only gained through trading with a villager. -+ */ -+ TRADING, -+} -diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java -index d1579153092c1b80350155110f1b9926b1a1ef57..c8777a476e38ef5e72b6709761990a339eb43d2b 100644 ---- a/src/main/java/org/bukkit/entity/Villager.java -+++ b/src/main/java/org/bukkit/entity/Villager.java -@@ -1,10 +1,13 @@ - package org.bukkit.entity; - - import java.util.Locale; -+import java.util.Map; // Paper -+import java.util.UUID; // Paper - import org.bukkit.Keyed; - import org.bukkit.Location; - import org.bukkit.NamespacedKey; - import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; // Paper - - /** - * Represents a villager NPC -@@ -224,4 +227,50 @@ public interface Villager extends AbstractVillager { - return key; - } - } -+ -+ // Paper start - Add villager reputation API -+ /** -+ * Get the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} -+ * for a specific player by {@link UUID}. -+ * -+ * @param uniqueId The {@link UUID} of the player to get the reputation of. -+ * @return The player's copied reputation with this villager. -+ */ -+ @Nullable -+ public com.destroystokyo.paper.entity.villager.Reputation getReputation(@NotNull UUID uniqueId); -+ -+ /** -+ * Get all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ * -+ * @return All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} for all players -+ * in a copied map. -+ */ -+ @NotNull -+ public Map getReputations(); -+ -+ /** -+ * Set the {@link com.destroystokyo.paper.entity.villager.Reputation reputation} -+ * for a specific player by {@link UUID}. -+ * -+ * @param uniqueId The {@link UUID} of the player to set the reputation of. -+ * @param reputation The {@link com.destroystokyo.paper.entity.villager.Reputation reputation} to set. -+ */ -+ public void setReputation(@NotNull UUID uniqueId, @NotNull com.destroystokyo.paper.entity.villager.Reputation reputation); -+ -+ /** -+ * Set all {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ * -+ * @param reputations All {@link com.destroystokyo.paper.entity.villager.Reputation reputations} -+ * for all players mapped by their {@link UUID unique IDs}. -+ */ -+ public void setReputations(@NotNull Map reputations); -+ -+ /** -+ * Clear all reputations from this villager. This removes every single -+ * reputation regardless of its impact and the player associated. -+ */ -+ public void clearReputations(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0203-Spawn-Reason-API.patch b/Spigot-API-Patches/0203-Spawn-Reason-API.patch deleted file mode 100644 index 0ee08ee9965b..000000000000 --- a/Spigot-API-Patches/0203-Spawn-Reason-API.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 10 Apr 2014 23:18:28 -0400 -Subject: [PATCH] Spawn Reason API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 476184db904d8a2e1347e1219e8ba196bf4da5cb..c1010e314144a65e12eaf5514d639a87f45891a9 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -1,6 +1,8 @@ - package org.bukkit; - - import java.io.File; -+ -+import org.bukkit.event.entity.CreatureSpawnEvent; - import org.bukkit.generator.ChunkGenerator; - - import java.util.ArrayList; -@@ -2249,6 +2251,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @NotNull - public T spawn(@NotNull Location location, @NotNull Class clazz) throws IllegalArgumentException; - -+ // Paper start -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { -+ return spawn(location, clazz, reason, null); -+ } -+ - /** - * Spawn an entity of a specific class at the given {@link Location}, with - * the supplied function run before the entity is added to the world. -@@ -2266,7 +2274,28 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * {@link Entity} requested cannot be spawned - */ - @NotNull -- public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException; -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.CUSTOM, function); -+ } -+ -+ @NotNull -+ public default T spawn(@NotNull Location location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) throws IllegalArgumentException { -+ return spawn(location, clazz, function, reason); -+ } -+ -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, null); -+ } -+ -+ @NotNull -+ public default Entity spawnEntity(@NotNull Location loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer function) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, function); -+ } -+ -+ @NotNull -+ public T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException; -+ // Paper end - - /** - * Spawn a {@link FallingBlock} entity at the given {@link Location} of diff --git a/Spigot-API-Patches/0204-Potential-bed-API.patch b/Spigot-API-Patches/0204-Potential-bed-API.patch deleted file mode 100644 index b8b1e2519a89..000000000000 --- a/Spigot-API-Patches/0204-Potential-bed-API.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Sun, 10 May 2020 23:06:41 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -getPotentialBedLocation - Gets the last known location of a player's bed. This does not preform any check if the bed is still valid and does not load any chunks. - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 3418133d07250a7fd50caad8d97924b86fb30bad..b09d12390d5f77330ac84452e0fee63a169bd01f 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -240,6 +240,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public int getSleepTicks(); - -+ -+ // Paper start - Potential bed api -+ /** -+ * Gets the Location of the player's bed, null if they have not slept -+ * in one. This method will not attempt to validate if the current bed -+ * is still valid. -+ * -+ * @return Bed Location if has slept in one, otherwise null. -+ */ -+ @Nullable -+ public Location getPotentialBedLocation(); -+ // Paper end -+ - /** - * Attempts to make the entity sleep at the given location. - *
diff --git a/Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch b/Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch deleted file mode 100644 index 4603ec725546..000000000000 --- a/Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 27 Apr 2020 12:31:59 +0200 -Subject: [PATCH] Prioritise own classes where possible - -This adds the server property `Paper.DisableClassPrioritization` to disable -prioritization of own classes for plugins' classloaders. - -This value is by default not present, and this will therefore break any -plugins which abuse behaviour related to not using their own classes -while still loading their own. This is often an issue with failing to -relocate or shade properly, such as when shading plugin APIs like Vault. - -A plugin's classloader will first look in the same jar as it is loading -in for a requested class, then load it. It does not re-use other -plugins' classes if it has the chance to avoid doing so. - -If a class is not found in the same jar as it is loading for and it does -find it elsewhere, it will still choose the class elsewhere. This is -intended behaviour, as it will only prioritise classes it has in its own -jar, no other plugins' classes will be prioritised in any other order -than the one they were registered in. - -The patch in general terms just loads the class in the plugin's jar -before it starts looking elsewhere for it. - -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index ce751577623eaad0f31e2eb7bf0842d1ab73e845..31793f46e5623729dfb4048e901f274082f57826 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -51,6 +51,7 @@ import org.yaml.snakeyaml.error.YAMLException; - */ - public final class JavaPluginLoader implements PluginLoader { - final Server server; -+ private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper - private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; - private final Map classLoadLock = new java.util.HashMap(); // Paper - private final Map classLoadLockCount = new java.util.HashMap(); // Paper -@@ -203,6 +204,11 @@ public final class JavaPluginLoader implements PluginLoader { - - @Nullable - Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { -+ // Paper start - prioritize self -+ return getClassByName(name, resolve, description, null); -+ } -+ Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description, PluginClassLoader requester) { -+ // Paper end - // Paper start - make MT safe - java.util.concurrent.locks.ReentrantReadWriteLock lock; - synchronized (classLoadLock) { -@@ -210,6 +216,13 @@ public final class JavaPluginLoader implements PluginLoader { - classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); - } - lock.writeLock().lock();try { -+ // Paper start - prioritize self -+ if (!DISABLE_CLASS_PRIORITIZATION && requester != null) { -+ try { -+ return requester.loadClass0(name, false, false, ((SimplePluginManager) server.getPluginManager()).isTransitiveDepend(description, requester.getDescription())); -+ } catch (ClassNotFoundException cnfe) {} -+ } -+ // Paper end - // Paper end - for (PluginClassLoader loader : loaders) { - try { -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 22abd85da592c79e312928de596e5d552a45ef12..cfa408e560d85311b474562a6d3860363727eff0 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - public JavaPlugin getPlugin() { return plugin; } // Spigot - private final JavaPluginLoader loader; - private final Map> classes = new ConcurrentHashMap>(); -- private final PluginDescriptionFile description; -+ private final PluginDescriptionFile description; PluginDescriptionFile getDescription() { return description; } // Paper - private final File dataFolder; - private final File file; - private final JarFile jar; -@@ -117,7 +117,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - } - - if (checkGlobal) { -- Class result = loader.getClassByName(name, resolve, description); -+ Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - - if (result != null) { - PluginDescriptionFile provider = ((PluginClassLoader) result.getClassLoader()).description; diff --git a/Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch b/Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 8ffb283fa6ce..000000000000 --- a/Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:31 +0200 -Subject: [PATCH] Add Raw Byte ItemStack Serialization - -Serializes using NBT which is safer for server data migrations than bukkits format. - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index d6897f43a0692e031bed8a212d9a637ef548cc60..e348034288c74ab80360086d71f0b7f61551df24 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -97,5 +97,9 @@ public interface UnsafeValues { - static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { - return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); - } -+ -+ byte[] serializeItem(ItemStack item); -+ -+ ItemStack deserializeItem(byte[] data); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index bf39989dbe08c93120d75bed6281ae75c460afca..15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -628,6 +628,30 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); - } - -+ /** -+ * Deserializes this itemstack from raw NBT bytes. NBT is safer for data migrations as it will -+ * use the built in data converter instead of bukkits dangerous serialization system. -+ * -+ * This expects that the DataVersion was stored on the root of the Compound, as saved from -+ * the {@link #serializeAsBytes()} API returned. -+ * @param bytes bytes representing an item in NBT -+ * @return ItemStack migrated to this version of Minecraft if needed. -+ */ -+ @NotNull -+ public static ItemStack deserializeBytes(@NotNull byte[] bytes) { -+ return org.bukkit.Bukkit.getUnsafe().deserializeItem(bytes); -+ } -+ -+ /** -+ * Serializes this itemstack to raw bytes in NBT. NBT is safer for data migrations as it will -+ * use the built in data converter instead of bukkits dangerous serialization system. -+ * @return bytes representing this item in NBT. -+ */ -+ @NotNull -+ public byte[] serializeAsBytes() { -+ return org.bukkit.Bukkit.getUnsafe().serializeItem(this); -+ } -+ - /** - * Gets the Display name as seen in the Client. - * Currently the server only supports the English language. To override this, diff --git a/Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch b/Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch deleted file mode 100644 index 43903ca4e091..000000000000 --- a/Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 31 May 2020 15:26:17 +0100 -Subject: [PATCH] Provide a useful PluginClassLoader#toString - -There are several cases where the plugin classloader may be dumped to the logs, -however, this provides no indication of the owner of the classloader, making -these messages effectively useless, this patch rectifies this - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index e7a8a221a23d2adc497afd21e512eecba4c63a6b..11e5618ff66385574ba04db0942a75227cf8eb0f 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -226,4 +226,16 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); - } -+ -+ // Paper start -+ @Override -+ public String toString() { -+ JavaPlugin currPlugin = plugin != null ? plugin : pluginInit; -+ return "PluginClassLoader{" + -+ "plugin=" + currPlugin + -+ ", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) + -+ ", url=" + file + -+ '}'; -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch b/Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index 5b633e50af54..000000000000 --- a/Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:16 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/block/DoubleChest.java b/src/main/java/org/bukkit/block/DoubleChest.java -index 83a4642119c3f33749e04c774cf2b39839f797e2..a39d2f1acbbd84ae0e2cf29f85594e09e55e9355 100644 ---- a/src/main/java/org/bukkit/block/DoubleChest.java -+++ b/src/main/java/org/bukkit/block/DoubleChest.java -@@ -34,6 +34,18 @@ public class DoubleChest implements InventoryHolder { - return inventory.getRightSide().getHolder(); - } - -+ // Paper start - getHolder without snapshot -+ @Nullable -+ public InventoryHolder getLeftSide(boolean useSnapshot) { -+ return inventory.getLeftSide().getHolder(useSnapshot); -+ } -+ -+ @Nullable -+ public InventoryHolder getRightSide(boolean useSnapshot) { -+ return inventory.getRightSide().getHolder(useSnapshot); -+ } -+ // Paper end -+ - @NotNull - public Location getLocation() { - return getInventory().getLocation(); -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 9c6a5bdac8c3ab682bbfae04ff24b76a62bc2883..6386206188e820206bb1a9f516b5e194fdc9d952 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -384,6 +384,17 @@ public interface Inventory extends Iterable { - @Nullable - public InventoryHolder getHolder(); - -+ // Paper start - getHolder without snapshot -+ /** -+ * Gets the block or entity belonging to the open inventory -+ * -+ * @param useSnapshot Create a snapshot if the holder is a tile entity -+ * @return The holder of the inventory; null if it has no holder. -+ */ -+ @Nullable -+ public InventoryHolder getHolder(boolean useSnapshot); -+ // Paper end -+ - @NotNull - @Override - public ListIterator iterator(); diff --git a/Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch b/Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch deleted file mode 100644 index e718e0e59829..000000000000 --- a/Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Fri, 22 May 2020 13:35:21 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java -index e8e56e89e32d84af0639fe2e9b0eeabd747b6007..b1d8007eed489aa061c1a6813bcdafc101231e56 100644 ---- a/src/main/java/org/bukkit/entity/AbstractArrow.java -+++ b/src/main/java/org/bukkit/entity/AbstractArrow.java -@@ -143,6 +143,14 @@ public interface AbstractArrow extends Projectile { - } - - // Paper start -+ /** -+ * Gets the ItemStack for this arrow. -+ * -+ * @return The ItemStack, as if a player picked up the arrow -+ */ -+ @NotNull -+ org.bukkit.inventory.ItemStack getItemStack(); -+ - /** - * Gets the {@link PickupRule} for this arrow. - * diff --git a/Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index 93bd233b8579..000000000000 --- a/Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LordKorea -Date: Mon, 11 May 2020 22:38:10 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7fa937d339ee98ad308deebb523fead6522eb262 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerRecipeBookClickEvent.java -@@ -0,0 +1,84 @@ -+package com.destroystokyo.paper.event.player; -+ -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player clicks a recipe in the recipe book -+ */ -+public class PlayerRecipeBookClickEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancel = false; -+ @NotNull private NamespacedKey recipe; -+ private boolean makeAll; -+ -+ public PlayerRecipeBookClickEvent(@NotNull Player player, @NotNull NamespacedKey recipe, boolean makeAll) { -+ super(player); -+ this.recipe = recipe; -+ this.makeAll = makeAll; -+ } -+ -+ /** -+ * Gets the namespaced key of the recipe that was clicked by the player -+ * -+ * @return The namespaced key of the recipe -+ */ -+ @NotNull -+ public NamespacedKey getRecipe() { -+ return recipe; -+ } -+ -+ /** -+ * Changes what recipe is requested. This sets the requested recipe to the recipe with the given key -+ * -+ * @param recipe The key of the recipe that should be requested -+ */ -+ public void setRecipe(@NotNull NamespacedKey recipe) { -+ this.recipe = recipe; -+ } -+ -+ /** -+ * Gets a boolean which indicates whether or not the player requested to make the maximum amount of results. This is -+ * true if shift is pressed while the recipe is clicked in the recipe book -+ * -+ * @return {@code true} if shift is pressed while the recipe is clicked -+ */ -+ public boolean isMakeAll() { -+ return makeAll; -+ } -+ -+ /** -+ * Sets whether or not the maximum amount of results should be made. If this is true, the request is handled as if -+ * the player had pressed shift while clicking on the recipe -+ * -+ * @param makeAll {@code true} if the request should attempt to make the maximum amount of results -+ */ -+ public void setMakeAll(boolean makeAll) { -+ this.makeAll = makeAll; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch b/Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch deleted file mode 100644 index 1b51f21c6982..000000000000 --- a/Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 6 Jun 2020 18:13:16 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index 01b462fccce71cef3398dd43944046f322b8e57e..f093f991f1fedd20fcef041b093398250b7fb286 100644 ---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -@@ -5,6 +5,7 @@ import java.util.Collection; - import java.util.List; - import java.util.Map; - import java.util.Set; -+import net.kyori.adventure.text.Component; - import org.bukkit.attribute.Attribute; - import org.bukkit.attribute.AttributeModifier; - import org.bukkit.configuration.serialization.ConfigurationSerializable; -@@ -62,6 +63,20 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @NotNull - String getDisplayName(); - -+ // Paper start -+ /** -+ * Gets the display name that is set. -+ *

-+ * Plugins should check that hasDisplayName() returns true -+ * before calling this method. -+ * -+ * @return the display name that is set -+ * @deprecated use {@link #displayName()} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent(); -+ // Paper end - /** - * Sets the display name. - * -@@ -71,6 +86,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Deprecated // Paper - void setDisplayName(@Nullable String name); - -+ // Paper start -+ /** -+ * Sets the display name. -+ * -+ * @param component the name component to set -+ * @deprecated use {@link #displayName(Component)} -+ */ -+ @Deprecated -+ void setDisplayNameComponent(@Nullable net.md_5.bungee.api.chat.BaseComponent[] component); -+ // Paper end - /** - * Checks for existence of a localized name. - * -@@ -134,6 +159,19 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Nullable - List getLore(); - -+ /** -+ * Gets the lore that is set. -+ *

-+ * Plugins should check if hasLore() returns true before -+ * calling this method. -+ * -+ * @return a list of lore that is set -+ * @deprecated use {@link #lore()} -+ */ -+ @Nullable -+ @Deprecated -+ List getLoreComponents(); -+ - /** - * Sets the lore for this item. - * Removes lore when given null. -@@ -144,6 +182,16 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste - @Deprecated // Paper - void setLore(@Nullable List lore); - -+ /** -+ * Sets the lore for this item. -+ * Removes lore when given null. -+ * -+ * @param lore the lore that will be set -+ * @deprecated use {@link #lore(List)} -+ */ -+ @Deprecated -+ void setLoreComponents(@Nullable List lore); -+ - /** - * Checks for existence of custom model data. - *

diff --git a/Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch deleted file mode 100644 index 747470a546b5..000000000000 --- a/Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:05:54 -0700 -Subject: [PATCH] added 2 new TargetReasons for 1.16 mob behavior - - -diff --git a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -index dee186e99463a56394bbc2039d1e763d109125b9..601904150156d475c18286b485f3409307a75950 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java -@@ -159,6 +159,14 @@ public class EntityTargetEvent extends EntityEvent implements Cancellable { - * as wheat in it's hand. - */ - TEMPT, -+ /** -+ * When the target is in a different dimension -+ */ -+ TARGET_OTHER_LEVEL, // Paper -+ /** -+ * When the target is in creative or spectator mode, or the gamemode is peaceful, or other reasons -+ */ -+ TARGET_INVALID, // Paper - /** - * A currently unknown reason for the entity changing target. - */ diff --git a/Spigot-API-Patches/0213-Add-entity-liquid-API.patch b/Spigot-API-Patches/0213-Add-entity-liquid-API.patch deleted file mode 100644 index c13d4c2cb36a..000000000000 --- a/Spigot-API-Patches/0213-Add-entity-liquid-API.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:33 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 2622a2f5c9e2cb43aff7ef9eac2dcdb3fd8fad04..75cebfca7b436ef30b718bba7e0566d047e5c61a 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -668,5 +668,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); -+ -+ /** -+ * Check if entity is in rain -+ */ -+ public boolean isInRain(); -+ -+ /** -+ * Check if entity is in bubble column -+ */ -+ public boolean isInBubbleColumn(); -+ -+ /** -+ * Check if entity is in water or rain -+ */ -+ public boolean isInWaterOrRain(); -+ -+ /** -+ * Check if entity is in water or bubble column -+ */ -+ public boolean isInWaterOrBubbleColumn(); -+ -+ /** -+ * Check if entity is in water or rain or bubble column -+ */ -+ public boolean isInWaterOrRainOrBubbleColumn(); -+ -+ /** -+ * Check if entity is in lava -+ */ -+ public boolean isInLava(); - // Paper end - } diff --git a/Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch deleted file mode 100644 index 5dc61d601d07..000000000000 --- a/Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent / PrepareGrindstoneEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -Grindstone is a backwards compat from a previous PrepareGrindstoneEvent - -diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..449e8c06f8434b59d49a76481fa60c5c49e80579 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareGrindstoneEvent.java -@@ -0,0 +1,28 @@ -+package com.destroystokyo.paper.event.inventory; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.inventory.GrindstoneInventory; -+import org.bukkit.inventory.InventoryView; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an item is put in a slot for grinding in a Grindstone -+ * @see com.destroystokyo.paper.event.inventory.PrepareResultEvent -+ */ -+@Deprecated -+public class PrepareGrindstoneEvent extends PrepareResultEvent { -+ -+ public PrepareGrindstoneEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -+ super(inventory, result); -+ } -+ -+ @NotNull -+ @Override -+ public GrindstoneInventory getInventory() { -+ return (GrindstoneInventory) super.getInventory(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..045ce9ec3c9134aced5f5235b760ac85599d16c6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/event/inventory/PrepareResultEvent.java -@@ -0,0 +1,48 @@ -+package com.destroystokyo.paper.event.inventory; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.inventory.InventoryEvent; -+import org.bukkit.event.inventory.InventoryType; -+import org.bukkit.inventory.InventoryView; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when an item is put in an inventory containing a result slot -+ */ -+public class PrepareResultEvent extends InventoryEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private ItemStack result; -+ -+ public PrepareResultEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -+ super(inventory); -+ this.result = result; -+ } -+ -+ /** -+ * Get result item, may be null. -+ * -+ * @return result item -+ */ -+ @Nullable -+ public ItemStack getResult() { -+ return result; -+ } -+ -+ public void setResult(@Nullable ItemStack result) { -+ this.result = result; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -index 77109a07f07aa6985106dc1a9ad5218f6c7f360f..f1f6f4ab4f81a3f21e757fef4a30b00e94371f8d 100644 ---- a/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/PrepareAnvilEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import com.destroystokyo.paper.event.inventory.PrepareResultEvent; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.AnvilInventory; - import org.bukkit.inventory.InventoryView; -@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; - /** - * Called when an item is put in a slot for repair by an anvil. - */ --public class PrepareAnvilEvent extends InventoryEvent { -+// Paper start - extend PrepareResultEvent -+public class PrepareAnvilEvent extends PrepareResultEvent { - -- private static final HandlerList handlers = new HandlerList(); -- private ItemStack result; -+ //private static final HandlerList handlers = new HandlerList(); -+ //private ItemStack result; - - public PrepareAnvilEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -- super(inventory); -- this.result = result; -+ super(inventory, result); -+ //this.result = result; -+ // Paper end - } - - @NotNull -@@ -33,13 +36,14 @@ public class PrepareAnvilEvent extends InventoryEvent { - */ - @Nullable - public ItemStack getResult() { -- return result; -+ return super.getResult(); // Paper - } - - public void setResult(@Nullable ItemStack result) { -- this.result = result; -+ super.setResult(result); // Paper - } - -+ /* // Paper - comment out - @NotNull - @Override - public HandlerList getHandlers() { -@@ -50,4 +54,5 @@ public class PrepareAnvilEvent extends InventoryEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ // Paper - } -diff --git a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -index 99af1540324c4d68c5890ac40b591c5cbdd2e870..0bc0ca4f96c800e9c46c61710f44446691d8b93f 100644 ---- a/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/PrepareSmithingEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.inventory; - -+import com.destroystokyo.paper.event.inventory.PrepareResultEvent; - import org.bukkit.event.HandlerList; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.ItemStack; -@@ -10,14 +11,16 @@ import org.jetbrains.annotations.Nullable; - /** - * Called when an item is put in a slot for upgrade by a Smithing Table. - */ --public class PrepareSmithingEvent extends InventoryEvent { -+// Paper start - extend PrepareResultEvent -+public class PrepareSmithingEvent extends PrepareResultEvent { - -- private static final HandlerList handlers = new HandlerList(); -- private ItemStack result; -+ //private static final HandlerList handlers = new HandlerList(); -+ //private ItemStack result; - - public PrepareSmithingEvent(@NotNull InventoryView inventory, @Nullable ItemStack result) { -- super(inventory); -- this.result = result; -+ super(inventory, result); -+ //this.result = result; -+ // Paper end - } - - @NotNull -@@ -33,13 +36,14 @@ public class PrepareSmithingEvent extends InventoryEvent { - */ - @Nullable - public ItemStack getResult() { -- return result; -+ return super.getResult(); // Paper - } - - public void setResult(@Nullable ItemStack result) { -- this.result = result; -+ super.setResult(result); // Paper - } - -+ /* // Paper - comment out - @NotNull - @Override - public HandlerList getHandlers() { -@@ -50,4 +54,5 @@ public class PrepareSmithingEvent extends InventoryEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ */ // Paper - } diff --git a/Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch b/Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index 1f3141b2437d..000000000000 --- a/Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Wed, 29 Apr 2020 02:09:17 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 77d352450f6bc5293efec3b75e08b857e2626fe7..1eaf6aae1e13c48a7f911e523015cb9b8cca8638 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1478,6 +1478,22 @@ public final class Bukkit { - return server.createChunkData(world); - } - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ public static ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { -+ return server.createVanillaChunkData(world, x, z); -+ } -+ // Paper stop -+ - /** - * Creates a boss bar instance to display to players. The progress - * defaults to 1.0 -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 4b1f515f2228f16c1ce793bd45510243d758236f..8ee02c3d6cc8751704e5993fecd05293714e492f 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1245,6 +1245,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public ChunkGenerator.ChunkData createChunkData(@NotNull World world); - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ ChunkGenerator.ChunkData createVanillaChunkData(@NotNull World world, int x, int z); -+ // Paper end -+ - /** - * Creates a boss bar instance to display to players. The progress - * defaults to 1.0 -diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java -index 7caef27682f22a77de283dd6f391ec8bc0b0312b..5ba77d40a38e5e592ee265e4fbd510043a0b4345 100644 ---- a/src/main/java/org/bukkit/generator/ChunkGenerator.java -+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java -@@ -227,6 +227,22 @@ public abstract class ChunkGenerator { - return false; - } - -+ // Paper start -+ /** -+ * Create a ChunkData for use in a generator, that is populated by the vanilla generator for that world -+ * -+ * @param world the world to create the ChunkData for -+ * @param x the x coordinate of the chunk -+ * @param z the z coordinate of the chunk -+ * @return a new ChunkData for the world -+ * -+ */ -+ @NotNull -+ public ChunkData createVanillaChunkData(@NotNull World world, int x, int z) { -+ return Bukkit.getServer().createVanillaChunkData(world, x, z); -+ } -+ // Paper end -+ - /** - * Data for a Chunk. - */ diff --git a/Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch b/Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch deleted file mode 100644 index a3117a4377db..000000000000 --- a/Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gerrygames -Date: Thu, 16 Jul 2020 10:40:10 +0200 -Subject: [PATCH] Support hex colors in getLastColors - - -diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java -index 44d597d7a6f66a18b8037e971170ff7cea5e825f..4594701d77c5d0f744bece871b98d9f6f73eb5a7 100644 ---- a/src/main/java/org/bukkit/ChatColor.java -+++ b/src/main/java/org/bukkit/ChatColor.java -@@ -363,6 +363,7 @@ public enum ChatColor { - return new String(b); - } - -+ private static final Pattern HEX_COLOR_PATTERN = Pattern.compile(COLOR_CHAR + "x(?>" + COLOR_CHAR + "[0-9a-f]){6}", Pattern.CASE_INSENSITIVE); // Paper - Support hex colors in getLastColors - /** - * Gets the ChatColors used at the end of the given input string. - * -@@ -380,6 +381,15 @@ public enum ChatColor { - for (int index = length - 1; index > -1; index--) { - char section = input.charAt(index); - if (section == COLOR_CHAR && index < length - 1) { -+ // Paper start - Support hex colors -+ if (index > 11 && input.charAt(index - 12) == COLOR_CHAR && (input.charAt(index - 11) == 'x' || input.charAt(index - 11) == 'X')) { -+ String color = input.substring(index - 12, index + 2); -+ if (HEX_COLOR_PATTERN.matcher(color).matches()) { -+ result = color + result; -+ break; -+ } -+ } -+ // Paper end - char c = input.charAt(index + 1); - ChatColor color = getByChar(c); - diff --git a/Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch b/Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch deleted file mode 100644 index 17b9d923f2ec..000000000000 --- a/Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:25 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 1eaf6aae1e13c48a7f911e523015cb9b8cca8638..6228d7eca85fba52296c8d63d32804f32af1b421 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -171,6 +171,17 @@ public final class Bukkit { - return server.getMaxPlayers(); - } - -+ // Paper start -+ /** -+ * Set the maximum amount of players which can login to this server. -+ * -+ * @param maxPlayers the amount of players this server allows -+ */ -+ public static void setMaxPlayers(int maxPlayers) { -+ server.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - /** - * Get the game port that the server runs on. - * -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8ee02c3d6cc8751704e5993fecd05293714e492f..6237578b373002c009efde4fb4c1864f0bf4f19e 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -144,6 +144,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - public int getMaxPlayers(); - -+ // Paper start -+ /** -+ * Set the maximum amount of players which can login to this server. -+ * -+ * @param maxPlayers the amount of players this server allows -+ */ -+ public void setMaxPlayers(int maxPlayers); -+ // Paper end -+ - /** - * Get the game port that the server runs on. - * diff --git a/Spigot-API-Patches/0218-Add-moon-phase-API.patch b/Spigot-API-Patches/0218-Add-moon-phase-API.patch deleted file mode 100644 index c9e982795475..000000000000 --- a/Spigot-API-Patches/0218-Add-moon-phase-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:03 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/io/papermc/paper/world/MoonPhase.java b/src/main/java/io/papermc/paper/world/MoonPhase.java -new file mode 100644 -index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e5f008f7e ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/MoonPhase.java -@@ -0,0 +1,36 @@ -+package io.papermc.paper.world; -+ -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.HashMap; -+import java.util.Map; -+ -+public enum MoonPhase { -+ FULL_MOON(0L), -+ WANING_GIBBOUS(1L), -+ LAST_QUARTER(2L), -+ WANING_CRESCENT(3L), -+ NEW_MOON(4L), -+ WAXING_CRESCENT(5L), -+ FIRST_QUARTER(6L), -+ WAXING_GIBBOUS(7L); -+ -+ private final long day; -+ -+ MoonPhase(long day) { -+ this.day = day; -+ } -+ -+ private static final Map BY_DAY = new HashMap<>(); -+ -+ static { -+ for (MoonPhase phase : values()) { -+ BY_DAY.put(phase.day, phase); -+ } -+ } -+ -+ @NotNull -+ public static MoonPhase getPhase(long day) { -+ return BY_DAY.get(day % 8L); -+ } -+} -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6441d4e45e5d5f008f95233cdc34048b8be38592..e20d863d1308b470a294cb7ab022aac4b9a91f71 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -70,6 +70,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - * @return The amount of Players in this world - */ - int getPlayerCount(); -+ -+ /** -+ * @return the current moon phase at the current time in the world -+ */ -+ @NotNull -+ io.papermc.paper.world.MoonPhase getMoonPhase(); - // Paper end - - /** diff --git a/Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index 6550b233c55a..000000000000 --- a/Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:08 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index a2f5639904881d9bef7d1550dbed810e4b17c8de..9bf525b795ff1d88d2596b1f2bc787ce0df047bb 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -805,5 +805,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param jumping entity jump state - */ - void setJumping(boolean jumping); -+ -+ /** -+ * Plays pickup item animation towards this entity. -+ *

-+ * This will remove the item on the client. -+ *

-+ * Quantity is inferred to be that of the {@link Item}. -+ * -+ * @param item item to pickup -+ */ -+ default void playPickupItemAnimation(@NotNull Item item) { -+ playPickupItemAnimation(item, item.getItemStack().getAmount()); -+ } -+ -+ /** -+ * Plays pickup item animation towards this entity. -+ *

-+ * This will remove the item on the client. -+ * -+ * @param item item to pickup -+ * @param quantity quantity of item -+ */ -+ void playPickupItemAnimation(@NotNull Item item, int quantity); - // Paper end - } diff --git a/Spigot-API-Patches/0220-Add-BellRingEvent.patch b/Spigot-API-Patches/0220-Add-BellRingEvent.patch deleted file mode 100644 index 7862ad8c8885..000000000000 --- a/Spigot-API-Patches/0220-Add-BellRingEvent.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Mon, 24 Jun 2019 21:27:39 -0700 -Subject: [PATCH] Add BellRingEvent - -Add a new event, BellRingEvent, to trigger whenever a player rings a -village bell. Passes along the bell block and the player who rang it. - -diff --git a/src/main/java/io/papermc/paper/event/block/BellRingEvent.java b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..881e545df51409e6101b4bb49f699655a744f13f ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BellRingEvent.java -@@ -0,0 +1,55 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.potion.PotionEffect; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a bell is rung. -+ */ -+public class BellRingEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private final Entity entity; -+ -+ public BellRingEvent(@NotNull Block block, @Nullable Entity entity) { -+ super(block); -+ this.entity = entity; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the entity that rang the bell. -+ * -+ * @return the ringer or null if none -+ */ -+ @Nullable -+ public Entity getEntity() { -+ return entity; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0221-Brand-support.patch b/Spigot-API-Patches/0221-Brand-support.patch deleted file mode 100644 index 2c6d0a6ab95b..000000000000 --- a/Spigot-API-Patches/0221-Brand-support.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Mon, 6 Apr 2020 20:30:09 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2530c811f52f51d6338900221b4681c952c1c752..828b2b0538d4f936bee57d9fca55774723e13970 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -2044,6 +2044,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - // Paper end - } - -+ // Paper start - brand support -+ /** -+ * Returns player's client brand name. If the client didn't send this information, the brand name will be null.
-+ * For the Notchian client this name defaults to vanilla. Some modified clients report other names such as forge.
-+ * @return client brand name -+ */ -+ @Nullable -+ String getClientBrandName(); -+ // Paper end -+ - @NotNull - @Override - Spigot spigot(); diff --git a/Spigot-API-Patches/0222-Add-more-Evoker-API.patch b/Spigot-API-Patches/0222-Add-more-Evoker-API.patch deleted file mode 100644 index 0d6f0f73285b..000000000000 --- a/Spigot-API-Patches/0222-Add-more-Evoker-API.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:22:44 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/org/bukkit/entity/Evoker.java b/src/main/java/org/bukkit/entity/Evoker.java -index f8d173adc09197418883dc7bc66dd8bfff8c5c72..76f81cd124090337876c9e5e469862a1c8da4ec8 100644 ---- a/src/main/java/org/bukkit/entity/Evoker.java -+++ b/src/main/java/org/bukkit/entity/Evoker.java -@@ -64,4 +64,19 @@ public interface Evoker extends Spellcaster { - */ - @Deprecated - void setCurrentSpell(@Nullable Spell spell); -+ -+ // Paper start -+ /** -+ * @return the sheep being targeted by the {@link Spell#WOLOLO wololo spell}, or {@code null} if none -+ */ -+ @Nullable -+ Sheep getWololoTarget(); -+ -+ /** -+ * Set the sheep to be the target of the {@link Spell#WOLOLO wololo spell}, or {@code null} to clear. -+ * -+ * @param sheep new wololo target -+ */ -+ void setWololoTarget(@Nullable Sheep sheep); -+ // Paper end - } diff --git a/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index b6751c5ef8d1..000000000000 --- a/Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:17:46 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 2b53e68e96ea346a6f2b5cadcf9f81b2c231c408..e453e5eb7245aad3ecbb19652ebb34abe030c0a9 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3578,6 +3578,16 @@ public enum Material implements Keyed { - } - return false; - } -+ -+ /** -+ * Return the translation key for the Material, so the client can translate it into the active -+ * locale when using a TranslatableComponent. -+ * @return the translation key -+ */ -+ @NotNull -+ public String getTranslationKey() { -+ return Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index e348034288c74ab80360086d71f0b7f61551df24..2d9264ffe0fee863f1b814952ef063daa7962d76 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -101,5 +101,34 @@ public interface UnsafeValues { - byte[] serializeItem(ItemStack item); - - ItemStack deserializeItem(byte[] data); -+ -+ /** -+ * Return the translation key for the Material, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. -+ * @return the translation key -+ */ -+ String getTranslationKey(Material mat); -+ -+ /** -+ * Return the translation key for the Block, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}. -+ * @return the translation key -+ */ -+ String getTranslationKey(org.bukkit.block.Block block); -+ -+ /** -+ * Return the translation key for the EntityType, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
-+ * This is null, when the EntityType isn't known to NMS (custom entities) -+ * @return the translation key -+ */ -+ String getTranslationKey(org.bukkit.entity.EntityType type); -+ -+ /** -+ * Return the translation key for the ItemStack, so the client can translate it into the active -+ * locale when using a {@link net.kyori.adventure.text.TranslatableComponent}.
-+ * @return the translation key -+ */ -+ String getTranslationKey(ItemStack itemStack); - // Paper end - } -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e1cc36fbe808973227c0e8ca7166453235c90279..e6647c45f65bae916759cd899256f8130790d242 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -584,5 +584,13 @@ public interface Block extends Metadatable { - */ - @NotNull - com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup(); -+ -+ /** -+ * Return the translation key for the Block, so the client can translate it into the active -+ * locale when using a TranslatableComponent. -+ * @return the translation key -+ */ -+ @NotNull -+ String getTranslationKey(); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java -index 774363a8186b3861f10c0452ac63726cae365169..692b75eb78405874077c850bfc72e247ccc80860 100644 ---- a/src/main/java/org/bukkit/entity/EntityType.java -+++ b/src/main/java/org/bukkit/entity/EntityType.java -@@ -414,4 +414,15 @@ public enum EntityType implements Keyed { - public boolean isAlive() { - return living; - } -+ -+ /** -+ * Return the translation key for the EntityType, so the client can translate it into the active -+ * locale when using a TranslatableComponent.
-+ * This is null, when the EntityType isn't known to NMS (custom entities) -+ * @return the translation key -+ */ -+ @Nullable -+ String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 15b48ad1ba5bcf7394fb3f52ce2cc6baa6632f66..c236cb81b7ec7993b63da929c0492564e75581ee 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -851,5 +851,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - ItemMeta itemMeta = getItemMeta(); - return itemMeta != null && itemMeta.hasItemFlag(flag); - } -+ -+ /** -+ * Gets the translation key for this itemstack. -+ * This is not the same as getting the translation key -+ * for the material of this itemstack. -+ * -+ * @return the translation key -+ */ -+ @NotNull -+ public String getTranslationKey() { -+ return Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch b/Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index 9a15253cfdea..000000000000 --- a/Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:17:37 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java -index e2bcc96ad067e2abfe9108b3a2235fe5da7ab3eb..3cbe5afc3548d4b7d0c6e625d9029506133676ff 100644 ---- a/src/main/java/org/bukkit/inventory/ItemFactory.java -+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java -@@ -184,5 +184,62 @@ public interface ItemFactory { - */ - @Nullable - String getI18NDisplayName(@Nullable ItemStack item); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying. -+ * -+ * @param itemStack -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack -+ */ -+ @NotNull -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull ItemStack itemStack); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * Uses the display name of the entity, if present. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent()} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable String customName); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @Nullable net.md_5.bungee.api.chat.BaseComponent customName); -+ -+ /** -+ * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} for displaying. -+ * -+ * @param entity Entity to create the HoverEvent for -+ * @param customName a custom name that should be displayed, if not passed entity name will be displayed -+ * @return the {@link net.md_5.bungee.api.chat.hover.content.Content} of that {@link org.bukkit.entity.Entity} -+ * @deprecated use {@link org.bukkit.entity.Entity#asHoverEvent(java.util.function.UnaryOperator)} -+ */ -+ @NotNull -+ @Deprecated -+ net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName); - // Paper end - } diff --git a/Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch b/Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index 53584ff63362..000000000000 --- a/Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 26 Aug 2020 02:11:58 -0400 -Subject: [PATCH] Add additional open container api to HumanEntity - - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index b09d12390d5f77330ac84452e0fee63a169bd01f..77bff8fb6bfdf739e413084e13677a83e723c71e 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -148,6 +148,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - @Nullable - public InventoryView openMerchant(@NotNull Merchant merchant, boolean force); - -+ // Paper start - Add additional containers -+ /** -+ * Opens an empty anvil inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no anvil block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openAnvil(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty cartography table inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no cartography table block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openCartographyTable(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty grindstone inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no grindstone block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openGrindstone(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty loom inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no loom block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openLoom(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty smithing table inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no smithing table block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openSmithingTable(@Nullable Location location, boolean force); -+ -+ /** -+ * Opens an empty stonecutter inventory window with the player's inventory -+ * on the bottom. -+ * -+ * @param location The location to attach it to. If null, the player's -+ * location is used. -+ * @param force If false, and there is no stonecutter block at the location, -+ * no inventory will be opened and null will be returned. -+ * @return The newly opened inventory view, or null if it could not be -+ * opened. -+ */ -+ @Nullable -+ public InventoryView openStonecutter(@Nullable Location location, boolean force); -+ // Paper end -+ - /** - * Force-closes the currently open inventory view for this player, if any. - */ diff --git a/Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index a92a435f5ae5..000000000000 --- a/Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:31 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 2d9264ffe0fee863f1b814952ef063daa7962d76..84eda68281c6c6968d95b1313a33696c3a9980d4 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -130,5 +130,12 @@ public interface UnsafeValues { - * @return the translation key - */ - String getTranslationKey(ItemStack itemStack); -+ -+ /** -+ * Creates and returns the next EntityId available. -+ *

-+ * Use this when sending custom packets, so that there are no collisions on the client or server. -+ */ -+ public int nextEntityId(); - // Paper end - } diff --git a/Spigot-API-Patches/0227-Entity-isTicking.patch b/Spigot-API-Patches/0227-Entity-isTicking.patch deleted file mode 100644 index 3856ba234e62..000000000000 --- a/Spigot-API-Patches/0227-Entity-isTicking.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:07 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 75cebfca7b436ef30b718bba7e0566d047e5c61a..2cc501b74741bdbdc40d1b135725f18c4d36dc2b 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -698,5 +698,10 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - * Check if entity is in lava - */ - public boolean isInLava(); -+ -+ /** -+ * Check if entity is inside a ticking chunk -+ */ -+ public boolean isTicking(); - // Paper end - } diff --git a/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch deleted file mode 100644 index 7798b89d2182..000000000000 --- a/Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aurora -Date: Sat, 3 Oct 2020 16:28:41 +0200 -Subject: [PATCH] Clarify the Javadocs for Entity.getEntitySpawnReason() - - -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 2cc501b74741bdbdc40d1b135725f18c4d36dc2b..428daeb04d0a35a443467e2f657d2356bcfdd7d7 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -664,7 +664,7 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - Chunk getChunk(); - - /** -- * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. -+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that initially spawned this entity. - */ - @NotNull - org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason(); diff --git a/Spigot-API-Patches/0230-Player-elytra-boost-API.patch b/Spigot-API-Patches/0230-Player-elytra-boost-API.patch deleted file mode 100644 index 1f9e683db7cb..000000000000 --- a/Spigot-API-Patches/0230-Player-elytra-boost-API.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:06:14 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 828b2b0538d4f936bee57d9fca55774723e13970..7aa9fb852dce23c53fee80e97e0dcdb278ae82ba 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1916,6 +1916,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - @NotNull - T getClientOption(@NotNull ClientOption option); -+ -+ /** -+ * Boost a Player that's {@link #isGliding()} using a {@link Firework}. -+ * If the creation of the entity is cancelled, no boosting is done. -+ * This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}. -+ * -+ * @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with -+ * @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled -+ * @throws IllegalArgumentException if {@link #isGliding()} is false -+ * or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET} -+ */ -+ @Nullable -+ Firework boostElytra(@NotNull ItemStack firework); - // Paper end - - // Spigot start diff --git a/Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch b/Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index 86d947866a60..000000000000 --- a/Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:35:58 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 6228d7eca85fba52296c8d63d32804f32af1b421..68101a322ffab8ec28843386b79b8079576fa720 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -950,6 +950,27 @@ public final class Bukkit { - return server.getOfflinePlayer(name); - } - -+ // Paper start -+ /** -+ * Gets the player by the given name, regardless if they are offline or -+ * online. -+ *

-+ * This will not make a web request to get the UUID for the given name, -+ * thus this method will not block. However this method will return -+ * {@code null} if the player is not cached. -+ *

-+ * -+ * @param name the name of the player to retrieve -+ * @return an offline player if cached, {@code null} otherwise -+ * @see #getOfflinePlayer(String) -+ * @see #getOfflinePlayer(java.util.UUID) -+ */ -+ @Nullable -+ public static OfflinePlayer getOfflinePlayerIfCached(@NotNull String name) { -+ return server.getOfflinePlayerIfCached(name); -+ } -+ // Paper end -+ - /** - * Gets the player by the given UUID, regardless if they are offline or - * online. -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 6237578b373002c009efde4fb4c1864f0bf4f19e..a79fa08b9e6fb924b2da933eb6e4b365d14d938d 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -797,6 +797,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @NotNull - public OfflinePlayer getOfflinePlayer(@NotNull String name); - -+ // Paper start -+ /** -+ * Gets the player by the given name, regardless if they are offline or -+ * online. -+ *

-+ * This will not make a web request to get the UUID for the given name, -+ * thus this method will not block. However this method will return -+ * {@code null} if the player is not cached. -+ *

-+ * -+ * @param name the name of the player to retrieve -+ * @return an offline player if cached, {@code null} otherwise -+ * @see #getOfflinePlayer(String) -+ * @see #getOfflinePlayer(java.util.UUID) -+ */ -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(@NotNull String name); -+ // Paper end -+ - /** - * Gets the player by the given UUID, regardless if they are offline or - * online. diff --git a/Spigot-API-Patches/0232-Add-ignore-discounts-API.patch b/Spigot-API-Patches/0232-Add-ignore-discounts-API.patch deleted file mode 100644 index 492c998c91c4..000000000000 --- a/Spigot-API-Patches/0232-Add-ignore-discounts-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:33:38 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/org/bukkit/inventory/MerchantRecipe.java b/src/main/java/org/bukkit/inventory/MerchantRecipe.java -index 1fb4a1c53791776f9c5a952a592f15fc35cb2703..2be2f3fe655c417bfc8f8e840f9e9415d168f37e 100644 ---- a/src/main/java/org/bukkit/inventory/MerchantRecipe.java -+++ b/src/main/java/org/bukkit/inventory/MerchantRecipe.java -@@ -28,6 +28,7 @@ public class MerchantRecipe implements Recipe { - private boolean experienceReward; - private int villagerExperience; - private float priceMultiplier; -+ private boolean ignoreDiscounts; // Paper - - public MerchantRecipe(@NotNull ItemStack result, int maxUses) { - this(result, 0, maxUses, false); -@@ -38,6 +39,12 @@ public class MerchantRecipe implements Recipe { - } - - public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier) { -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, villagerExperience, priceMultiplier, false); -+ } -+ public MerchantRecipe(@NotNull ItemStack result, int uses, int maxUses, boolean experienceReward, int villagerExperience, float priceMultiplier, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.result = result; - this.uses = uses; - this.maxUses = maxUses; -@@ -172,4 +179,20 @@ public class MerchantRecipe implements Recipe { - public void setPriceMultiplier(float priceMultiplier) { - this.priceMultiplier = priceMultiplier; - } -+ -+ // Paper start -+ /** -+ * @return Whether all discounts on this trade should be ignored. -+ */ -+ public boolean shouldIgnoreDiscounts() { -+ return ignoreDiscounts; -+ } -+ -+ /** -+ * @param ignoreDiscounts Whether all discounts on this trade should be ignored. -+ */ -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch b/Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch deleted file mode 100644 index 142a8b52027f..000000000000 --- a/Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:27 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java -index c404a5b8efea7c780db5ddae19456753808abb3d..0ee072645ecf1bf5feb74de6960947ef76db366e 100644 ---- a/src/main/java/org/bukkit/entity/Item.java -+++ b/src/main/java/org/bukkit/entity/Item.java -@@ -90,5 +90,34 @@ public interface Item extends Entity { - * @param canMobPickup True to allow non-player entity pickup - */ - public void setCanMobPickup(boolean canMobPickup); -+ -+ /** -+ * Gets whether the player can pickup the item or not -+ * -+ * @return True if a player can pickup the item -+ */ -+ public boolean canPlayerPickup(); -+ -+ /** -+ * Sets whether the item can be picked up or not. Modifies the pickup delay value to do so. -+ * -+ * @param canPlayerPickup True if the player can pickup the item -+ */ -+ public void setCanPlayerPickup(boolean canPlayerPickup); -+ -+ /** -+ * Gets whether the item will age and despawn from being on the ground too long -+ * -+ * @return True if the item will age -+ */ -+ public boolean willAge(); -+ -+ /** -+ * Sets whether the item will age or not. If the item is not ageing, it will not despawn -+ * by being on the ground for too long. -+ * -+ * @param willAge True if the item should age -+ */ -+ public void setWillAge(boolean willAge); - // Paper end - } diff --git a/Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch b/Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index ff56b99ebfb1..000000000000 --- a/Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:38:15 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/org/bukkit/block/Beacon.java b/src/main/java/org/bukkit/block/Beacon.java -index 6349fa9da3f96df3553fb9552c1cab95338cecb0..78475fc6faff0f295828d7b53792001d51aa2889 100644 ---- a/src/main/java/org/bukkit/block/Beacon.java -+++ b/src/main/java/org/bukkit/block/Beacon.java -@@ -64,4 +64,26 @@ public interface Beacon extends TileState, Lockable, Nameable { - * @param effect desired secondary effect - */ - void setSecondaryEffect(@Nullable PotionEffectType effect); -+ -+ // Paper start - Custom effect ranges -+ /** -+ * Gets the effect range of this beacon. -+ * A negative range value means the beacon is using its default range based on tier. -+ * @return Either the custom range set with {@link #setEffectRange(double)} or the range based on the beacon tier. -+ */ -+ double getEffectRange(); -+ -+ /** -+ * Sets the effect range of the beacon -+ * A negative range value means the beacon is using its default range based on tier. -+ * @param range Radius of effect range. -+ */ -+ void setEffectRange(double range); -+ -+ /** -+ * Resets the custom range from this beacon and falls back to the range based on the the beacon tier. -+ * Shortcut for setting the effect range to a negative number. -+ */ -+ void resetEffectRange(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0235-Add-API-for-quit-reason.patch b/Spigot-API-Patches/0235-Add-API-for-quit-reason.patch deleted file mode 100644 index 63d864224b9f..000000000000 --- a/Spigot-API-Patches/0235-Add-API-for-quit-reason.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:58 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index 849e8f10dd77e9fb46aab17752b8f1ff79e9d42e..b6016aa1e91863efc252eecab69ade6f54c89f27 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -11,16 +11,28 @@ import org.jetbrains.annotations.Nullable; - public class PlayerQuitEvent extends PlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private net.kyori.adventure.text.Component quitMessage; // Paper -+ private final QuitReason reason; // Paper - - @Deprecated // Paper - public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { -+ // Paper start -+ this(who, quitMessage, null); -+ } -+ @Deprecated // Paper -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage, @Nullable QuitReason quitReason) { - super(who); - this.quitMessage = quitMessage != null ? org.bukkit.Bukkit.getUnsafe().legacyComponentSerializer().deserialize(quitMessage) : null; // Paper -+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; - } - // Paper start -+ @Deprecated - public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { -+ this(who, quitMessage, null); -+ } -+ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage, @Nullable QuitReason quitReason) { - super(who); - this.quitMessage = quitMessage; -+ this.reason = quitReason == null ? QuitReason.DISCONNECTED : quitReason; - } - - /** -@@ -75,4 +87,39 @@ public class PlayerQuitEvent extends PlayerEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start -+ @NotNull -+ public QuitReason getReason() { -+ return this.reason; -+ } -+ -+ public enum QuitReason { -+ /** -+ * The player left on their own behalf. -+ *

-+ * This does not mean they pressed the disconnect button in their client, but rather that the client severed the -+ * connection themselves. This may occur if no keep-alive packet is received on their side, among other things. -+ */ -+ DISCONNECTED, -+ -+ /** -+ * The player was kicked from the server. -+ */ -+ KICKED, -+ -+ /** -+ * The player has timed out. -+ */ -+ TIMED_OUT, -+ -+ /** -+ * The player's connection has entered an erroneous state. -+ *

-+ * Reasons for this may include invalid packets, invalid data, and uncaught exceptions in the packet handler, -+ * among others. -+ */ -+ ERRONEOUS_STATE, -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch b/Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch deleted file mode 100644 index bdf3dd2bbe51..000000000000 --- a/Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:37:48 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index e6647c45f65bae916759cd899256f8130790d242..e4e3be0ee9c557e04d9ed1ab6f1569bd36a0e846 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -592,5 +592,29 @@ public interface Block extends Metadatable { - */ - @NotNull - String getTranslationKey(); -+ -+ /** -+ * Gets the speed at which this block will be destroyed by a given {@link ItemStack} -+ * -+ *

Default value is 1.0

-+ * -+ * @param itemStack {@link ItemStack} used to mine this Block -+ * @return the speed that this Block will be mined by the given {@link ItemStack} -+ */ -+ @NotNull -+ public default float getDestroySpeed(@NotNull ItemStack itemStack) { -+ return getDestroySpeed(itemStack, false); -+ } -+ -+ /** -+ * Gets the speed at which this blook will be destroyed by a given {@link org.bukkit.inventory.ItemStack} -+ *

-+ * Default value is 1.0 -+ * @param itemStack {@link org.bukkit.inventory.ItemStack} used to mine this Block -+ * @param considerEnchants true to look at enchants on the itemstack -+ * @return the speed that this Block will be mined by the given {@link org.bukkit.inventory.ItemStack} -+ */ -+ @NotNull -+ float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants); - // Paper end - } diff --git a/Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch b/Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index bb5b5e0b5e83..000000000000 --- a/Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:07:58 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 9bf525b795ff1d88d2596b1f2bc787ce0df047bb..e535750d01a6c1bf4b1fe94df518166213da9b08 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -766,6 +766,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - @Nullable - ItemStack getActiveItem(); - -+ // Paper start -+ /** -+ * Interrupts any ongoing active "usage" or consumption or an item. -+ */ -+ void clearActiveItem(); -+ // Paper end -+ - /** - * Get's remaining time a player needs to keep hands raised with an item to finish using it. - * @return Remaining ticks to use the item diff --git a/Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch b/Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 3bf6084e1446..000000000000 --- a/Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Tue, 25 Aug 2020 13:45:15 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..58d18f05af13d836ddc62fcd30befcb06f07c57c ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerItemCooldownEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.player; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Fired when a player receives an item cooldown. -+ */ -+public class PlayerItemCooldownEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ @NotNull -+ private final Material type; -+ private boolean cancelled; -+ private int cooldown; -+ -+ public PlayerItemCooldownEvent(@NotNull Player player, @NotNull Material type, int cooldown) { -+ super(player); -+ this.type = type; -+ this.cooldown = cooldown; -+ } -+ -+ /** -+ * Get the material affected by the cooldown. -+ * -+ * @return material affected by the cooldown -+ */ -+ @NotNull -+ public Material getType() { -+ return type; -+ } -+ -+ /** -+ * Gets the cooldown in ticks. -+ * -+ * @return cooldown in ticks -+ */ -+ public int getCooldown() { -+ return cooldown; -+ } -+ -+ /** -+ * Sets the cooldown of the material in ticks. -+ * Setting the cooldown to 0 results in removing an already existing cooldown for the material. -+ * -+ * @param cooldown cooldown in ticks, has to be a positive number -+ */ -+ public void setCooldown(int cooldown) { -+ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!"); -+ this.cooldown = cooldown; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0239-More-lightning-API.patch b/Spigot-API-Patches/0239-More-lightning-API.patch deleted file mode 100644 index 1b6f51229997..000000000000 --- a/Spigot-API-Patches/0239-More-lightning-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sun, 26 Jul 2020 14:44:16 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java -index be347c3d0291f44036bae29a4e7e4645d6a4cdf6..2c81a3f685588431a3c7675c84b35a28975232af 100644 ---- a/src/main/java/org/bukkit/entity/LightningStrike.java -+++ b/src/main/java/org/bukkit/entity/LightningStrike.java -@@ -31,4 +31,38 @@ public interface LightningStrike extends Entity { - @Override - Spigot spigot(); - // Spigot end -+ -+ // Paper start -+ /** -+ * Returns the amount of flash iterations that will be done before the lightning dies. -+ * -+ * @see #getLifeTicks() for how long the current flash will last -+ * @return amount of flashes that will be shown before the lightning dies -+ */ -+ int getFlashCount(); -+ -+ /** -+ * Sets the amount of life iterations that will be done before the lightning dies. -+ * Default number of flashes on creation is between 1-3. -+ * -+ * @param flashes amount of iterations that will be done before the lightning dies, must to be a positive number -+ */ -+ void setFlashCount(int flashes); -+ -+ /** -+ * Returns the amount of ticks the current flash will do damage for. -+ * Starts with 2 by default, will damage while it is equal to or above 0, with the next flash beginning somewhere between 0 and -9. -+ * -+ * @return ticks the current flash will do damage for -+ */ -+ int getLifeTicks(); -+ -+ /** -+ * Sets the amount of ticks the current flash will do damage/fire for. -+ * Default is 2 for each flash, on which the sound and effect will also be played. -+ * -+ * @param lifeTicks ticks the current flash will do damage for -+ */ -+ void setLifeTicks(int lifeTicks); -+ // Paper end - } diff --git a/Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch b/Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index 051544b4a90d..000000000000 --- a/Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 12:32:35 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aa7d440b797eac9e62678d03cc87f42838758bfd ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/PlayerShearBlockEvent.java -@@ -0,0 +1,108 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.List; -+ -+/** -+ * Called when a player uses sheers on a block. -+ *

-+ * This event is not called when breaking blocks with shears but instead only when a -+ * player uses the sheer item on a block to garner drops from said block and/or change its state. -+ *

-+ * Examples include shearing a pumpkin to turn it into a carved pumpkin or shearing a beehive to get honeycomb. -+ */ -+public class PlayerShearBlockEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ private final Block block; -+ private final ItemStack item; -+ private final EquipmentSlot hand; -+ private final List drops; -+ -+ public PlayerShearBlockEvent(@NotNull Player who, @NotNull Block block, @NotNull ItemStack item, @NotNull EquipmentSlot hand, @NotNull List drops) { -+ super(who); -+ this.block = block; -+ this.item = item; -+ this.hand = hand; -+ this.drops = drops; -+ } -+ -+ /** -+ * Gets the block being sheared in this event. -+ * -+ * @return The {@link Block} which block is being sheared in this event. -+ */ -+ @NotNull -+ public Block getBlock() { -+ return block; -+ } -+ -+ /** -+ * Gets the item used to shear the block. -+ * -+ * @return The {@link ItemStack} of the shears. -+ */ -+ @NotNull -+ public ItemStack getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets the hand used to shear the block. -+ * -+ * @return Either {@link EquipmentSlot#HAND} OR {@link EquipmentSlot#OFF_HAND}. -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ -+ /** -+ * Gets the resulting drops of this event. -+ * -+ * @return A {@link List list} of {@link ItemStack items} that will be dropped as result of this event. -+ */ -+ @NotNull -+ public List getDrops() { -+ return drops; -+ } -+ -+ /** -+ * Gets whether the shearing of the block should be cancelled or not. -+ * -+ * @return Whether the shearing of the block should be cancelled or not. -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Sets whether the shearing of the block should be cancelled or not. -+ * -+ * @param cancel whether the shearing of the block should be cancelled or not. -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch b/Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch deleted file mode 100644 index 9f71d1c074dc..000000000000 --- a/Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Fri, 4 Dec 2020 15:53:19 -0800 -Subject: [PATCH] Enable multi-release plugin jars - - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 11e5618ff66385574ba04db0942a75227cf8eb0f..c833cee9fddd12afdfe6bde1435559819b9ad656 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -58,7 +58,18 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - this.description = description; - this.dataFolder = dataFolder; - this.file = file; -- this.jar = new JarFile(file); -+ // Paper - enable multi-release jars for Java 9+ -+ JarFile jarFile; -+ try { -+ final java.lang.reflect.Method runtimeVersionMethod = JarFile.class.getMethod("runtimeVersion"); -+ final Object runtimeVersion = runtimeVersionMethod.invoke(null); -+ @SuppressWarnings("JavaReflectionMemberAccess") final java.lang.reflect.Constructor constructor = JarFile.class.getConstructor(File.class, boolean.class, int.class, runtimeVersion.getClass()); -+ jarFile = constructor.newInstance(file, true, java.util.zip.ZipFile.OPEN_READ, runtimeVersion); -+ } catch (Exception ignored) { -+ jarFile = new JarFile(file); -+ } -+ this.jar = jarFile; -+ // Paper end - this.manifest = jar.getManifest(); - this.url = file.toURI().toURL(); - this.libraryLoader = libraryLoader; diff --git a/Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch b/Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index e2ce87ec9d2e..000000000000 --- a/Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:24:45 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2c1cda1126e577a88f19071e958eddb5a38785af ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java -@@ -0,0 +1,42 @@ -+package io.papermc.paper.event.packet; -+ -+import org.bukkit.Chunk; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.ChunkEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Is called when a {@link org.bukkit.entity.Player} receives a {@link org.bukkit.Chunk} -+ *

-+ * Can for example be used for spawning a fake entity when the player receives a chunk. -+ * -+ * Should only be used for packet/clientside related stuff. -+ * Not intended for modifying server side state. -+ */ -+public class PlayerChunkLoadEvent extends ChunkEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final Player player; -+ -+ public PlayerChunkLoadEvent(@NotNull Chunk chunk, @NotNull Player player) { -+ super(chunk); -+ this.player = player; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..12163a7b0591a7d022dc7eb9ee6608a1b6c39d9b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/packet/PlayerChunkUnloadEvent.java -@@ -0,0 +1,40 @@ -+package io.papermc.paper.event.packet; -+ -+import org.bukkit.Chunk; -+import org.bukkit.entity.Player; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.ChunkEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Is called when a {@link Player} receives a chunk unload packet. -+ * -+ * Should only be used for packet/clientside related stuff. -+ * Not intended for modifying server side. -+ */ -+public class PlayerChunkUnloadEvent extends ChunkEvent { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private final Player player; -+ -+ public PlayerChunkUnloadEvent(@NotNull Chunk chunk, @NotNull Player player) { -+ super(chunk); -+ this.player = player; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public Player getPlayer() { -+ return player; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch b/Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index 3ca885228df0..000000000000 --- a/Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:12 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index e535750d01a6c1bf4b1fe94df518166213da9b08..9f0645dc5f76ee9ef73d88f768025429e5a9edf7 100644 ---- a/src/main/java/org/bukkit/entity/LivingEntity.java -+++ b/src/main/java/org/bukkit/entity/LivingEntity.java -@@ -835,5 +835,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource - * @param quantity quantity of item - */ - void playPickupItemAnimation(@NotNull Item item, int quantity); -+ -+ /** -+ * Gets player hurt direction -+ * -+ * @return hurt direction -+ */ -+ float getHurtDirection(); -+ -+ /** -+ * Sets player hurt direction -+ * -+ * @param hurtDirection hurt direction -+ */ -+ void setHurtDirection(float hurtDirection); - // Paper end - } diff --git a/Spigot-API-Patches/0244-added-PlayerTradeEvent.patch b/Spigot-API-Patches/0244-added-PlayerTradeEvent.patch deleted file mode 100644 index 5288a1120599..000000000000 --- a/Spigot-API-Patches/0244-added-PlayerTradeEvent.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:10:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java -new file mode 100755 -index 0000000000000000000000000000000000000000..198e5464eae6b961c83148a57c18f91a4bb33cf6 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java -@@ -0,0 +1,121 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.MerchantRecipe; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a player trades with a villager or wandering trader -+ */ -+public class PlayerTradeEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ -+ private boolean increaseTradeUses; -+ private boolean rewardExp; -+ private final AbstractVillager villager; -+ private MerchantRecipe trade; -+ -+ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) { -+ super(player); -+ this.villager = villager; -+ this.trade = trade; -+ this.rewardExp = rewardExp; -+ this.increaseTradeUses = increaseTradeUses; -+ } -+ -+ /** -+ * Gets the Villager or Wandering trader associated with this event -+ * @return the villager or wandering trader -+ */ -+ @NotNull -+ public AbstractVillager getVillager() { -+ return villager; -+ } -+ -+ /** -+ * Gets the associated trade with this event -+ * @return the trade -+ */ -+ @NotNull -+ public MerchantRecipe getTrade() { -+ return trade; -+ } -+ -+ /** -+ * Sets the trade. This is then used to determine the next prices -+ * @param trade the trade to use -+ */ -+ public void setTrade(@Nullable MerchantRecipe trade) { -+ this.trade = trade; -+ } -+ -+ /** -+ * @return will trade try to reward exp -+ */ -+ public boolean isRewardingExp() { -+ return rewardExp; -+ } -+ -+ /** -+ * Sets whether the trade will try to reward exp -+ * @param rewardExp try to reward exp -+ */ -+ public void setRewardExp(boolean rewardExp) { -+ this.rewardExp = rewardExp; -+ } -+ -+ /** -+ * @return whether or not the trade will count as a use of the trade -+ */ -+ public boolean willIncreaseTradeUses() { -+ return increaseTradeUses; -+ } -+ -+ /** -+ * Sets whether or not the trade will count as a use -+ * @param increaseTradeUses true to count/false to not count -+ */ -+ public void setIncreaseTradeUses(boolean increaseTradeUses) { -+ this.increaseTradeUses = increaseTradeUses; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index eed087f1f6ba..000000000000 --- a/Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:30 -0800 -Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -index c7d57e286c11eaa578ff6fd457b02a9ff829aa71..24b371b11347abf31fda4dadde8e0a7af60b181b 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java -@@ -37,6 +37,12 @@ public class PlayerBedEnterEvent extends PlayerEvent implements Cancellable { - * Entering the bed is prevented due to the player being too far away. - */ - TOO_FAR_AWAY, -+ // Paper start -+ /** -+ * Bed was obstructed. -+ */ -+ OBSTRUCTED, -+ // Paper end - /** - * Entering the bed is prevented due to there being monsters nearby. - */ diff --git a/Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch b/Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch deleted file mode 100644 index ddc1efeb9e1f..000000000000 --- a/Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:21:32 -0800 -Subject: [PATCH] Add TargetHitEvent API - - -diff --git a/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cc067ae118af9957b1b9f5c8d45f63f9154f4942 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/TargetHitEvent.java -@@ -0,0 +1,69 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockFace; -+import org.bukkit.entity.Projectile; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.ProjectileHitEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a Target Block is hit by a projectile. -+ *

-+ * Cancelling this event will stop the Target from emitting a redstone signal, -+ * and in the case that the shooter is a player, will stop them from receiving -+ * advancement criteria. -+ */ -+public class TargetHitEvent extends ProjectileHitEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled; -+ private int signalStrength; -+ -+ public TargetHitEvent(@NotNull Projectile projectile, @NotNull Block block, @NotNull BlockFace blockFace, int signalStrength) { -+ super(projectile, null, block, blockFace); -+ this.signalStrength = signalStrength; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the strength of the redstone signal to be emitted by the Target block -+ * -+ * @return the strength of the redstone signal to be emitted -+ */ -+ public int getSignalStrength() { -+ return signalStrength; -+ } -+ -+ /** -+ * Sets the strength of the redstone signal to be emitted by the Target block -+ * -+ * @param signalStrength the strength of the redstone signal to be emitted -+ */ -+ public void setSignalStrength(int signalStrength) { -+ if (signalStrength < 0 || signalStrength > 15) { -+ throw new IllegalArgumentException("Signal strength out of range (" + signalStrength + "), must be in range [0,15]"); -+ } -+ this.signalStrength = signalStrength; -+ } -+} diff --git a/Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch b/Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch deleted file mode 100644 index 87283b098489..000000000000 --- a/Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 17:27:27 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 6933fd6ad353a2d008c4a64c52a64bf36bd8035c..0c72d00ad238ab69d7ae0941e3ecb6c86e71624d 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -427,6 +427,42 @@ public interface Block extends Metadatable { - */ - boolean isLiquid(); - -+ // Paper start -+ /** -+ * Check if this block is solid -+ *

-+ * Determined by Minecraft, typically a block a player can use to place a new block to build things. -+ * An example of a non buildable block would be liquids, flowers, or fire -+ * -+ * @return true if block is buildable -+ */ -+ boolean isBuildable(); -+ /** -+ * Check if this block is burnable -+ *

-+ * Determined by Minecraft, typically a block that fire can destroy (Wool, Wood) -+ * -+ * @return true if block is burnable -+ */ -+ boolean isBurnable(); -+ /** -+ * Check if this block is replaceable -+ *

-+ * Determined by Minecraft, representing a block that is not AIR that you can still place a new block at, such as flowers. -+ * @return true if block is replaceable -+ */ -+ boolean isReplaceable(); -+ /** -+ * Check if this block is solid -+ *

-+ * Determined by Minecraft, typically a block a player can stand on and can't be passed through. -+ * -+ * This API is faster than accessing Material#isSolid as it avoids a material lookup and switch statement. -+ * @return true if block is solid -+ */ -+ boolean isSolid(); -+ // Paper end -+ - /** - * Gets the temperature of this block. - *

diff --git a/Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch deleted file mode 100644 index d6cdb8862b10..000000000000 --- a/Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:38 +1000 -Subject: [PATCH] Add API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/org/bukkit/entity/Boat.java b/src/main/java/org/bukkit/entity/Boat.java -index 24751b5c4e3bc24bdfa85af8f6fcba37413aa002..e0d0537606d4f9a3fe588ebf7d02f314c0359335 100644 ---- a/src/main/java/org/bukkit/entity/Boat.java -+++ b/src/main/java/org/bukkit/entity/Boat.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity; - -+import org.bukkit.Material; - import org.bukkit.TreeSpecies; - import org.jetbrains.annotations.NotNull; - -@@ -103,4 +104,14 @@ public interface Boat extends Vehicle { - */ - @Deprecated - public void setWorkOnLand(boolean workOnLand); -+ -+ // Paper start -+ /** -+ * Gets the {@link Material} that represents this Boat type. -+ * -+ * @return the boat material. -+ */ -+ @NotNull -+ public Material getBoatMaterial(); -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Minecart.java b/src/main/java/org/bukkit/entity/Minecart.java -index 95c79c5fa0c4e30201f887da6467ce5f81c8a255..53b042f8ebbbf6ee77435b93d4e89371375cc515 100644 ---- a/src/main/java/org/bukkit/entity/Minecart.java -+++ b/src/main/java/org/bukkit/entity/Minecart.java -@@ -1,5 +1,6 @@ - package org.bukkit.entity; - -+import org.bukkit.Material; - import org.bukkit.block.data.BlockData; - import org.bukkit.material.MaterialData; - import org.bukkit.util.Vector; -@@ -143,4 +144,14 @@ public interface Minecart extends Vehicle { - * @return the current block offset for this minecart. - */ - public int getDisplayBlockOffset(); -+ -+ // Paper start -+ /** -+ * Gets the {@link Material} that represents this Minecart type. -+ * -+ * @return the minecart material. -+ */ -+ @NotNull -+ public Material getMinecartMaterial(); -+ // Paper end - } diff --git a/Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch b/Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index d9cd5a9f0160..000000000000 --- a/Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:44:19 -0700 -Subject: [PATCH] Add PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4c141f3d8f668cdf9c75865a8e3ecbd012d9e521 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerFlowerPotManipulateEvent.java -@@ -0,0 +1,82 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player places an item in or takes an item out of a flowerpot. -+ */ -+public class PlayerFlowerPotManipulateEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ @NotNull -+ private final Block flowerpot; -+ @NotNull -+ private final ItemStack item; -+ private final boolean placing; -+ -+ private boolean cancel = false; -+ -+ public PlayerFlowerPotManipulateEvent(@NotNull final Player player, @NotNull final Block flowerpot, @NotNull final ItemStack item, final boolean placing) { -+ super(player); -+ this.flowerpot = flowerpot; -+ this.item = item; -+ this.placing = placing; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancel; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancel = cancel; -+ } -+ -+ /** -+ * Gets the flowerpot that is involved in this event. -+ * -+ * @return the flowerpot that is involved with this event -+ */ -+ @NotNull -+ public Block getFlowerpot() { -+ return flowerpot; -+ } -+ -+ /** -+ * Gets the item being placed, or taken from, the flower pot. -+ * Check if placing with {@link #isPlacing()}. -+ * -+ * @return the item placed, or taken from, the flowerpot -+ */ -+ @NotNull -+ public ItemStack getItem() { -+ return item; -+ } -+ -+ /** -+ * Gets if the item is being placed into the flowerpot. -+ * -+ * @return if the item is being placed into the flowerpot -+ */ -+ public boolean isPlacing() { -+ return placing; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch b/Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch deleted file mode 100644 index e2a1a8350ebe..000000000000 --- a/Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:15 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/org/bukkit/entity/Zombie.java b/src/main/java/org/bukkit/entity/Zombie.java -index 1217576e6f08abf0175ab800cfca058d5deda116..a39fbc9fa0903be8ed8e89f3ef39f93c02dfc90b 100644 ---- a/src/main/java/org/bukkit/entity/Zombie.java -+++ b/src/main/java/org/bukkit/entity/Zombie.java -@@ -140,5 +140,19 @@ public interface Zombie extends Monster, Ageable { - * @param shouldBurnInDay True to burn in sunlight - */ - void setShouldBurnInDay(boolean shouldBurnInDay); -+ -+ /** -+ * Check if this zombie can break doors -+ * -+ * @return True if zombie can break doors -+ */ -+ boolean canBreakDoors(); -+ -+ /** -+ * Sets if this zombie can break doors -+ * -+ * @param canBreakDoors True if zombie can break doors -+ */ -+ void setCanBreakDoors(boolean canBreakDoors); - // Paper end - } diff --git a/Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch b/Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index f484d40cca5d..000000000000 --- a/Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:17 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..287f487b266d5c12fcf6f028452735e314d55636 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/EntityLoadCrossbowEvent.java -@@ -0,0 +1,101 @@ -+package io.papermc.paper.event.entity; -+ -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.bukkit.inventory.EquipmentSlot; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a LivingEntity loads a crossbow with a projectile. -+ */ -+public class EntityLoadCrossbowEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final ItemStack crossbow; -+ private final EquipmentSlot hand; -+ private boolean cancelled; -+ private boolean consumeItem = true; -+ -+ public EntityLoadCrossbowEvent(@NotNull LivingEntity entity, @Nullable ItemStack crossbow, @NotNull EquipmentSlot hand) { -+ super(entity); -+ this.crossbow = crossbow; -+ this.hand = hand; -+ } -+ -+ @NotNull -+ @Override -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ /** -+ * Gets the crossbow {@link ItemStack} being loaded. -+ * -+ * @return the crossbow involved in this event -+ */ -+ @Nullable -+ public ItemStack getCrossbow() { -+ return crossbow; -+ } -+ -+ /** -+ * Gets the hand from which the crossbow was loaded. -+ * -+ * @return the hand -+ */ -+ @NotNull -+ public EquipmentSlot getHand() { -+ return hand; -+ } -+ -+ /** -+ * -+ * @return should the itemstack be consumed -+ */ -+ public boolean shouldConsumeItem() { -+ return consumeItem; -+ } -+ -+ /** -+ * -+ * @param consume should the item be consumed -+ */ -+ public void setConsumeItem(boolean consume) { -+ this.consumeItem = consume; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Set whether or not to cancel the crossbow being loaded. If canceled, the -+ * projectile that would be loaded into the crossbow will not be consumed. -+ * -+ * If set to false, and this event is pertaining to a player entity, -+ * it's recommended that a call to {@link Player#updateInventory()} is made -+ * as the client may think the server still loaded an item into the crossbow. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch b/Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch deleted file mode 100644 index 8ef5f7efcdb3..000000000000 --- a/Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..20c25a0f9d65188402e8bb3981348bc6462904bf ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/WorldGameRuleChangeEvent.java -@@ -0,0 +1,91 @@ -+package io.papermc.paper.event.world; -+ -+import org.bukkit.GameRule; -+import org.bukkit.World; -+import org.bukkit.command.CommandSender; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a world's gamerule is changed, either by command or by api. -+ */ -+public class WorldGameRuleChangeEvent extends WorldEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final CommandSender commandSender; -+ private final GameRule gameRule; -+ private String value; -+ private boolean cancelled; -+ -+ public WorldGameRuleChangeEvent(@NotNull World world, @Nullable CommandSender commandSender, @NotNull GameRule gameRule, @NotNull String value) { -+ super(world); -+ this.commandSender = commandSender; -+ this.gameRule = gameRule; -+ this.value = value; -+ } -+ -+ /** -+ * Gets the command sender associated with this event. -+ * -+ * @return {@code null} if the gamerule was changed via api, otherwise the {@link CommandSender}. -+ */ -+ @Nullable -+ public CommandSender getCommandSender() { -+ return commandSender; -+ } -+ -+ /** -+ * Gets the game rule associated with this event. -+ * -+ * @return the gamerule being changed. -+ */ -+ @NotNull -+ public GameRule getGameRule() { -+ return gameRule; -+ } -+ -+ /** -+ * Gets the new value of the gamerule. -+ * -+ * @return the new value of the gamerule. -+ */ -+ @NotNull -+ public String getValue() { -+ return value; -+ } -+ -+ /** -+ * Sets the new value of this gamerule. -+ * -+ * @param value the new value of the gamerule. -+ */ -+ public void setValue(@NotNull String value) { -+ this.value = value; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch b/Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index de081bbae793..000000000000 --- a/Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:16 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7a8d6815c17a107039399298f7ac9f0612faee02 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/server/ServerResourcesReloadedEvent.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.event.server; -+ -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.server.ServerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when resources such as datapacks are reloaded (e.g. /minecraft:reload) -+ *

-+ * Intended for use to re-register custom recipes, advancements that may be lost during a reload like this. -+ *

-+ */ -+public class ServerResourcesReloadedEvent extends ServerEvent { -+ -+ public static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final Cause cause; -+ -+ public ServerResourcesReloadedEvent(@NotNull Cause cause) { -+ this.cause = cause; -+ } -+ -+ /** -+ * Gets the cause of the resource reload. -+ * -+ * @return the reload cause -+ */ -+ @NotNull -+ public Cause getCause() { -+ return cause; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ public enum Cause { -+ COMMAND, -+ PLUGIN, -+ } -+} diff --git a/Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch b/Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch deleted file mode 100644 index 126714b965c3..000000000000 --- a/Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:23 +0200 -Subject: [PATCH] Add BlockFailedDispenseEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dab794341170ed10d5a05c1b4c180d164e0f70e2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BlockFailedDispenseEvent.java -@@ -0,0 +1,57 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a block tries to dispense an item, but its inventory is empty. -+ */ -+public class BlockFailedDispenseEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private boolean shouldPlayEffect = true; -+ -+ public BlockFailedDispenseEvent(@NotNull Block theBlock) { -+ super(theBlock); -+ } -+ -+ /** -+ * @return if the effect should be played -+ */ -+ public boolean shouldPlayEffect() { -+ return this.shouldPlayEffect; -+ } -+ -+ /** -+ * Sets if the effect for empty dispensers should be played -+ * -+ * @param playEffect if the effect should be played -+ */ -+ public void shouldPlayEffect(boolean playEffect) { -+ this.shouldPlayEffect = playEffect; -+ } -+ -+ /** -+ * {@inheritDoc} -+ * -+ * @return {@link #shouldPlayEffect()} -+ */ -+ @Override -+ public boolean callEvent() { -+ super.callEvent(); -+ return this.shouldPlayEffect(); -+ } -+ -+ @Override -+ public @NotNull -+ HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ public static @NotNull -+ HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch b/Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index 2b65c3a24526..000000000000 --- a/Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:16 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..26370e46e4a12e3470e9bb747fac5786a7305810 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerLecternPageChangeEvent.java -@@ -0,0 +1,115 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Lectern; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PlayerLecternPageChangeEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final Lectern lectern; -+ private final ItemStack book; -+ private final PageChangeDirection pageChangeDirection; -+ private final int oldPage; -+ private int newPage; -+ -+ public PlayerLecternPageChangeEvent(@NotNull Player player, @NotNull Lectern lectern, @NotNull ItemStack book, @NotNull PageChangeDirection pageChangeDirection, int oldPage, int newPage) { -+ super(player); -+ this.lectern = lectern; -+ this.book = book; -+ this.pageChangeDirection = pageChangeDirection; -+ this.oldPage = oldPage; -+ this.newPage = newPage; -+ } -+ -+ /** -+ * Gets the lectern involved. -+ * -+ * @return the Lectern -+ */ -+ @NotNull -+ public Lectern getLectern() { -+ return lectern; -+ } -+ -+ /** -+ * Gets the current ItemStack on the lectern. -+ * -+ * @return the ItemStack on the Lectern -+ */ -+ @NotNull -+ public ItemStack getBook() { -+ return this.book; -+ } -+ -+ /** -+ * Gets the page change direction. This is essentially returns which button the player clicked, left or right. -+ * -+ * @return the page change direction -+ */ -+ @NotNull -+ public PageChangeDirection getPageChangeDirection() { -+ return pageChangeDirection; -+ } -+ -+ /** -+ * Gets the page changed from. Pages are 0-indexed. -+ * -+ * @return the page changed from -+ */ -+ public int getOldPage() { -+ return oldPage; -+ } -+ -+ /** -+ * Gets the page changed to. Pages are 0-indexed. -+ * -+ * @return the page changed to -+ */ -+ public int getNewPage() { -+ return newPage; -+ } -+ -+ /** -+ * Sets the page changed to. Pages are 0-indexed. -+ * Page indices that are greater than the number of pages will show the last page. -+ * -+ * @param newPage the new paged changed to -+ */ -+ public void setNewPage(int newPage) { -+ this.newPage = newPage; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public enum PageChangeDirection { -+ LEFT, -+ RIGHT, -+ } -+} diff --git a/Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch b/Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index 567702695669..000000000000 --- a/Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:42 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8cb05709f7cb5dee993ff6fea1626c41b90a7d8b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerLoomPatternSelectEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.banner.PatternType; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.LoomInventory; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player selects a banner patten in a loom inventory. -+ */ -+public class PlayerLoomPatternSelectEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final LoomInventory loomInventory; -+ private PatternType patternType; -+ -+ public PlayerLoomPatternSelectEvent(@NotNull Player player, @NotNull LoomInventory loomInventory, @NotNull PatternType patternType) { -+ super(player); -+ this.loomInventory = loomInventory; -+ this.patternType = patternType; -+ } -+ -+ /** -+ * Gets the loom inventory involved. -+ * -+ * @return the loom inventory -+ */ -+ @NotNull -+ public LoomInventory getLoomInventory() { -+ return loomInventory; -+ } -+ -+ /** -+ * Gets the pattern type selected. -+ * -+ * @return the pattern type -+ */ -+ @NotNull -+ public PatternType getPatternType() { -+ return patternType; -+ } -+ -+ /** -+ * Sets the pattern type selected. -+ * -+ * @param patternType the pattern type -+ */ -+ public void setPatternType(@NotNull PatternType patternType) { -+ this.patternType = patternType; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch b/Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch deleted file mode 100644 index 2a40d2b44f28..000000000000 --- a/Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 3 Dec 2020 14:04:57 -0800 -Subject: [PATCH] Better AnnotationTest printout - - -diff --git a/pom.xml b/pom.xml -index 6b71d9a397dd5b72320402a47b8e7197d24e061c..73fbd5d5a591871a3a386fb5c455cd96a3992e7a 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -257,6 +257,19 @@ - true - - -+ -+ org.apache.maven.plugins -+ maven-surefire-plugin -+ 2.22.2 -+ -+ -+ -+ listener -+ io.papermc.paper.JunitEventListener -+ -+ -+ -+ - - org.apache.maven.plugins - maven-javadoc-plugin -diff --git a/src/test/java/io/papermc/paper/JunitEventListener.java b/src/test/java/io/papermc/paper/JunitEventListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..072ac1a96394b8d494f42fca8dfe08115eaed3fe ---- /dev/null -+++ b/src/test/java/io/papermc/paper/JunitEventListener.java -@@ -0,0 +1,6 @@ -+package io.papermc.paper; -+ -+import org.junit.runner.notification.RunListener; -+ -+public class JunitEventListener extends RunListener { -+} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 03229d5f4ec36a82197beb391356d791ff67fb2f..19271057cf24329757c9419fa6c97848e008a96c 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -107,13 +107,18 @@ public class AnnotationTest { - - Collections.sort(errors); - -- System.out.println(errors.size() + " missing annotation(s):"); -+ StringBuilder builder = new StringBuilder() -+ .append("There ") -+ .append(errors.size() != 1 ? "are " : "is ") -+ .append(errors.size()) -+ .append(" missing annotation") -+ .append(errors.size() != 1 ? "s:\n" : ":\n"); -+ - for (String message : errors) { -- System.out.print("\t"); -- System.out.println(message); -+ builder.append("\t").append(message).append("\n"); - } - -- Assert.fail("There " + errors.size() + " are missing annotation(s)"); -+ Assert.fail(builder.toString()); - } - - private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { diff --git a/Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch deleted file mode 100644 index 197d00ca140c..000000000000 --- a/Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:55 +1000 -Subject: [PATCH] Add API to get exact interaction point in PlayerInteractEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -index 1208e1f8c2163d83c5b12bbb9b7ac044c72380e0..a01f86e6aba8b66ecc713da0787cd861e2930a2a 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java -@@ -1,5 +1,6 @@ - package org.bukkit.event.player; - -+import org.bukkit.Location; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.BlockFace; -@@ -34,22 +35,30 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { - private Result useClickedBlock; - private Result useItemInHand; - private EquipmentSlot hand; -+ private Location interactionPoint; // Paper - - public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace) { - this(who, action, item, clickedBlock, clickedFace, EquipmentSlot.HAND); - } - - public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand) { -+ // Paper start - Add interactionPoint -+ this(who, action, item, clickedBlock, clickedFace, hand, null); -+ } -+ -+ public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand, @Nullable final Location interactionPoint) { - super(who); - this.action = action; - this.item = item; - this.blockClicked = clickedBlock; - this.blockFace = clickedFace; - this.hand = hand; -+ this.interactionPoint = interactionPoint; - - useItemInHand = Result.DEFAULT; - useClickedBlock = clickedBlock == null ? Result.DENY : Result.ALLOW; - } -+ // Paper end - - /** - * Returns the action type -@@ -221,6 +230,18 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { - return hand; - } - -+ // Paper start -+ /** -+ * The exact point at which the interaction occurred. May be null. -+ * -+ * @return the exact interaction point. May be null. -+ */ -+ @Nullable -+ public Location getInteractionPoint() { -+ return interactionPoint; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { diff --git a/Spigot-API-Patches/0259-Add-sendOpLevel-API.patch b/Spigot-API-Patches/0259-Add-sendOpLevel-API.patch deleted file mode 100644 index d1a8696b2d2b..000000000000 --- a/Spigot-API-Patches/0259-Add-sendOpLevel-API.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:02:57 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 7aa9fb852dce23c53fee80e97e0dcdb278ae82ba..68a03821a5f06308a9c51fdf107d3924c44886c8 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1929,6 +1929,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - @Nullable - Firework boostElytra(@NotNull ItemStack firework); -+ -+ /** -+ * Send a packet to the player indicating its operator status level. -+ *

-+ * Note: This will not persist across more than the current connection, and setting the player's operator -+ * status as a later point will override the effects of this. -+ * -+ * @param level The level to send to the player. Must be in {@code [0, 4]}. -+ * @throws IllegalArgumentException If the level is negative or greater than {@code 4} (i.e. not within {@code [0, 4]}). -+ */ -+ void sendOpLevel(byte level); - // Paper end - - // Spigot start diff --git a/Spigot-API-Patches/0260-Add-StructureLocateEvent.patch b/Spigot-API-Patches/0260-Add-StructureLocateEvent.patch deleted file mode 100644 index 88c14d8ea610..000000000000 --- a/Spigot-API-Patches/0260-Add-StructureLocateEvent.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Tue, 15 Sep 2020 21:59:16 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..45b6694fc5741831e2df638b1f760a3ca28a4907 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java -@@ -0,0 +1,155 @@ -+package io.papermc.paper.event.world; -+ -+import org.bukkit.Location; -+import org.bukkit.StructureType; -+import org.bukkit.World; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called before a structure/feature is located. -+ * This happens when: -+ *

    -+ *
  • The /locate command is used.
  • -+ *
  • An Eye of Ender is used.
  • -+ *
  • An Explorer/Treasure Map is activated.
  • -+ *
  • {@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.
  • -+ *
-+ */ -+public class StructureLocateEvent extends WorldEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final Location origin; -+ private Location result = null; -+ private StructureType type; -+ private int radius; -+ private boolean findUnexplored; -+ private boolean cancelled = false; -+ -+ public StructureLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored) { -+ super(world); -+ this.origin = origin; -+ this.type = structureType; -+ this.radius = radius; -+ this.findUnexplored = findUnexplored; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ /** -+ * Gets the location set as the structure location, if it was defined. -+ *

-+ * Returns {@code null} if it has not been set by {@link StructureLocateEvent#setResult(Location)}. -+ * Since this event fires before the search is done, the actual location is unknown at this point. -+ * -+ * @return The result location, if it has been set. null if it has not. -+ * @see World#locateNearestStructure(Location, StructureType, int, boolean) -+ */ -+ @Nullable -+ public Location getResult() { -+ return result; -+ } -+ -+ /** -+ * Sets the result {@link Location}. This causes the search to be skipped, and the location passed here to be used as the result. -+ * -+ * @param result the {@link Location} of the structure. -+ */ -+ public void setResult(@Nullable Location result) { -+ this.result = result; -+ } -+ -+ /** -+ * Gets the {@link StructureType} that is to be located. -+ * -+ * @return the structure type. -+ */ -+ @NotNull -+ public StructureType getType() { -+ return type; -+ } -+ -+ /** -+ * Sets the {@link StructureType} that is to be located. -+ * -+ * @param type the structure type. -+ */ -+ public void setType(@NotNull StructureType type) { -+ this.type = type; -+ } -+ -+ /** -+ * Gets the {@link Location} from which the search is to be conducted. -+ * -+ * @return {@link Location} where search begins -+ */ -+ @NotNull -+ public Location getOrigin() { -+ return origin; -+ } -+ -+ /** -+ * Gets the search radius in which to attempt locating the structure. -+ *

-+ * This radius may not always be obeyed during the structure search! -+ * -+ * @return the search radius. -+ */ -+ public int getRadius() { -+ return radius; -+ } -+ -+ /** -+ * Sets the search radius in which to attempt locating the structure. -+ *

-+ * This radius may not always be obeyed during the structure search! -+ * -+ * @param radius the search radius. -+ */ -+ public void setRadius(int radius) { -+ this.radius = radius; -+ } -+ -+ /** -+ * Gets whether to search exclusively for unexplored structures. -+ *

-+ * As with the search radius, this value is not always obeyed. -+ * -+ * @return Whether to search for only unexplored structures. -+ */ -+ public boolean shouldFindUnexplored() { -+ return findUnexplored; -+ } -+ -+ /** -+ * Sets whether to search exclusively for unexplored structures. -+ *

-+ * As with the search radius, this value is not always obeyed. -+ * -+ * @param findUnexplored Whether to search for only unexplored structures. -+ */ -+ public void setFindUnexplored(boolean findUnexplored) { -+ this.findUnexplored = findUnexplored; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch b/Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index e7986f5bb15e..000000000000 --- a/Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 664de64b020cf9090a2fbee0afe2bfaf150adc3c..b06995aa57aa9cba0bb59f1d26d81015619a08e6 100644 ---- a/src/main/java/org/bukkit/inventory/InventoryView.java -+++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -450,7 +450,7 @@ public abstract class InventoryView { - /** - * Get the title of this inventory window. - * -- * @return The title. -+ * @return The title or empty string when title is {@code null}. - */ - @NotNull - public /*abstract*/ net.kyori.adventure.text.Component title() { diff --git a/Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch b/Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch deleted file mode 100644 index 585039117584..000000000000 --- a/Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:15:54 +1000 -Subject: [PATCH] Add BlockPreDispenseEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..07aad3f4ff60a6a6de69634b0d31926e9c00e77b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BlockPreDispenseEvent.java -@@ -0,0 +1,60 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Block; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.bukkit.inventory.ItemStack; -+import org.jetbrains.annotations.NotNull; -+ -+public class BlockPreDispenseEvent extends BlockEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean cancelled = false; -+ private final ItemStack itemStack; -+ private final int slot; -+ -+ public BlockPreDispenseEvent(@NotNull Block block, @NotNull ItemStack itemStack, int slot) { -+ super(block); -+ this.itemStack = itemStack; -+ this.slot = slot; -+ } -+ -+ /** -+ * Gets the {@link ItemStack} to be dispensed. -+ * -+ * @return The item to be dispensed -+ */ -+ @NotNull -+ public ItemStack getItemStack() { -+ return itemStack; -+ } -+ -+ /** -+ * Gets the inventory slot of the dispenser to dispense from. -+ * -+ * @return The inventory slot -+ */ -+ public int getSlot() { -+ return slot; -+ } -+ -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+} diff --git a/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch b/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index 9916b1726bcb..000000000000 --- a/Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:40 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java -index 3c2a6a2167eab43097f5d6ccf1550e12795fc0b6..c1ec099448d57f2a5f973ac5b4e4a25b79ea2112 100644 ---- a/src/main/java/org/bukkit/Tag.java -+++ b/src/main/java/org/bukkit/Tag.java -@@ -425,6 +425,32 @@ public interface Tag extends Keyed { - * Vanilla fluid tag representing water and flowing water. - */ - Tag FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class); -+ // Paper start -+ /** -+ * Key for the build in entity registry -+ */ -+ String REGISTRY_ENTITIES = "entities"; -+ /** -+ * Vanilla entity tag representing arrow entities. -+ */ -+ Tag ARROWS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("arrows"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag representing entities that live in beehives -+ */ -+ Tag BEEHIVE_INHABITORS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("beehive_inhabitors"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag representing projectiles that impact -+ */ -+ Tag IMPACT_PROJECTILES = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("impact_projectiles"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag for village raiders -+ */ -+ Tag RAIDERS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("raiders"), org.bukkit.entity.EntityType.class); -+ /** -+ * Vanilla entity tag for skeleton types -+ */ -+ Tag SKELETONS = Bukkit.getTag(REGISTRY_ENTITIES, NamespacedKey.minecraft("skeletons"), org.bukkit.entity.EntityType.class); -+ // Paper end - - /** - * Returns whether or not this tag has an entry for the specified item. diff --git a/Spigot-API-Patches/0264-added-Wither-API.patch b/Spigot-API-Patches/0264-added-Wither-API.patch deleted file mode 100644 index dbfc15a42c2c..000000000000 --- a/Spigot-API-Patches/0264-added-Wither-API.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:40 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java -index 426d3693317cd303d35d8203026b528d87e401d5..8c95cd6933f11076de936854f379e6fc8600b525 100644 ---- a/src/main/java/org/bukkit/entity/Wither.java -+++ b/src/main/java/org/bukkit/entity/Wither.java -@@ -6,4 +6,34 @@ import com.destroystokyo.paper.entity.RangedEntity; - * Represents a Wither boss - */ - public interface Wither extends Monster, Boss, RangedEntity { // Paper -+ // Paper start -+ /** -+ * @return whether the wither is charged -+ */ -+ boolean isCharged(); -+ -+ /** -+ * @return ticks the wither is invulnerable for -+ */ -+ int getInvulnerableTicks(); -+ -+ /** -+ * Sets for how long in the future, the wither should be invulnerable. -+ * -+ * @param ticks ticks the wither is invulnerable for -+ */ -+ void setInvulnerableTicks(int ticks); -+ -+ /** -+ * @return whether the wither can travel through portals -+ */ -+ boolean canTravelThroughPortals(); -+ -+ /** -+ * Sets whether the wither can travel through portals. -+ * -+ * @param value whether the wither can travel through portals -+ */ -+ void setCanTravelThroughPortals(boolean value); -+ // Paper end - } diff --git a/Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch b/Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index 4331e880bb9a..000000000000 --- a/Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:12:18 -0600 -Subject: [PATCH] Added PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c80183a79713b1e73549911e474a8c585cfdeb52 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerChangeBeaconEffectEvent.java -@@ -0,0 +1,141 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.potion.PotionEffectType; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a player sets the effect for a beacon -+ */ -+public class PlayerChangeBeaconEffectEvent extends PlayerEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ private PotionEffectType primary; -+ private PotionEffectType secondary; -+ private final Block beacon; -+ private boolean consumeItem = true; -+ -+ private boolean isCancelled; -+ -+ public PlayerChangeBeaconEffectEvent(@NotNull Player player, @Nullable PotionEffectType primary, @Nullable PotionEffectType secondary, @Nullable Block beacon) { -+ super(player); -+ this.primary = primary; -+ this.secondary = secondary; -+ this.isCancelled = false; -+ this.beacon = beacon; -+ } -+ -+ /** -+ * @return the primary effect -+ */ -+ @Nullable public PotionEffectType getPrimary() { -+ return primary; -+ } -+ -+ /** -+ * Sets the primary effect -+ *

-+ * NOTE: The primary effect still has to be one of the valid effects for a beacon. -+ * -+ * @param primary the primary effect -+ */ -+ public void setPrimary(@Nullable PotionEffectType primary) { -+ this.primary = primary; -+ } -+ -+ /** -+ * @return the secondary effect -+ */ -+ @Nullable public PotionEffectType getSecondary() { -+ return secondary; -+ } -+ -+ /** -+ * Sets the secondary effect -+ *

-+ * This only has an effect when the beacon is able to accept a secondary effect. -+ * NOTE: The secondary effect still has to be a valid effect for a beacon. -+ * -+ * @param secondary the secondary effect -+ */ -+ public void setSecondary(@Nullable PotionEffectType secondary) { -+ this.secondary = secondary; -+ } -+ -+ /** -+ * @return the beacon block associated with this event, or null if not found -+ */ -+ @Nullable -+ public Block getBeacon() { -+ return beacon; -+ } -+ -+ /** -+ * Gets if the item used to change the beacon will be consume. -+ *

-+ * Independant of {@link #isCancelled()}. If the event is cancelled -+ * the item will NOT be consumed. -+ * -+ * @return true if item will be consumed -+ */ -+ public boolean willConsumeItem() { -+ return consumeItem; -+ } -+ -+ /** -+ * Sets if the item used to change the beacon should be consumed. -+ *

-+ * Independant of {@link #isCancelled()}. If the event is cancelled -+ * the item will NOT be consumed. -+ * -+ * @param consumeItem true if item should be consumed -+ */ -+ public void setConsumeItem(boolean consumeItem) { -+ this.consumeItem = consumeItem; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

-+ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will -+ * not take effect -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return this.isCancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ *

-+ * If cancelled, the item will NOT be consumed regardless of what {@link #willConsumeItem()} says -+ *

-+ * If a {@link PlayerChangeBeaconEffectEvent} is cancelled, the changes will not be applied -+ * or saved. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.isCancelled = cancel; -+ } -+ -+ @Override -+ public @NotNull HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index 1a81930699af..000000000000 --- a/Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 29 Jan 2021 15:13:04 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -index a33986a0c437a673435206fc337031a7eebdab3b..e0e068799a1868c8e561869015f41f553ef4fbdb 100644 ---- a/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -+++ b/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java -@@ -10,10 +10,19 @@ import org.jetbrains.annotations.NotNull; - public class EntityUnleashEvent extends EntityEvent { - private static final HandlerList handlers = new HandlerList(); - private final UnleashReason reason; -+ private boolean dropLeash; // Paper - -+ // Paper start - drop leash variable -+ @Deprecated - public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason) { -+ this(entity, reason, false); -+ } -+ -+ public EntityUnleashEvent(@NotNull Entity entity, @NotNull UnleashReason reason, boolean dropLeash) { - super(entity); -+ // Paper end - this.reason = reason; -+ this.dropLeash = dropLeash; // Paper - } - - /** -@@ -26,6 +35,26 @@ public class EntityUnleashEvent extends EntityEvent { - return reason; - } - -+ // Paper start -+ /** -+ * Returns whether a leash item will be dropped. -+ * -+ * @return Whether the leash item will be dropped -+ */ -+ public boolean isDropLeash() { -+ return dropLeash; -+ } -+ -+ /** -+ * Sets whether a leash item should be dropped. -+ * -+ * @param dropLeash Whether the leash item should be dropped -+ */ -+ public void setDropLeash(boolean dropLeash) { -+ this.dropLeash = dropLeash; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -index cf78950b56d4977f6c4d9d98d183bfc5ba3bacc0..68eab1563caba1ee4f52b308f390e4e172667fc5 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java -@@ -13,8 +13,15 @@ public class PlayerUnleashEntityEvent extends EntityUnleashEvent implements Canc - private final Player player; - private boolean cancelled = false; - -+ // Paper start - drop leash variable -+ @Deprecated - public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player) { -- super(entity, UnleashReason.PLAYER_UNLEASH); -+ this(entity, player, false); -+ } -+ -+ public PlayerUnleashEntityEvent(@NotNull Entity entity, @NotNull Player player, boolean dropLeash) { -+ super(entity, UnleashReason.PLAYER_UNLEASH, dropLeash); -+ // Paper end - this.player = player; - } - diff --git a/Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch b/Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index ce446c46fe27..000000000000 --- a/Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:13:59 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fb1bca3a9d12096c9a2b2663f466a8ff5f2b4319 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerStonecutterRecipeSelectEvent.java -@@ -0,0 +1,59 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.inventory.StonecutterInventory; -+import org.bukkit.inventory.StonecuttingRecipe; -+import org.jetbrains.annotations.NotNull; -+ -+public class PlayerStonecutterRecipeSelectEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ private final StonecutterInventory stonecutterInventory; -+ private StonecuttingRecipe stonecuttingRecipe; -+ -+ public PlayerStonecutterRecipeSelectEvent(@NotNull Player player, @NotNull StonecutterInventory stonecutterInventory, @NotNull StonecuttingRecipe stonecuttingRecipe) { -+ super(player); -+ this.stonecutterInventory = stonecutterInventory; -+ this.stonecuttingRecipe = stonecuttingRecipe; -+ } -+ -+ @NotNull -+ public StonecutterInventory getStonecutterInventory() { -+ return stonecutterInventory; -+ } -+ -+ @NotNull -+ public StonecuttingRecipe getStonecuttingRecipe() { -+ return stonecuttingRecipe; -+ } -+ -+ public void setStonecuttingRecipe(@NotNull StonecuttingRecipe stonecuttingRecipe) { -+ this.stonecuttingRecipe = stonecuttingRecipe; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Spigot-API-Patches/0268-EntityMoveEvent.patch b/Spigot-API-Patches/0268-EntityMoveEvent.patch deleted file mode 100644 index 0f5a4c5a81f4..000000000000 --- a/Spigot-API-Patches/0268-EntityMoveEvent.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Tue, 11 Feb 2020 21:56:38 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fae0b1daf733e85d8f691f5ef934b8c0b51db194 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/entity/EntityMoveEvent.java -@@ -0,0 +1,140 @@ -+package io.papermc.paper.event.entity; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.Location; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.entity.EntityEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Holds information for living entity movement events -+ */ -+public class EntityMoveEvent extends EntityEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private boolean canceled; -+ private Location from; -+ private Location to; -+ -+ public EntityMoveEvent(@NotNull LivingEntity entity, @NotNull Location from, @NotNull Location to) { -+ super(entity); -+ this.from = from; -+ this.to = to; -+ } -+ -+ @Override -+ @NotNull -+ public LivingEntity getEntity() { -+ return (LivingEntity) entity; -+ } -+ -+ public boolean isCancelled() { -+ return canceled; -+ } -+ -+ public void setCancelled(boolean cancel) { -+ canceled = cancel; -+ } -+ -+ /** -+ * Gets the location this entity moved from -+ * -+ * @return Location the entity moved from -+ */ -+ @NotNull -+ public Location getFrom() { -+ return from; -+ } -+ -+ /** -+ * Sets the location to mark as where the entity moved from -+ * -+ * @param from New location to mark as the entity's previous location -+ */ -+ public void setFrom(@NotNull Location from) { -+ validateLocation(from); -+ this.from = from; -+ } -+ -+ /** -+ * Gets the location this entity moved to -+ * -+ * @return Location the entity moved to -+ */ -+ @NotNull -+ public Location getTo() { -+ return to; -+ } -+ -+ /** -+ * Sets the location that this entity will move to -+ * -+ * @param to New Location this entity will move to -+ */ -+ public void setTo(@NotNull Location to) { -+ validateLocation(to); -+ this.to = to; -+ } -+ -+ /** -+ * Check if the entity has changed position (even within the same block) in the event -+ * -+ * @return whether the entity has changed position or not -+ */ -+ public boolean hasChangedPosition() { -+ return hasExplicitlyChangedPosition() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the entity has changed position (even within the same block) in the event, disregarding a possible world change -+ * -+ * @return whether the entity has changed position or not -+ */ -+ public boolean hasExplicitlyChangedPosition() { -+ return from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ(); -+ } -+ -+ /** -+ * Check if the entity has moved to a new block in the event -+ * -+ * @return whether the entity has moved to a new block or not -+ */ -+ public boolean hasChangedBlock() { -+ return hasExplicitlyChangedBlock() || !from.getWorld().equals(to.getWorld()); -+ } -+ -+ /** -+ * Check if the entity has moved to a new block in the event, disregarding a possible world change -+ * -+ * @return whether the entity has moved to a new block or not -+ */ -+ public boolean hasExplicitlyChangedBlock() { -+ return from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ(); -+ } -+ -+ /** -+ * Check if the entity has changed orientation in the event -+ * -+ * @return whether the entity has changed orientation or not -+ */ -+ public boolean hasChangedOrientation() { -+ return from.getPitch() != to.getPitch() || from.getYaw() != to.getYaw(); -+ } -+ -+ private void validateLocation(@NotNull Location loc) { -+ Preconditions.checkArgument(loc != null, "Cannot use null location!"); -+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); -+ } -+ -+ @Override -+ @NotNull -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0269-add-DragonEggFormEvent.patch b/Spigot-API-Patches/0269-add-DragonEggFormEvent.patch deleted file mode 100644 index c465295e880b..000000000000 --- a/Spigot-API-Patches/0269-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:49 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5495b87330518363498e1ac5d8f0a832be35fefb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/DragonEggFormEvent.java -@@ -0,0 +1,63 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.Block; -+import org.bukkit.block.BlockState; -+import org.bukkit.boss.DragonBattle; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockFormEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when the {@link EnderDragon} is defeated (killed) in a {@link DragonBattle}, -+ * causing a {@link Material#DRAGON_EGG} (more formally: {@link #getNewState()}) -+ * to possibly appear depending on {@link #isCancelled()}. -+ * This event might be cancelled by default depending on -+ * eg. {@link DragonBattle#hasBeenPreviouslyKilled()} and server configuration. -+ */ -+public class DragonEggFormEvent extends BlockFormEvent implements Cancellable { -+ private static final HandlerList handlers = new HandlerList(); -+ private final DragonBattle dragonBattle; -+ private boolean cancelled; -+ -+ public DragonEggFormEvent(@NotNull Block block, @NotNull BlockState newState, -+ @NotNull DragonBattle dragonBattle) { -+ super(block, newState); -+ this.dragonBattle = dragonBattle; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancelled) { -+ this.cancelled = cancelled; -+ } -+ -+ /** -+ * Gets the {@link DragonBattle} associated with this event. -+ * Keep in mind that the {@link EnderDragon} is already dead -+ * when this event is called. -+ * -+ * @return the dragon battle -+ */ -+ @NotNull -+ public DragonBattle getDragonBattle() { -+ return dragonBattle; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch b/Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index 984da00f52a2..000000000000 --- a/Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:25:26 -0600 -Subject: [PATCH] Allow adding items to BlockDropItemEvent - - -diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -index a0f6f1af304190b4c5db4b284d460f625eeb7801..3dd4bd38e72c04e74e5787fb38ca9abd10bad06b 100644 ---- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java -@@ -64,7 +64,7 @@ public class BlockDropItemEvent extends BlockEvent implements Cancellable { - * Gets list of the Item drops caused by the block break. - * - * This list is mutable - removing an item from it will cause it to not -- * drop. It is not legal however to add new items to the list. -+ * drop. Adding to the list is allowed. - * - * @return The Item the block caused to drop - */ diff --git a/Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index 6de1a3b39618..000000000000 --- a/Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:29 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -index ac140fc2c638e22e06b2920db3e376ab9e8c3733..f5e3bfd22d4d38182065b5215e5f78d9bb13381e 100644 ---- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -+++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java -@@ -458,4 +458,15 @@ public interface BukkitScheduler { - @Deprecated - @NotNull - public BukkitTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay, long period) throws IllegalArgumentException; -+ -+ // Paper start - add getMainThreadExecutor -+ /** -+ * Returns an executor that will run tasks on the next server tick. -+ * -+ * @param plugin the reference to the plugin scheduling tasks -+ * @return an executor associated with the given plugin -+ */ -+ @NotNull -+ public java.util.concurrent.Executor getMainThreadExecutor(@NotNull Plugin plugin); -+ // Paper end - } diff --git a/Spigot-API-Patches/0273-Add-missing-effects.patch b/Spigot-API-Patches/0273-Add-missing-effects.patch deleted file mode 100644 index 57086bea9cc4..000000000000 --- a/Spigot-API-Patches/0273-Add-missing-effects.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ivan Pekov -Date: Tue, 5 Jan 2021 10:19:11 +0200 -Subject: [PATCH] Add missing effects - - -diff --git a/src/main/java/org/bukkit/Effect.java b/src/main/java/org/bukkit/Effect.java -index d0c812c72967469122f7f276ced31cfb0e9482dc..0f598fa0560d14b44dcc65205364870c0bbfa0d8 100644 ---- a/src/main/java/org/bukkit/Effect.java -+++ b/src/main/java/org/bukkit/Effect.java -@@ -201,6 +201,65 @@ public enum Effect { - * The sound of an enderdragon growling - */ - ENDERDRAGON_GROWL(3001, Type.SOUND), -+ // Paper start - add missing effects -+ /** -+ * The sound of a wither spawning -+ */ -+ WITHER_SPAWNED(1023, Type.SOUND), -+ /** -+ * The sound of an ender dragon dying -+ */ -+ ENDER_DRAGON_DEATH(1028, Type.SOUND), -+ /** -+ * The sound of an ender portal being created in the overworld -+ */ -+ END_PORTAL_CREATED_IN_OVERWORLD(1038, Type.SOUND), -+ /** -+ * The sound of phantom's bites -+ */ -+ PHANTOM_BITES(1039, Type.SOUND), -+ /** -+ * The sound of zombie converting to drowned zombie -+ */ -+ ZOMBIE_CONVERTS_TO_DROWNED(1040, Type.SOUND), -+ /** -+ * The sound of a husk converting to zombie by drowning -+ */ -+ HUSK_CONVERTS_TO_ZOMBIE(1041, Type.SOUND), -+ /** -+ * The sound of a grindstone being used -+ */ -+ GRINDSTONE_USED(1042, Type.SOUND), -+ /** -+ * The sound of a book page being turned -+ */ -+ BOOK_PAGE_TURNED(1043, Type.SOUND), -+ /** -+ * Particles displayed when a composter composts -+ */ -+ COMPOSTER_COMPOSTS(1500, Type.VISUAL), -+ /** -+ * Particles displayed when lava converts a block (either water to stone, or -+ * removing existing blocks such as torches) -+ */ -+ LAVA_CONVERTS_BLOCK(1501, Type.VISUAL), -+ /** -+ * Particles displayd when a redstone torch burns out -+ */ -+ REDSTONE_TORCH_BURNS_OUT(1502, Type.VISUAL), -+ /** -+ * Particles displayed when an ender eye is placed -+ */ -+ ENDER_EYE_PLACED(1503, Type.VISUAL), -+ /** -+ * Particles displayed when an ender dragon destroys block -+ */ -+ ENDER_DRAGON_DESTROYS_BLOCK(2008, Type.VISUAL), -+ /** -+ * Particles displayed when a wet sponge vaporizes in nether. -+ */ -+ WET_SPONGE_VAPORIZES_IN_NETHER(2009, Type.VISUAL) -+ // Paper end - ; - - private final int id; diff --git a/Spigot-API-Patches/0274-Expose-Tracked-Players.patch b/Spigot-API-Patches/0274-Expose-Tracked-Players.patch deleted file mode 100644 index 1c4214897ca2..000000000000 --- a/Spigot-API-Patches/0274-Expose-Tracked-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 68a03821a5f06308a9c51fdf107d3924c44886c8..34b51466ffb281b05f531b3f7deda245ae7fd96a 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1,6 +1,7 @@ - package org.bukkit.entity; - - import java.net.InetSocketAddress; -+import java.util.Set; // Paper - import java.util.UUID; - import com.destroystokyo.paper.ClientOption; // Paper - import com.destroystokyo.paper.Title; // Paper -@@ -1942,6 +1943,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - void sendOpLevel(byte level); - // Paper end - -+ // Paper start -+ /** -+ * @return Returns a set of Players within this player's tracking range (that the player's client can "see") -+ */ -+ @NotNull -+ Set getTrackedPlayers(); -+ // Paper end -+ - // Spigot start - public class Spigot extends Entity.Spigot { - diff --git a/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch b/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch deleted file mode 100644 index eaa498baeaa7..000000000000 --- a/Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 2 Mar 2021 15:24:58 -0800 -Subject: [PATCH] Cache the result of Material#isBlock - - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index e453e5eb7245aad3ecbb19652ebb34abe030c0a9..112c3f035ec7e7a7cae939264e0af4c6f4450abd 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3522,6 +3522,7 @@ public enum Material implements Keyed { - public final Class data; - private final boolean legacy; - private final NamespacedKey key; -+ private boolean isBlock; // Paper - - private Material(final int id) { - this(id, 64); -@@ -3719,6 +3720,11 @@ public enum Material implements Keyed { - * @return true if this material is a block - */ - public boolean isBlock() { -+ // Paper start - cache isBlock -+ return this.isBlock; -+ } -+ private boolean isBlock0() { -+ // Paper end - switch (this) { - // - case ACACIA_BUTTON: -@@ -4664,6 +4670,7 @@ public enum Material implements Keyed { - static { - for (Material material : values()) { - BY_NAME.put(material.name(), material); -+ material.isBlock = material.isBlock0(); // Paper - } - } - diff --git a/Spigot-API-Patches/0276-Add-worldborder-events.patch b/Spigot-API-Patches/0276-Add-worldborder-events.patch deleted file mode 100644 index 09c3770e1628..000000000000 --- a/Spigot-API-Patches/0276-Add-worldborder-events.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 22:40:26 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..126fe50b519a8d7cd158f799058cb235f9c4cbdb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeEvent.java -@@ -0,0 +1,114 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a world border changes its bounds, either over time, or instantly. -+ */ -+public class WorldBorderBoundsChangeEvent extends WorldBorderEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private Type type; -+ private final double oldSize; -+ private double newSize; -+ private long duration; -+ private boolean cancelled; -+ -+ public WorldBorderBoundsChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Type type, double oldSize, double newSize, long duration) { -+ super(world, worldBorder); -+ this.type = type; -+ this.oldSize = oldSize; -+ this.newSize = newSize; -+ this.duration = duration; -+ } -+ -+ /** -+ * Gets if this change is an instant change or over-time change. -+ * -+ * @return the change type -+ */ -+ @NotNull -+ public Type getType() { -+ return type; -+ } -+ -+ /** -+ * Gets the old size or the world border. -+ * -+ * @return the old size -+ */ -+ public double getOldSize() { -+ return oldSize; -+ } -+ -+ /** -+ * Gets the new size of the world border. -+ * -+ * @return the new size -+ */ -+ public double getNewSize() { -+ return newSize; -+ } -+ -+ /** -+ * Sets the new size of the world border. -+ * -+ * @param newSize the new size -+ */ -+ public void setNewSize(double newSize) { -+ // PAIL: TODO: Magic Values -+ this.newSize = Math.min(6.0E7D, Math.max(1.0D, newSize)); -+ } -+ -+ /** -+ * Gets the time in milliseconds for the change. Will be 0 if instant. -+ * -+ * @return the time in milliseconds for the change -+ */ -+ public long getDuration() { -+ return duration; -+ } -+ -+ /** -+ * Sets the time in milliseconds for the change. Will change {@link #getType()} to return -+ * {@link Type#STARTED_MOVE}. -+ * -+ * @param duration the time in milliseconds for the change -+ */ -+ public void setDuration(long duration) { -+ // PAIL: TODO: Magic Values -+ this.duration = Math.min(9223372036854775L, Math.max(0L, duration)); -+ if (duration >= 0 && type == Type.INSTANT_MOVE) type = Type.STARTED_MOVE; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public enum Type { -+ STARTED_MOVE, -+ INSTANT_MOVE -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3d578ae2c5615b0ebace99d9bacf100b086c971 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderBoundsChangeFinishEvent.java -@@ -0,0 +1,65 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.HandlerList; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a moving world border has finished it's move. -+ */ -+public class WorldBorderBoundsChangeFinishEvent extends WorldBorderEvent { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final double oldSize; -+ private final double newSize; -+ private final double duration; -+ -+ public WorldBorderBoundsChangeFinishEvent(@NotNull World world, @NotNull WorldBorder worldBorder, double oldSize, double newSize, double duration) { -+ super(world, worldBorder); -+ this.oldSize = oldSize; -+ this.newSize = newSize; -+ this.duration = duration; -+ } -+ -+ /** -+ * Gets the old size of the worldborder. -+ * -+ * @return the old size -+ */ -+ public double getOldSize() { -+ return oldSize; -+ } -+ -+ /** -+ * Gets the new size of the worldborder. -+ * -+ * @return the new size -+ */ -+ public double getNewSize() { -+ return newSize; -+ } -+ -+ /** -+ * Gets the duration this worldborder took to make the change. -+ *

-+ * Can be 0 if handlers for {@link io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent} set the duration to 0. -+ * -+ * @return the duration of the transition -+ */ -+ public double getDuration() { -+ return duration; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4a10c773a8d05a596066e63306dead74c1363fd7 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderCenterChangeEvent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a world border's center is changed. -+ */ -+public class WorldBorderCenterChangeEvent extends WorldBorderEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final Location oldCenter; -+ private Location newCenter; -+ private boolean cancelled; -+ -+ public WorldBorderCenterChangeEvent(@NotNull World world, @NotNull WorldBorder worldBorder, @NotNull Location oldCenter, @NotNull Location newCenter) { -+ super(world, worldBorder); -+ this.oldCenter = oldCenter; -+ this.newCenter = newCenter; -+ } -+ -+ /** -+ * Gets the original center location of the world border. -+ * -+ * @return the old center -+ */ -+ @NotNull -+ public Location getOldCenter() { -+ return oldCenter; -+ } -+ -+ /** -+ * Gets the new center location for the world border. -+ * -+ * @return the new center -+ */ -+ @NotNull -+ public Location getNewCenter() { -+ return newCenter; -+ } -+ -+ /** -+ * Sets the new center location for the world border. Y coordinate is ignored. -+ * -+ * @param newCenter the new center -+ */ -+ public void setNewCenter(@NotNull Location newCenter) { -+ this.newCenter = newCenter; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..67bd469d3680c9554ce6c1d5493826a252682835 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/world/border/WorldBorderEvent.java -@@ -0,0 +1,22 @@ -+package io.papermc.paper.event.world.border; -+ -+import org.bukkit.World; -+import org.bukkit.WorldBorder; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.world.WorldEvent; -+import org.jetbrains.annotations.NotNull; -+ -+public abstract class WorldBorderEvent extends WorldEvent { -+ -+ private final WorldBorder worldBorder; -+ -+ public WorldBorderEvent(@NotNull World world, @NotNull WorldBorder worldBorder) { -+ super(world); -+ this.worldBorder = worldBorder; -+ } -+ -+ @NotNull -+ public WorldBorder getWorldBorder() { -+ return worldBorder; -+ } -+} diff --git a/Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch b/Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch deleted file mode 100644 index a38082f8e8d1..000000000000 --- a/Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:34:24 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java -new file mode 100755 -index 0000000000000000000000000000000000000000..ef9e53a73eff469bbaa8fb20c634297acb9d1986 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerNameEntityEvent.java -@@ -0,0 +1,118 @@ -+package io.papermc.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when the player is attempting to rename a mob -+ */ -+public class PlayerNameEntityEvent extends PlayerEvent implements Cancellable { -+ -+ private LivingEntity entity; -+ private Component name; -+ private boolean persistent; -+ private boolean cancelled; -+ -+ public PlayerNameEntityEvent(@NotNull Player player, @NotNull LivingEntity entity, @NotNull Component name, boolean persistent) { -+ super(player); -+ this.entity = entity; -+ this.name = name; -+ this.persistent = persistent; -+ } -+ -+ /** -+ * Gets the name to be given to the entity. -+ * @return the name -+ */ -+ @Nullable -+ public Component getName() { -+ return name; -+ } -+ -+ /** -+ * Sets the name to be given to the entity. -+ * -+ * @param name the name -+ */ -+ public void setName(@Nullable Component name) { -+ this.name = name; -+ } -+ -+ /** -+ * Gets the entity involved in this event. -+ * -+ * @return the entity -+ */ -+ @NotNull -+ public LivingEntity getEntity() { -+ return entity; -+ } -+ -+ /** -+ * Sets the entity involved in this event. -+ * -+ * @param entity the entity -+ */ -+ public void setEntity(@NotNull LivingEntity entity) { -+ this.entity = entity; -+ } -+ -+ /** -+ * Gets whether this will set the mob to be persistent. -+ * -+ * @return persistent -+ */ -+ public boolean isPersistent() { -+ return persistent; -+ } -+ -+ /** -+ * Sets whether this will set the mob to be persistent. -+ * -+ * @param persistent persistent -+ */ -+ public void setPersistent(boolean persistent) { -+ this.persistent = persistent; -+ } -+ -+ /** -+ * Gets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins -+ * -+ * @return true if this event is cancelled -+ */ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Sets the cancellation state of this event. A cancelled event will not -+ * be executed in the server, but will still pass to other plugins. -+ * -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch b/Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch deleted file mode 100644 index b0b34773c0f9..000000000000 --- a/Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:05:29 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/org/bukkit/event/block/BlockCookEvent.java b/src/main/java/org/bukkit/event/block/BlockCookEvent.java -index be7af5440bf9923f0c9c84efa4d70a89337a2f96..a3f1c9cb36c9069ed622985a525bfc2a7a27ab91 100644 ---- a/src/main/java/org/bukkit/event/block/BlockCookEvent.java -+++ b/src/main/java/org/bukkit/event/block/BlockCookEvent.java -@@ -14,12 +14,21 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { - private final ItemStack source; - private ItemStack result; - private boolean cancelled; -+ private final org.bukkit.inventory.CookingRecipe recipe; // Paper - -+ @Deprecated // Paper - public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result) { -+ // Paper start -+ this(block, source, result, null); -+ } -+ -+ public BlockCookEvent(@NotNull final Block block, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { -+ // Paper end - super(block); - this.source = source; - this.result = result; - this.cancelled = false; -+ this.recipe = recipe; // Paper - } - - /** -@@ -61,6 +70,18 @@ public class BlockCookEvent extends BlockEvent implements Cancellable { - this.cancelled = cancel; - } - -+ // Paper start -+ /** -+ * Gets the cooking recipe associated with this event. -+ * -+ * @return the recipe -+ */ -+ @org.jetbrains.annotations.Nullable -+ public org.bukkit.inventory.CookingRecipe getRecipe() { -+ return recipe; -+ } -+ // Paper end -+ - @NotNull - @Override - public HandlerList getHandlers() { -diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -index 066e7dd9a34d35c8b643a5efcf95d6a5ef47c7ee..16b3ab8f525c4e863f804cc8460a330407d85478 100644 ---- a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java -@@ -10,7 +10,13 @@ import org.jetbrains.annotations.NotNull; - */ - public class FurnaceSmeltEvent extends BlockCookEvent { - -+ @Deprecated // Paper - public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result) { - super(furnace, source, result); - } -+ // Paper start -+ public FurnaceSmeltEvent(@NotNull final Block furnace, @NotNull final ItemStack source, @NotNull final ItemStack result, @org.jetbrains.annotations.Nullable org.bukkit.inventory.CookingRecipe recipe) { -+ super(furnace, source, result, recipe); -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0279-Add-Block-isValidTool.patch b/Spigot-API-Patches/0279-Add-Block-isValidTool.patch deleted file mode 100644 index f037cf8c322b..000000000000 --- a/Spigot-API-Patches/0279-Add-Block-isValidTool.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:23 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 181658c679d306ffc4ad45259494571ee224ef47..08e6f1741685f54506c8a4ff29bbd30f62cf8e45 100644 ---- a/src/main/java/org/bukkit/block/Block.java -+++ b/src/main/java/org/bukkit/block/Block.java -@@ -218,6 +218,15 @@ public interface Block extends Metadatable { - public static int getBlockKeyZ(long packed) { - return (int) ((packed << 10) >> 37); - } -+ -+ /** -+ * Checks if the itemstack is a valid tool to -+ * break the block with -+ * -+ * @param itemStack The (tool) itemstack -+ * @return whether the block will drop items -+ */ -+ boolean isValidTool(@NotNull ItemStack itemStack); - // Paper End - - /** diff --git a/Spigot-API-Patches/0280-Implement-Keyed-on-World.patch b/Spigot-API-Patches/0280-Implement-Keyed-on-World.patch deleted file mode 100644 index 75f66d584850..000000000000 --- a/Spigot-API-Patches/0280-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:10 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e21baa41e 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -639,6 +639,18 @@ public final class Bukkit { - public static World getWorld(@NotNull UUID uid) { - return server.getWorld(uid); - } -+ // Paper start -+ /** -+ * Gets the world from the given NamespacedKey -+ * -+ * @param worldKey the NamespacedKey of the world to retrieve -+ * @return a world with the given NamespacedKey, or null if none exists -+ */ -+ @Nullable -+ public static World getWorld(@NotNull NamespacedKey worldKey) { -+ return server.getWorld(worldKey); -+ } -+ // Paper end - - /** - * Gets the map from the given item ID. -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5abf99e55 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -541,6 +541,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - @Nullable - public World getWorld(@NotNull UUID uid); - -+ // Paper start -+ /** -+ * Gets the world from the given NamespacedKey -+ * -+ * @param worldKey the NamespacedKey of the world to retrieve -+ * @return a world with the given NamespacedKey, or null if none exists -+ */ -+ @Nullable -+ public World getWorld(@NotNull NamespacedKey worldKey); -+ // Paper end -+ - /** - * Gets the map from the given item ID. - * -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index ced33fc6de6bfa2767123131d532e7ae9ef3a5be..98512bddbb0c8bd6a3f487c60b1ec77b274b991e 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -43,7 +43,7 @@ import org.jetbrains.annotations.Nullable; - /** - * Represents a world, which may contain entities, chunks and blocks - */ --public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper -+public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience, Keyed { // Paper - - // Paper start - /** -@@ -829,6 +829,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - - @NotNull - java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); -+ -+ /** -+ * Get the world's key -+ * -+ * @return the world's key -+ */ -+ @NotNull -+ @Override -+ NamespacedKey getKey(); - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java -index 6e6945dd4c770be04ec09da3958fae751717527a..e6a83252f42da31ad38f8dc1beccc7aa2c3f54b8 100644 ---- a/src/main/java/org/bukkit/WorldCreator.java -+++ b/src/main/java/org/bukkit/WorldCreator.java -@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; - * Represents various types of options that may be used to create a world. - */ - public class WorldCreator { -+ private final NamespacedKey key; // Paper - private final String name; - private long seed; - private World.Environment environment = World.Environment.NORMAL; -@@ -26,13 +27,67 @@ public class WorldCreator { - * @param name Name of the world that will be created - */ - public WorldCreator(@NotNull String name) { -- if (name == null) { -- throw new IllegalArgumentException("World name cannot be null"); -- } -+ // Paper start -+ this(name, NamespacedKey.minecraft(name.toLowerCase(java.util.Locale.ENGLISH).replace(" ", "_"))); -+ } - -- this.name = name; -+ /** -+ * Creates an empty WorldCreator for the given world name and key -+ * -+ * @param levelName LevelName of the world that will be created -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ public WorldCreator(@NotNull String levelName, @NotNull NamespacedKey worldKey) { -+ if (levelName == null || worldKey == null) { -+ throw new IllegalArgumentException("World name and key cannot be null"); -+ } -+ this.name = levelName; - this.seed = (new Random()).nextLong(); -+ this.key = worldKey; -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given key. -+ * LevelName will be the Key part of the NamespacedKey. -+ * -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ public WorldCreator(@NotNull NamespacedKey worldKey) { -+ this(worldKey.getKey(), worldKey); -+ } -+ -+ /** -+ * Gets the key for this WorldCreator -+ * -+ * @return the key -+ */ -+ @NotNull -+ public NamespacedKey key() { -+ return key; -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given world name and key -+ * -+ * @param levelName LevelName of the world that will be created -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ @NotNull -+ public static WorldCreator ofNameAndKey(@NotNull String levelName, @NotNull NamespacedKey worldKey) { -+ return new WorldCreator(levelName, worldKey); -+ } -+ -+ /** -+ * Creates an empty WorldCreator for the given key. -+ * LevelName will be the Key part of the NamespacedKey. -+ * -+ * @param worldKey NamespacedKey of the world that will be created -+ */ -+ @NotNull -+ public static WorldCreator ofKey(@NotNull NamespacedKey worldKey) { -+ return new WorldCreator(worldKey); - } -+ // Paper end - - /** - * Copies the options from the specified world diff --git a/Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch b/Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch deleted file mode 100644 index 4d216020ecda..000000000000 --- a/Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Fri, 12 Mar 2021 18:31:31 +0100 -Subject: [PATCH] fix Inventory#getContents null annotations - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 6386206188e820206bb1a9f516b5e194fdc9d952..7956aebcb390379677dccf7c9561866cf94c024c 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -158,9 +158,8 @@ public interface Inventory extends Iterable { - * - * @return An array of ItemStacks from the inventory. Individual items may be null. - */ -- @NotNull -- public ItemStack[] getContents(); -- -+ public @org.checkerframework.checker.nullness.qual.Nullable ItemStack @org.checkerframework.checker.nullness.qual.NonNull [] getContents(); // Paper - make array elements nullable instead array -+ - /** - * Completely replaces the inventory's contents. Removes all existing - * contents and replaces it with the ItemStacks given in the array. diff --git a/Spigot-API-Patches/0282-Item-Rarity-API.patch b/Spigot-API-Patches/0282-Item-Rarity-API.patch deleted file mode 100644 index 1d73fff91a1c..000000000000 --- a/Spigot-API-Patches/0282-Item-Rarity-API.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:40 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/io/papermc/paper/inventory/ItemRarity.java b/src/main/java/io/papermc/paper/inventory/ItemRarity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74ef8395cc040ce488c2acaa416db20272cc2734 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/inventory/ItemRarity.java -@@ -0,0 +1,28 @@ -+package io.papermc.paper.inventory; -+ -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextColor; -+import org.jetbrains.annotations.NotNull; -+ -+public enum ItemRarity { -+ -+ COMMON(NamedTextColor.WHITE), -+ UNCOMMON(NamedTextColor.YELLOW), -+ RARE(NamedTextColor.AQUA), -+ EPIC(NamedTextColor.LIGHT_PURPLE); -+ -+ TextColor color; -+ -+ ItemRarity(TextColor color) { -+ this.color = color; -+ } -+ -+ /** -+ * Gets the color formatting associated with the rarity. -+ * @return -+ */ -+ @NotNull -+ public TextColor getColor() { -+ return color; -+ } -+} -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 112c3f035ec7e7a7cae939264e0af4c6f4450abd..9b1c9e60dba9ea3ef8d8e164f13dd76daf57db8e 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3589,6 +3589,17 @@ public enum Material implements Keyed { - public String getTranslationKey() { - return Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ /** -+ * Returns the item rarity for the item. The Material MUST be an Item not a block. -+ * Use {@link #isItem()} before this. -+ * -+ * @return the item rarity -+ */ -+ @NotNull -+ public io.papermc.paper.inventory.ItemRarity getItemRarity() { -+ return Bukkit.getUnsafe().getItemRarity(this); -+ } - // Paper end - - /** -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 84eda68281c6c6968d95b1313a33696c3a9980d4..bcd10b2c9255d778b678310febf1937301d01a50 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -137,5 +137,22 @@ public interface UnsafeValues { - * Use this when sending custom packets, so that there are no collisions on the client or server. - */ - public int nextEntityId(); -+ -+ /** -+ * Gets the item rarity of a material. The material MUST be an item. -+ * Use {@link Material#isItem()} before this. -+ * -+ * @param material the material to get the rarity of -+ * @return the item rarity -+ */ -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(Material material); -+ -+ /** -+ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. -+ * -+ * @param itemStack the itemstack to get the rarity of -+ * @return the itemstack rarity -+ */ -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); - // Paper end - } -diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index c236cb81b7ec7993b63da929c0492564e75581ee..7929a00a3e93e0b6a4df99013e0da5bcfecd678b 100644 ---- a/src/main/java/org/bukkit/inventory/ItemStack.java -+++ b/src/main/java/org/bukkit/inventory/ItemStack.java -@@ -863,5 +863,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public String getTranslationKey() { - return Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ /** -+ * Gets the item rarity of the itemstack. The rarity can change based on enchantements. -+ * -+ * @return the itemstack rarity -+ */ -+ @NotNull -+ public io.papermc.paper.inventory.ItemRarity getRarity() { -+ return Bukkit.getUnsafe().getItemStackRarity(this); -+ } - // Paper end - } diff --git a/Spigot-API-Patches/0283-Expose-protocol-version.patch b/Spigot-API-Patches/0283-Expose-protocol-version.patch deleted file mode 100644 index f5e20e22d732..000000000000 --- a/Spigot-API-Patches/0283-Expose-protocol-version.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 26 Mar 2021 11:23:27 +0100 -Subject: [PATCH] Expose protocol version - - -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index bcd10b2c9255d778b678310febf1937301d01a50..6dbd520182b1e7713a68baad09b7f613424ef619 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -154,5 +154,12 @@ public interface UnsafeValues { - * @return the itemstack rarity - */ - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); -+ -+ /** -+ * Returns the server's protocol version. -+ * -+ * @return the server's protocol version -+ */ -+ int getProtocolVersion(); - // Paper end - } diff --git a/Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch b/Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index b0f198f0e1f9..000000000000 --- a/Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:15 -0700 -Subject: [PATCH] add isDeeplySleeping to HumanEntity - - -diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index f0e0710fef5a3e0b722ece7ccf89c3d0f88f8f0f..2ce774c81a93260a1464183d435b4c418ed61648 100644 ---- a/src/main/java/org/bukkit/entity/HumanEntity.java -+++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -319,6 +319,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder - */ - public void setCooldown(@NotNull Material material, int ticks); - -+ // Paper start -+ /** -+ * If the player has slept enough to count towards passing the night. -+ * -+ * @return true if the player has slept enough -+ */ -+ public boolean isDeeplySleeping(); -+ // Paper end -+ - /** - * Get the sleep ticks of the player. This value may be capped. - * diff --git a/Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch b/Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index 6c8b681cd94c..000000000000 --- a/Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:15 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -index bc71bc2d3ace0d19d730c09f05f9e0655bcee8f5..caef53d0f6546516fa7aabb2cb3abed70808b3ba 100644 ---- a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -+++ b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java -@@ -16,6 +16,7 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { - private int burnTime; - private boolean cancelled; - private boolean burning; -+ private boolean consumeFuel = true; // Paper - - public FurnaceBurnEvent(@NotNull final Block furnace, @NotNull final ItemStack fuel, final int burnTime) { - super(furnace); -@@ -70,6 +71,25 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { - public void setBurning(boolean burning) { - this.burning = burning; - } -+ // Paper start -+ /** -+ * Gets whether the furnace's fuel will be consumed or not. -+ * -+ * @return whether the furnace's fuel will be consumed -+ */ -+ public boolean willConsumeFuel() { -+ return consumeFuel; -+ } -+ -+ /** -+ * Sets whether the furnace's fuel will be consumed or not. -+ * -+ * @param consumeFuel true to consume the fuel -+ */ -+ public void setConsumeFuel(boolean consumeFuel) { -+ this.consumeFuel = consumeFuel; -+ } -+ // Paper end - - @Override - public boolean isCancelled() { diff --git a/Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch b/Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index 447a45db067f..000000000000 --- a/Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:20 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/inventory/EntityEquipment.java b/src/main/java/org/bukkit/inventory/EntityEquipment.java -index f905bf7a28a42d8bd2aecd42030d2b2092696fc3..58cfd450973f56bfbdd20f9dca8c1e7455260a55 100644 ---- a/src/main/java/org/bukkit/inventory/EntityEquipment.java -+++ b/src/main/java/org/bukkit/inventory/EntityEquipment.java -@@ -405,4 +405,32 @@ public interface EntityEquipment { - */ - @Nullable - Entity getHolder(); -+ // Paper start -+ /** -+ * Gets the drop chance of specified slot. -+ * -+ *

    -+ *
  • A drop chance of 0.0F will never drop -+ *
  • A drop chance of 1.0F will always drop -+ *
-+ * -+ * @param slot the slot to get the drop chance of -+ * @return the drop chance for the slot -+ */ -+ float getDropChance(@NotNull EquipmentSlot slot); -+ -+ /** -+ * Sets the drop chance of the specified slot. -+ * -+ *
    -+ *
  • A drop chance of 0.0F will never drop -+ *
  • A drop chance of 1.0F will always drop -+ *
-+ * -+ * @param slot the slot to set the drop chance of -+ * @param chance the drop chance for the slot -+ * @throws UnsupportedOperationException when called on players -+ */ -+ void setDropChance(@NotNull EquipmentSlot slot, float chance); -+ // Paper end - } diff --git a/Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch b/Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index d8dccca755a1..000000000000 --- a/Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:25 -0700 -Subject: [PATCH] Added PlayerDeepSleepEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e3ee540bb0a5bc578b148fbcf8b5e39ab9c8575c ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerDeepSleepEvent.java -@@ -0,0 +1,46 @@ -+package io.papermc.paper.event.player; -+ -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a player has slept long enough -+ * to count as passing the night/storm. -+ *

-+ * Cancelling this event will prevent the player from being counted as deeply sleeping -+ * unless they exit and re-enter the bed. -+ */ -+public class PlayerDeepSleepEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private boolean cancelled; -+ -+ public PlayerDeepSleepEvent(@NotNull Player player) { -+ super(player); -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ @Override -+ public void setCancelled(boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+} diff --git a/Spigot-API-Patches/0288-More-World-API.patch b/Spigot-API-Patches/0288-More-World-API.patch deleted file mode 100644 index 1a3c73561cc3..000000000000 --- a/Spigot-API-Patches/0288-More-World-API.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:53:22 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 98512bddbb0c8bd6a3f487c60b1ec77b274b991e..a1496fe00a2d5ba6c1af054d4327f868b2cd7344 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -3482,6 +3482,120 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - @Nullable - public Location locateNearestStructure(@NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored); - -+ // Paper start -+ /** -+ * Locates the nearest biome based on an origin, biome type, and radius to search. -+ * Step defaults to {@code 8}. -+ * -+ * @param origin Origin location -+ * @param biome Biome to find -+ * @param radius radius to search -+ * @return Location of biome or null if not found in specified radius -+ */ -+ @Nullable -+ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius); -+ -+ /** -+ * Locates the nearest biome based on an origin, biome type, and radius to search -+ * and step -+ * -+ * @param origin Origin location -+ * @param biome Biome to find -+ * @param radius radius to search -+ * @param step Search step 1 would mean checking every block, 8 would be every 8th block -+ * @return Location of biome or null if not found in specified radius -+ */ -+ @Nullable -+ Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius, int step); -+ -+ /** -+ * Checks if the world: -+ *

    -+ *
  • evaporates water
  • -+ *
  • dries sponges
  • -+ *
  • has lava spread faster and further
  • -+ *
-+ * -+ * @return true if ultrawarm, false if not -+ */ -+ boolean isUltrawarm(); -+ -+ /** -+ * Checks if the world is natural. -+ *

-+ * If {@code false}, compasses will spin randomly in the world. -+ * If {@code true}, nether portals will spawn zombified piglins. -+ *

-+ * -+ * @return true or false -+ */ -+ boolean isNatural(); -+ -+ /** -+ * Gets the coordinate scaling of this world. -+ * -+ * @return the coordinate scale -+ */ -+ double getCoordinateScale(); -+ -+ /** -+ * Checks if the world has skylight access -+ * -+ * @return whether there is skylight -+ */ -+ boolean hasSkylight(); -+ -+ /** -+ * Checks if the world has a bedrock ceiling -+ * -+ * @return whether the world has a bedrock ceiling -+ */ -+ boolean hasBedrockCeiling(); -+ -+ /** -+ * Checks if piglins will turn into Zombified Piglins in this world -+ * -+ * @return whether Piglins will not transform -+ */ -+ boolean isPiglinSafe(); -+ -+ /** -+ * Checks if beds work -+ * -+ * @return whether beds work -+ */ -+ boolean doesBedWork(); -+ -+ /** -+ * Checks if respawn anchors work -+ * -+ * @return whether respawn anchors work -+ */ -+ boolean doesRespawnAnchorWork(); -+ -+ /** -+ * Checks if this world supports raids -+ * -+ * @return whether this world supports raids -+ */ -+ boolean hasRaids(); -+ -+ /** -+ * Checks if this world has a fixed time -+ * -+ * @return whether this world has fixed time -+ */ -+ boolean isFixedTime(); -+ -+ /** -+ * Gets the collection of materials that burn infinitely in this world. -+ * -+ * @return the materials that will forever stay lit by fire -+ */ -+ @NotNull -+ Collection getInfiniburn(); -+ // Paper end -+ - // Spigot start - /** - * Returns the view distance used for this world. diff --git a/Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch b/Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index a622f2b98fff..000000000000 --- a/Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:49 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -diff --git a/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e0028733615ddc9e34359f673ca1c3cadb133948 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/player/PlayerBedFailEnterEvent.java -@@ -0,0 +1,119 @@ -+package io.papermc.paper.event.player; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.block.Block; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Cancellable; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.PlayerEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PlayerBedFailEnterEvent extends PlayerEvent implements Cancellable { -+ -+ private static final HandlerList HANDLER_LIST = new HandlerList(); -+ -+ private final FailReason failReason; -+ private final Block bed; -+ private boolean willExplode; -+ private Component message; -+ private boolean cancelled; -+ -+ public PlayerBedFailEnterEvent(@NotNull Player player, @NotNull FailReason failReason, @NotNull Block bed, boolean willExplode, @Nullable Component message) { -+ super(player); -+ this.failReason = failReason; -+ this.bed = bed; -+ this.willExplode = willExplode; -+ this.message = message; -+ } -+ -+ @NotNull -+ public FailReason getFailReason() { -+ return failReason; -+ } -+ -+ @NotNull -+ public Block getBed() { -+ return bed; -+ } -+ -+ public boolean getWillExplode() { -+ return willExplode; -+ } -+ -+ public void setWillExplode(boolean willExplode) { -+ this.willExplode = willExplode; -+ } -+ -+ @Nullable -+ public Component getMessage() { -+ return message; -+ } -+ -+ public void setMessage(@Nullable Component message) { -+ this.message = message; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return cancelled; -+ } -+ -+ /** -+ * Cancel this event. -+ *

-+ * NOTE: This does not cancel the player getting in the bed, but any messages/explosions -+ * that may occur because of the interaction. -+ * @param cancel true if you wish to cancel this event -+ */ -+ @Override -+ public void setCancelled(boolean cancel) { -+ cancelled = cancel; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return HANDLER_LIST; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return HANDLER_LIST; -+ } -+ -+ public static enum FailReason { -+ /** -+ * The world doesn't allow sleeping (ex. Nether or The End). Entering -+ * the bed is prevented and the bed explodes. -+ */ -+ NOT_POSSIBLE_HERE, -+ /** -+ * Entering the bed is prevented due to it not being night nor -+ * thundering currently. -+ *

-+ * If the event is forcefully allowed during daytime, the player will -+ * enter the bed (and set its bed location), but might get immediately -+ * thrown out again. -+ */ -+ NOT_POSSIBLE_NOW, -+ /** -+ * Entering the bed is prevented due to the player being too far away. -+ */ -+ TOO_FAR_AWAY, -+ /** -+ * Bed is obstructed. -+ */ -+ OBSTRUCTED, -+ /** -+ * Entering the bed is prevented due to there being some other problem. -+ */ -+ OTHER_PROBLEM, -+ /** -+ * Entering the bed is prevented due to there being monsters nearby. -+ */ -+ NOT_SAFE; -+ -+ public static final FailReason[] VALUES = values(); -+ } -+} diff --git a/Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch b/Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index 776ee50cb632..000000000000 --- a/Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:25:47 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a907015c769c754a1599325068259ca0f109489a ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BeaconActivatedEvent.java -@@ -0,0 +1,40 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.block.Beacon; -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * Called when a beacon is activated. -+ * Activation occurs when the beacon activation sound is played, and the beam becomes visible. -+ */ -+public class BeaconActivatedEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public BeaconActivatedEvent(@NotNull Block block) { -+ super(block); -+ } -+ -+ /** -+ * Returns the beacon that was activated. -+ * -+ * @return the beacon that was activated. -+ */ -+ @NotNull -+ public Beacon getBeacon() { -+ return (Beacon) block.getState(); -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..34f18468b4cfc08717cc3442778c9e85124e5a22 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/event/block/BeaconDeactivatedEvent.java -@@ -0,0 +1,43 @@ -+package io.papermc.paper.event.block; -+ -+import org.bukkit.Material; -+import org.bukkit.block.Beacon; -+import org.bukkit.block.Block; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.block.BlockEvent; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Called when a beacon is deactivated, either because its base block(s) or itself were destroyed. -+ */ -+public class BeaconDeactivatedEvent extends BlockEvent { -+ private static final HandlerList handlers = new HandlerList(); -+ -+ public BeaconDeactivatedEvent(@NotNull Block block) { -+ super(block); -+ } -+ -+ /** -+ * Returns the beacon that was deactivated. -+ * This will return null if the beacon does not exist. -+ * (which can occur after the deactivation of a now broken beacon) -+ * -+ * @return The beacon that got deactivated, or null if it does not exist. -+ */ -+ @Nullable -+ public Beacon getBeacon() { -+ return block.getType() == Material.BEACON ? (Beacon) block.getState() : null; -+ } -+ -+ @NotNull -+ @Override -+ public HandlerList getHandlers() { -+ return handlers; -+ } -+ -+ @NotNull -+ public static HandlerList getHandlerList() { -+ return handlers; -+ } -+} diff --git a/Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch deleted file mode 100644 index 41342d0d34e6..000000000000 --- a/Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 17:17:54 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -index d2be2ad2e3665728e614a89dd62ef9237f1d3ce6..359e385bd6854a4b146cd0a54badb9c3d31ca12d 100644 ---- a/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -+++ b/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java -@@ -14,17 +14,30 @@ public class PlayerRespawnEvent extends PlayerEvent { - private Location respawnLocation; - private final boolean isBedSpawn; - private final boolean isAnchorSpawn; -+ private final java.util.Set respawnFlags; // Paper - - @Deprecated - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { - this(respawnPlayer, respawnLocation, isBedSpawn, false); - } - -+ @Deprecated // Paper - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { -+ // Paper start -+ this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder()); -+ } -+ -+ public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final com.google.common.collect.ImmutableSet.Builder respawnFlags) { -+ // Paper end - super(respawnPlayer); - this.respawnLocation = respawnLocation; - this.isBedSpawn = isBedSpawn; - this.isAnchorSpawn = isAnchorSpawn; -+ // Paper start -+ if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); } -+ if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); } -+ this.respawnFlags = respawnFlags.build(); -+ // Paper end - } - - /** -@@ -77,4 +90,31 @@ public class PlayerRespawnEvent extends PlayerEvent { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ // Paper start -+ /** -+ * Get the set of flags that apply to this respawn. -+ * -+ * @return an immutable set of the flags that apply to this respawn -+ */ -+ @NotNull -+ public java.util.Set getRespawnFlags() { -+ return respawnFlags; -+ } -+ -+ public enum RespawnFlag { -+ /** -+ * Will use the bed spawn location -+ */ -+ BED_SPAWN, -+ /** -+ * Will use the respawn anchor location -+ */ -+ ANCHOR_SPAWN, -+ /** -+ * Is caused by going to the end portal in the end. -+ */ -+ END_PORTAL, -+ } -+ // Paper end - } diff --git a/Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index b2fb9bb339dd..000000000000 --- a/Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 1 Apr 2021 00:34:41 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -index 619ed37169c126a8c75d02699a04728bac49d10d..4cd97cb102e1ec53b3fe1a451b65b4b640fde099 100644 ---- a/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -+++ b/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java -@@ -24,6 +24,11 @@ - package com.destroystokyo.paper.event.server; - - import com.google.common.collect.ImmutableList; -+import io.papermc.paper.util.TransformingRandomAccessList; -+import net.kyori.adventure.text.Component; -+import net.kyori.examination.Examinable; -+import net.kyori.examination.ExaminableProperty; -+import net.kyori.examination.string.StringExaminer; - import org.apache.commons.lang.Validate; - import org.bukkit.Location; - import org.bukkit.command.Command; -@@ -34,6 +39,7 @@ import org.bukkit.event.HandlerList; - - import java.util.ArrayList; - import java.util.List; -+import java.util.stream.Stream; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -48,15 +54,29 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - private final boolean isCommand; - @Nullable - private final Location loc; -- @NotNull private List completions; -+ private final List completions = new ArrayList<>(); -+ private final List stringCompletions = new TransformingRandomAccessList<>( -+ this.completions, -+ Completion::suggestion, -+ Completion::completion -+ ); - private boolean cancelled; - private boolean handled = false; - private boolean fireSyncHandler = true; - -+ public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { -+ super(true); -+ this.sender = sender; -+ this.buffer = buffer; -+ this.isCommand = isCommand; -+ this.loc = loc; -+ } -+ -+ @Deprecated - public AsyncTabCompleteEvent(@NotNull CommandSender sender, @NotNull List completions, @NotNull String buffer, boolean isCommand, @Nullable Location loc) { - super(true); - this.sender = sender; -- this.completions = completions; -+ this.completions.addAll(fromStrings(completions)); - this.buffer = buffer; - this.isCommand = isCommand; - this.loc = loc; -@@ -84,7 +104,7 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - */ - @NotNull - public List getCompletions() { -- return completions; -+ return this.stringCompletions; - } - - /** -@@ -98,8 +118,42 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - * @param completions the new completions - */ - public void setCompletions(@NotNull List completions) { -+ if (completions == this.stringCompletions) { -+ return; -+ } - Validate.notNull(completions); -- this.completions = new ArrayList<>(completions); -+ this.completions.clear(); -+ this.completions.addAll(fromStrings(completions)); -+ } -+ -+ /** -+ * The list of {@link Completion completions} which will be offered to the sender, in order. -+ * This list is mutable and reflects what will be offered. -+ *

-+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ * -+ * @return a list of offered completions -+ */ -+ public @NotNull List completions() { -+ return this.completions; -+ } -+ -+ /** -+ * Set the {@link Completion completions} offered, overriding any already set. -+ * If this collection is not empty after the event is fired, then -+ * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} -+ * or current player names will not be called. -+ *

-+ * The passed collection will be cloned to a new List. You must call {{@link #completions()}} to mutate from here -+ * -+ * @param newCompletions the new completions -+ */ -+ public void completions(final @NotNull List newCompletions) { -+ Validate.notNull(newCompletions, "new completions"); -+ this.completions.clear(); -+ this.completions.addAll(newCompletions); - } - - /** -@@ -174,4 +228,102 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { - public static HandlerList getHandlerList() { - return handlers; - } -+ -+ private static @NotNull List fromStrings(final @NotNull List strings) { -+ final List list = new ArrayList<>(); -+ for (final String it : strings) { -+ list.add(new CompletionImpl(it, null)); -+ } -+ return list; -+ } -+ -+ /** -+ * A rich tab completion, consisting of a string suggestion, and a nullable {@link Component} tooltip. -+ */ -+ public interface Completion extends Examinable { -+ /** -+ * Get the suggestion string for this {@link Completion}. -+ * -+ * @return suggestion string -+ */ -+ @NotNull String suggestion(); -+ -+ /** -+ * Get the suggestion tooltip for this {@link Completion}. -+ * -+ * @return tooltip component -+ */ -+ @Nullable Component tooltip(); -+ -+ @Override -+ default @NotNull Stream examinableProperties() { -+ return Stream.of(ExaminableProperty.of("suggestion", this.suggestion()), ExaminableProperty.of("tooltip", this.tooltip())); -+ } -+ -+ /** -+ * Create a new {@link Completion} from a suggestion string. -+ * -+ * @param suggestion suggestion string -+ * @return new completion instance -+ */ -+ static @NotNull Completion completion(final @NotNull String suggestion) { -+ return new CompletionImpl(suggestion, null); -+ } -+ -+ /** -+ * Create a new {@link Completion} from a suggestion string and a tooltip {@link Component}. -+ * -+ *

If the provided component is null, the suggestion will not have a tooltip.

-+ * -+ * @param suggestion suggestion string -+ * @param tooltip tooltip component, or null -+ * @return new completion instance -+ */ -+ static @NotNull Completion completion(final @NotNull String suggestion, final @Nullable Component tooltip) { -+ return new CompletionImpl(suggestion, tooltip); -+ } -+ } -+ -+ static final class CompletionImpl implements Completion { -+ private final String suggestion; -+ private final Component tooltip; -+ -+ CompletionImpl(final @NotNull String suggestion, final @Nullable Component tooltip) { -+ this.suggestion = suggestion; -+ this.tooltip = tooltip; -+ } -+ -+ @Override -+ public @NotNull String suggestion() { -+ return this.suggestion; -+ } -+ -+ @Override -+ public @Nullable Component tooltip() { -+ return this.tooltip; -+ } -+ -+ @Override -+ public boolean equals(final @Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || this.getClass() != o.getClass()) { -+ return false; -+ } -+ final CompletionImpl that = (CompletionImpl) o; -+ return this.suggestion.equals(that.suggestion) -+ && java.util.Objects.equals(this.tooltip, that.tooltip); -+ } -+ -+ @Override -+ public int hashCode() { -+ return java.util.Objects.hash(this.suggestion, this.tooltip); -+ } -+ -+ @Override -+ public @NotNull String toString() { -+ return StringExaminer.simpleEscaping().examine(this); -+ } -+ } - } -diff --git a/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6f560a51277ccbd46a9142cfa057d276118c1c7b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TransformingRandomAccessList.java -@@ -0,0 +1,169 @@ -+package io.papermc.paper.util; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.AbstractList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.ListIterator; -+import java.util.RandomAccess; -+import java.util.function.Function; -+import java.util.function.Predicate; -+ -+import static com.google.common.base.Preconditions.checkNotNull; -+ -+/** -+ * Modified version of the Guava class with the same name to support add operations. -+ * -+ * @param backing list element type -+ * @param transformed list element type -+ */ -+public final class TransformingRandomAccessList extends AbstractList implements RandomAccess { -+ final List fromList; -+ final Function toFunction; -+ final Function fromFunction; -+ -+ /** -+ * Create a new {@link TransformingRandomAccessList}. -+ * -+ * @param fromList backing list -+ * @param toFunction function mapping backing list element type to transformed list element type -+ * @param fromFunction function mapping transformed list element type to backing list element type -+ */ -+ public TransformingRandomAccessList( -+ final @NonNull List fromList, -+ final @NonNull Function toFunction, -+ final @NonNull Function fromFunction -+ ) { -+ this.fromList = checkNotNull(fromList); -+ this.toFunction = checkNotNull(toFunction); -+ this.fromFunction = checkNotNull(fromFunction); -+ } -+ -+ @Override -+ public void clear() { -+ this.fromList.clear(); -+ } -+ -+ @Override -+ public T get(int index) { -+ return this.toFunction.apply(this.fromList.get(index)); -+ } -+ -+ @Override -+ public @NotNull Iterator iterator() { -+ return this.listIterator(); -+ } -+ -+ @Override -+ public @NotNull ListIterator listIterator(int index) { -+ return new TransformedListIterator(this.fromList.listIterator(index)) { -+ @Override -+ T transform(F from) { -+ return TransformingRandomAccessList.this.toFunction.apply(from); -+ } -+ -+ @Override -+ F transformBack(T from) { -+ return TransformingRandomAccessList.this.fromFunction.apply(from); -+ } -+ }; -+ } -+ -+ @Override -+ public boolean isEmpty() { -+ return this.fromList.isEmpty(); -+ } -+ -+ @Override -+ public boolean removeIf(Predicate filter) { -+ checkNotNull(filter); -+ return this.fromList.removeIf(element -> filter.test(this.toFunction.apply(element))); -+ } -+ -+ @Override -+ public T remove(int index) { -+ return this.toFunction.apply(this.fromList.remove(index)); -+ } -+ -+ @Override -+ public int size() { -+ return this.fromList.size(); -+ } -+ -+ @Override -+ public T set(int i, T t) { -+ return this.toFunction.apply(this.fromList.set(i, this.fromFunction.apply(t))); -+ } -+ -+ @Override -+ public void add(int i, T t) { -+ this.fromList.add(i, this.fromFunction.apply(t)); -+ } -+ -+ static abstract class TransformedListIterator implements ListIterator, Iterator { -+ final Iterator backingIterator; -+ -+ TransformedListIterator(ListIterator backingIterator) { -+ this.backingIterator = checkNotNull((Iterator) backingIterator); -+ } -+ -+ private ListIterator backingIterator() { -+ return cast(this.backingIterator); -+ } -+ -+ static
ListIterator cast(Iterator iterator) { -+ return (ListIterator) iterator; -+ } -+ -+ @Override -+ public final boolean hasPrevious() { -+ return this.backingIterator().hasPrevious(); -+ } -+ -+ @Override -+ public final T previous() { -+ return this.transform(this.backingIterator().previous()); -+ } -+ -+ @Override -+ public final int nextIndex() { -+ return this.backingIterator().nextIndex(); -+ } -+ -+ @Override -+ public final int previousIndex() { -+ return this.backingIterator().previousIndex(); -+ } -+ -+ @Override -+ public void set(T element) { -+ this.backingIterator().set(this.transformBack(element)); -+ } -+ -+ @Override -+ public void add(T element) { -+ this.backingIterator().add(this.transformBack(element)); -+ } -+ -+ abstract T transform(F from); -+ -+ abstract F transformBack(T to); -+ -+ @Override -+ public final boolean hasNext() { -+ return this.backingIterator.hasNext(); -+ } -+ -+ @Override -+ public final T next() { -+ return this.transform(this.backingIterator.next()); -+ } -+ -+ @Override -+ public final void remove() { -+ this.backingIterator.remove(); -+ } -+ } -+} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 19271057cf24329757c9419fa6c97848e008a96c..82b2783497947f336b0dd95db61f31f8f77f446c 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -48,6 +48,8 @@ public class AnnotationTest { - // Generic functional interface - "org/bukkit/util/Consumer", - // Paper start -+ "io/papermc/paper/util/TransformingRandomAccessList", -+ "io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator", - // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull - "co/aikar/timings/TimingHistory$2", - "co/aikar/timings/TimingHistory$2$1", diff --git a/Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index 58db0a8a2b0b..000000000000 --- a/Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -index c9af02b0f62b3d18da1e91d1ea02ce0864fc60b9..77aefda5aac4602bf5bf71c29600e7450defdd4e 100644 ---- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java -@@ -20,6 +20,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - private net.kyori.adventure.text.Component message; // Paper - //private String name; // Paper - Not used anymore - private final InetAddress ipAddress; -+ private final InetAddress rawAddress; // Paper - //private UUID uniqueId; // Paper - Not used anymore - - @Deprecated -@@ -49,7 +50,23 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.profile = profile; - } - -+ // Paper Start -+ /** -+ * Gets the raw address of the player logging in -+ * @return The address -+ */ -+ @NotNull -+ public InetAddress getRawAddress() { -+ return rawAddress; -+ } -+ // Paper end -+ -+ @Deprecated - public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { -+ this(name, ipAddress, ipAddress, uniqueId, profile); -+ } -+ -+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final InetAddress rawAddress, @NotNull final UUID uniqueId, @NotNull PlayerProfile profile) { - super(true); - this.profile = profile; - // Paper end -@@ -57,6 +74,7 @@ public class AsyncPlayerPreLoginEvent extends Event { - this.message = net.kyori.adventure.text.Component.empty(); // Paper - //this.name = name; // Paper - Not used anymore - this.ipAddress = ipAddress; -+ this.rawAddress = rawAddress; // Paper - //this.uniqueId = uniqueId; // Paper - Not used anymore - } - diff --git a/Spigot-API-Patches/0298-Inventory-close.patch b/Spigot-API-Patches/0298-Inventory-close.patch deleted file mode 100644 index 550e287fa68c..000000000000 --- a/Spigot-API-Patches/0298-Inventory-close.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:20 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/org/bukkit/inventory/Inventory.java -index 7956aebcb390379677dccf7c9561866cf94c024c..8f00cb2e3bc9963e9657c1b2493e8b015a6664d0 100644 ---- a/src/main/java/org/bukkit/inventory/Inventory.java -+++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -353,6 +353,15 @@ public interface Inventory extends Iterable { - */ - public void clear(); - -+ // Paper start -+ /** -+ * Closes the inventory for all viewers. -+ * -+ * @return the number if viewers the inventory was closed for -+ */ -+ public int close(); -+ // Paper end -+ - /** - * Gets a list of players viewing the inventory. Note that a player is - * considered to be viewing their own inventory and internal crafting diff --git a/Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index 9b01b3067615..000000000000 --- a/Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:51 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/org/bukkit/entity/Phantom.java b/src/main/java/org/bukkit/entity/Phantom.java -index ed4d417c2deefb78807cb61b01df5afcd334d754..a40b045f08b85e22e75459b547e7e7c0b95103ed 100644 ---- a/src/main/java/org/bukkit/entity/Phantom.java -+++ b/src/main/java/org/bukkit/entity/Phantom.java -@@ -26,5 +26,19 @@ public interface Phantom extends Flying { - */ - @Nullable - public java.util.UUID getSpawningEntity(); -+ -+ /** -+ * Check if this phantom will burn in the sunlight -+ * -+ * @return True if phantom will burn in sunlight -+ */ -+ public boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this phantom should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ public void setShouldBurnInDay(boolean shouldBurnInDay); - // Paper end - } -diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java -index 1c367f78eadf24850061a84ce63b950b79d3c435..684477b894e52ff33f9fce2edf76e58c292dd75e 100644 ---- a/src/main/java/org/bukkit/entity/Skeleton.java -+++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -46,4 +46,19 @@ public interface Skeleton extends Monster, RangedEntity { // Paper - */ - STRAY; - } -+ // Paper start -+ /** -+ * Check if this skeleton will burn in the sunlight -+ * -+ * @return True if skeleton will burn in sunlight -+ */ -+ boolean shouldBurnInDay(); -+ -+ /** -+ * Set if this skeleton should burn in the sunlight -+ * -+ * @param shouldBurnInDay True to burn in sunlight -+ */ -+ void setShouldBurnInDay(boolean shouldBurnInDay); -+ // Paper end - } diff --git a/Spigot-API-Patches/0300-Add-basic-Datapack-API.patch b/Spigot-API-Patches/0300-Add-basic-Datapack-API.patch deleted file mode 100644 index 5185f708deeb..000000000000 --- a/Spigot-API-Patches/0300-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/Datapack.java b/src/main/java/io/papermc/paper/datapack/Datapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7b2ab0be10a21e0496ad1d485ff8cb2c0b92a2cb ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/Datapack.java -@@ -0,0 +1,32 @@ -+package io.papermc.paper.datapack; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public interface Datapack { -+ -+ /** -+ * @return the name of the pack -+ */ -+ @NonNull -+ String getName(); -+ -+ /** -+ * @return the compatibility of the pack -+ */ -+ @NonNull -+ Compatibility getCompatibility(); -+ -+ /** -+ * @return whether or not the pack is currently enabled -+ */ -+ boolean isEnabled(); -+ -+ void setEnabled(boolean enabled); -+ -+ enum Compatibility { -+ TOO_OLD, -+ TOO_NEW, -+ COMPATIBLE, -+ } -+ -+} -diff --git a/src/main/java/io/papermc/paper/datapack/DatapackManager.java b/src/main/java/io/papermc/paper/datapack/DatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..58f78d5e91beacaf710f62461cf869f70d08b2a2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/DatapackManager.java -@@ -0,0 +1,21 @@ -+package io.papermc.paper.datapack; -+ -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import java.util.Collection; -+ -+public interface DatapackManager { -+ -+ /** -+ * @return all the packs known to the server -+ */ -+ @NonNull -+ Collection getPacks(); -+ -+ /** -+ * @return all the packs which are currently enabled -+ */ -+ @NonNull -+ Collection getEnabledPacks(); -+ -+} -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 5f7208196684d9c8373df28b7cfb5f9e21baa41e..33f04d57b7df3a6f9743246ba9af6d67f4fa4b54 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1937,6 +1937,14 @@ public final class Bukkit { - public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return server.getMobGoals(); - } -+ -+ /** -+ * @return the datapack manager -+ */ -+ @NotNull -+ public static io.papermc.paper.datapack.DatapackManager getDatapackManager() { -+ return server.getDatapackManager(); -+ } - // Paper end - - @NotNull -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index f3e27d2d02a9407bb1b091b8c1125ad5abf99e55..35ec8a060c2a2d2d48477b1bb940db51d18bf38e 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -1698,5 +1698,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - @NotNull - com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); -+ -+ /** -+ * @return the datapack manager -+ */ -+ @NotNull -+ io.papermc.paper.datapack.DatapackManager getDatapackManager(); - // Paper end - } diff --git a/Spigot-Server-Patches/0001-POM-Changes.patch b/Spigot-Server-Patches/0001-POM-Changes.patch deleted file mode 100644 index fd56507f92bb..000000000000 --- a/Spigot-Server-Patches/0001-POM-Changes.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes - - -diff --git a/pom.xml b/pom.xml -index 3fc047371e8f8a626e69697fad549d689c5dce89..a5d87d22cb1588d15e08da3b37e51c5e261c7799 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,15 +1,14 @@ - - 4.0.0 -- org.spigotmc -- spigot -+ paper - jar - 1.16.5-R0.1-SNAPSHOT -- Spigot -- https://www.spigotmc.org/ -+ Paper -+ https://papermc.io - - -- true -+ - UTF-8 - unknown - git -@@ -20,21 +19,39 @@ - - - -- org.spigotmc -- spigot-parent -+ com.destroystokyo.paper -+ paper-parent - dev-SNAPSHOT - ../pom.xml - - -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-bom -+ 2.11.2 -+ pom -+ import -+ -+ -+ -+ - - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api -+ ${project.version} -+ compile -+ -+ -+ com.destroystokyo.paper -+ paper-mojangapi - ${project.version} - compile - - -- org.spigotmc -+ io.papermc - minecraft-server - ${minecraft.version}-SNAPSHOT - compile -@@ -45,18 +62,15 @@ - 2.12.1 - compile - -+ -+ org.apache.logging.log4j -+ log4j-api -+ compile -+ - - org.apache.logging.log4j - log4j-iostreams -- 2.8.1 - compile -- -- -- -- org.apache.logging.log4j -- log4j-api -- -- - - - org.ow2.asm -@@ -64,12 +78,23 @@ - 9.1 - compile - -+ -+ -+ co.aikar -+ cleaner -+ 1.0-SNAPSHOT -+ -+ -+ io.netty -+ netty-all -+ 4.1.50.Final -+ - - - com.googlecode.json-simple - json-simple - 1.1.1 -- runtime -+ compile - - - org.xerial -@@ -80,7 +105,7 @@ - - mysql - mysql-connector-java -- 5.1.49 -+ 8.0.23 - runtime - - -@@ -105,7 +130,7 @@ - - org.apache.logging.log4j - log4j-slf4j-impl -- 2.8.1 -+ - runtime - - -@@ -132,34 +157,22 @@ - - - -+ paper-${minecraft.version} -+ clean install - - -- net.md-5 -- scriptus -- 0.4.1 -+ com.lukegb.mojo -+ gitdescribe-maven-plugin -+ 1.3 -+ -+ git-Paper- -+ .. -+ - - -- ex-spigot -- -- ${bt.name}-Spigot-%s -- ../ -- spigot.desc -- -- initialize -- -- describe -- -- -- -- ex-craftbukkit -- -- -%s -- ../../CraftBukkit -- craftbukkit.desc -- -- initialize -+ compile - -- describe -+ gitdescribe - - - -@@ -169,6 +182,7 @@ - maven-jar-plugin - 3.2.0 - -+ true - - - false -@@ -176,11 +190,13 @@ - - org.bukkit.craftbukkit.Main - CraftBukkit -- ${spigot.desc}${craftbukkit.desc} -- ${project.build.outputTimestamp} -+ -+ ${describe} -+ ${maven.build.timestamp} - Bukkit - ${api.version} - Bukkit Team -+ true - - - -@@ -216,14 +232,24 @@ - shade - - -+ ${project.build.directory}/dependency-reduced-pom.xml - ${shadeSourcesJar} - - -- org.spigotmc:minecraft-server -+ io.papermc:minecraft-server - - com/google/common/** - com/google/gson/** - com/google/thirdparty/** -+ -+ io/netty/** -+ META-INF/native/libnetty* -+ com/mojang/brigadier/** -+ META-INF/MANIFEST.MF -+ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class -+ com/mojang/datafixers/util/Either* -+ org/apache/logging/log4j/** -+ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat - - - -@@ -245,10 +271,11 @@ - jline - org.bukkit.craftbukkit.libs.jline - -- -- it.unimi -- org.bukkit.craftbukkit.libs.it.unimi -- -+ -+ -+ -+ -+ - - org.apache.commons.codec - org.bukkit.craftbukkit.libs.org.apache.commons.codec -@@ -316,10 +343,6 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 036c870d991118e5c09eced8485b94579bc6782a..c6417a0594ffe2d3650ec54d44e575e347a1f724 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -186,7 +186,7 @@ public class Main { - } - - if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); -+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 93046379d0cefd5d3236fc59e698809acdc18f80..674096cab190d62622f9947853b056f57d43a2a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/Spigot-Server-Patches/0002-Paper-config-files.patch b/Spigot-Server-Patches/0002-Paper-config-files.patch deleted file mode 100644 index 59d761b3b605..000000000000 --- a/Spigot-Server-Patches/0002-Paper-config-files.patch +++ /dev/null @@ -1,820 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 29 Feb 2016 21:02:09 -0600 -Subject: [PATCH] Paper config files - -Loads each yml file for early init too so it can be used for early options - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..68cd4134cb6a00c1768100462f8e9e94f3fa6279 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +1,286 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Functions; -+import com.google.common.base.Joiner; -+import com.google.common.collect.ImmutableSet; -+import com.google.common.collect.Iterables; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.apache.commons.lang3.tuple.MutablePair; -+import org.apache.commons.lang3.tuple.Pair; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.entity.Player; -+ -+import java.io.File; -+import java.time.LocalDateTime; -+import java.time.format.DateTimeFormatter; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.Collections; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Locale; -+import java.util.Map; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class PaperCommand extends Command { -+ private static final String BASE_PERM = "bukkit.command.paper."; -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ -+ public PaperCommand(String name) { -+ super(name); -+ this.description = "Paper related commands"; -+ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; -+ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); -+ } -+ -+ private static boolean testPermission(CommandSender commandSender, String permission) { -+ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; -+ commandSender.sendMessage(Bukkit.getPermissionMessage()); -+ return false; -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ if (args.length <= 1) -+ return getListMatchingLast(sender, args, SUBCOMMANDS); -+ -+ switch (args[0].toLowerCase(Locale.ENGLISH)) -+ { -+ case "entity": -+ if (args.length == 2) -+ return getListMatchingLast(sender, args, "help", "list"); -+ if (args.length == 3) -+ return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); -+ break; -+ } -+ return Collections.emptyList(); -+ } -+ -+ // Code from Mojang - copyright them -+ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { -+ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); -+ } -+ -+ public static boolean matches(String s, String s1) { -+ return s1.regionMatches(true, 0, s, 0, s.length()); -+ } -+ -+ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { -+ String last = strings[strings.length - 1]; -+ ArrayList results = Lists.newArrayList(); -+ -+ if (!collection.isEmpty()) { -+ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); -+ -+ while (iterator.hasNext()) { -+ String s1 = (String) iterator.next(); -+ -+ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { -+ results.add(s1); -+ } -+ } -+ -+ if (results.isEmpty()) { -+ iterator = collection.iterator(); -+ -+ while (iterator.hasNext()) { -+ Object object = iterator.next(); -+ -+ if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { -+ results.add(String.valueOf(object)); -+ } -+ } -+ } -+ } -+ -+ return results; -+ } -+ // end copy stuff -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ if (args.length == 0) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { -+ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; -+ } -+ switch (args[0].toLowerCase(Locale.ENGLISH)) { -+ case "heap": -+ dumpHeap(sender); -+ break; -+ case "entity": -+ listEntities(sender, args); -+ break; -+ case "reload": -+ doReload(sender); -+ break; -+ case "ver": -+ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) -+ case "version": -+ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); -+ if (ver != null) { -+ ver.execute(sender, commandLabel, new String[0]); -+ break; -+ } -+ // else - fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ -+ return true; -+ } -+ -+ /* -+ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 -+ */ -+ private void listEntities(CommandSender sender, String[] args) { -+ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); -+ return; -+ } -+ -+ switch (args[1].toLowerCase(Locale.ENGLISH)) { -+ case "list": -+ String filter = "*"; -+ if (args.length > 2) { -+ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); -+ return; -+ } -+ filter = args[2]; -+ } -+ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); -+ Set names = EntityTypes.getEntityNameList().stream() -+ .filter(n -> n.toString().matches(cleanfilter)) -+ .collect(Collectors.toSet()); -+ -+ if (names.isEmpty()) { -+ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ String worldName; -+ if (args.length > 3) { -+ worldName = args[3]; -+ } else if (sender instanceof Player) { -+ worldName = ((Player) sender).getWorld().getName(); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); -+ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ Map>> list = Maps.newHashMap(); -+ World bukkitWorld = Bukkit.getWorld(worldName); -+ if (bukkitWorld == null) { -+ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ WorldServer world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); -+ -+ Map nonEntityTicking = Maps.newHashMap(); -+ ChunkProviderServer chunkProviderServer = world.getChunkProvider(); -+ -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { -+ MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ -+ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -+ info.left++; -+ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { -+ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); -+ } -+ }); -+ -+ if (names.size() == 1) { -+ MinecraftKey name = names.iterator().next(); -+ Pair> info = list.get(name); -+ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); -+ if (info == null) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); -+ info.getRight().entrySet().stream() -+ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); -+ } else { -+ List> info = list.entrySet().stream() -+ .filter(e -> names.contains(e.getKey())) -+ .map(e -> Pair.of(e.getKey(), e.getValue().left)) -+ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .collect(Collectors.toList()); -+ -+ if (info == null || info.size() == 0) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ -+ int count = info.stream().mapToInt(Pair::getRight).sum(); -+ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); -+ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); -+ info.forEach(e -> { -+ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); -+ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); -+ }); -+ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); -+ } -+ break; -+ } -+ } -+ -+ private void dumpHeap(CommandSender sender) { -+ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); -+ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); -+ -+ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); -+ -+ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); -+ if (file != null) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); -+ } -+ } -+ -+ private void doReload(CommandSender sender) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); -+ -+ MinecraftServer console = MinecraftServer.getServer(); -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); -+ for (WorldServer world : console.getWorlds()) { -+ world.paperConfig.init(); -+ } -+ console.server.reloadCount++; -+ -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2c0514892d3993bef57ecf677cf8bb0fbe0216e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +1,185 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Throwables; -+ -+import java.io.File; -+import java.io.IOException; -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.regex.Pattern; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.command.Command; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.InvalidConfigurationException; -+import org.bukkit.configuration.file.YamlConfiguration; -+ -+public class PaperConfig { -+ -+ private static File CONFIG_FILE; -+ private static final String HEADER = "This is the main configuration file for Paper.\n" -+ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" -+ + "with caution, and make sure you know what each option does before configuring.\n" -+ + "\n" -+ + "If you need help with the configuration or have any questions related to Paper,\n" -+ + "join us in our Discord or IRC channel.\n" -+ + "\n" -+ + "Discord: https://discord.gg/papermc\n" -+ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" -+ + "Website: https://papermc.io/ \n" -+ + "Docs: https://paper.readthedocs.org/ \n"; -+ /*========================================================================*/ -+ public static YamlConfiguration config; -+ static int version; -+ static Map commands; -+ private static boolean verbose; -+ private static boolean fatalError; -+ /*========================================================================*/ -+ -+ public static void init(File configFile) { -+ CONFIG_FILE = configFile; -+ config = new YamlConfiguration(); -+ try { -+ config.load(CONFIG_FILE); -+ } catch (IOException ex) { -+ } catch (InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); -+ throw Throwables.propagate(ex); -+ } -+ config.options().header(HEADER); -+ config.options().copyDefaults(true); -+ verbose = getBoolean("verbose", false); -+ -+ commands = new HashMap(); -+ commands.put("paper", new PaperCommand("paper")); -+ -+ version = getInt("config-version", 20); -+ set("config-version", 20); -+ readConfig(PaperConfig.class, null); -+ } -+ -+ protected static void logError(String s) { -+ Bukkit.getLogger().severe(s); -+ } -+ -+ protected static void fatal(String s) { -+ fatalError = true; -+ throw new RuntimeException("Fatal paper.yml config error: " + s); -+ } -+ -+ protected static void log(String s) { -+ if (verbose) { -+ Bukkit.getLogger().info(s); -+ } -+ } -+ -+ public static void registerCommands() { -+ for (Map.Entry entry : commands.entrySet()) { -+ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); -+ } -+ } -+ -+ static void readConfig(Class clazz, Object instance) { -+ for (Method method : clazz.getDeclaredMethods()) { -+ if (Modifier.isPrivate(method.getModifiers())) { -+ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { -+ try { -+ method.setAccessible(true); -+ method.invoke(instance); -+ } catch (InvocationTargetException ex) { -+ throw Throwables.propagate(ex.getCause()); -+ } catch (Exception ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); -+ } -+ } -+ } -+ } -+ -+ try { -+ config.save(CONFIG_FILE); -+ } catch (IOException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); -+ } -+ } -+ -+ private static final Pattern SPACE = Pattern.compile(" "); -+ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); -+ public static int getSeconds(String str) { -+ str = SPACE.matcher(str).replaceAll(""); -+ final char unit = str.charAt(str.length() - 1); -+ str = NOT_NUMERIC.matcher(str).replaceAll(""); -+ double num; -+ try { -+ num = Double.parseDouble(str); -+ } catch (Exception e) { -+ num = 0D; -+ } -+ switch (unit) { -+ case 'd': num *= (double) 60*60*24; break; -+ case 'h': num *= (double) 60*60; break; -+ case 'm': num *= (double) 60; break; -+ default: case 's': break; -+ } -+ return (int) num; -+ } -+ -+ protected static String timeSummary(int seconds) { -+ String time = ""; -+ -+ if (seconds > 60 * 60 * 24) { -+ time += TimeUnit.SECONDS.toDays(seconds) + "d"; -+ seconds %= 60 * 60 * 24; -+ } -+ -+ if (seconds > 60 * 60) { -+ time += TimeUnit.SECONDS.toHours(seconds) + "h"; -+ seconds %= 60 * 60; -+ } -+ -+ if (seconds > 0) { -+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; -+ } -+ return time; -+ } -+ -+ private static void set(String path, Object val) { -+ config.set(path, val); -+ } -+ -+ private static boolean getBoolean(String path, boolean def) { -+ config.addDefault(path, def); -+ return config.getBoolean(path, config.getBoolean(path)); -+ } -+ -+ private static double getDouble(String path, double def) { -+ config.addDefault(path, def); -+ return config.getDouble(path, config.getDouble(path)); -+ } -+ -+ private static float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private static int getInt(String path, int def) { -+ config.addDefault(path, def); -+ return config.getInt(path, config.getInt(path)); -+ } -+ -+ private static List getList(String path, T def) { -+ config.addDefault(path, def); -+ return (List) config.getList(path, config.getList(path)); -+ } -+ -+ private static String getString(String path, String def) { -+ config.addDefault(path, def); -+ return config.getString(path, config.getString(path)); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b31109d2dadd29e8852468c19265066b773d2be0 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper; -+ -+import java.util.List; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.spigotmc.SpigotWorldConfig; -+ -+import static com.destroystokyo.paper.PaperConfig.log; -+import static com.destroystokyo.paper.PaperConfig.logError; -+ -+public class PaperWorldConfig { -+ -+ private final String worldName; -+ private final SpigotWorldConfig spigotConfig; -+ private YamlConfiguration config; -+ private boolean verbose; -+ -+ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { -+ this.worldName = worldName; -+ this.spigotConfig = spigotConfig; -+ this.config = PaperConfig.config; -+ init(); -+ } -+ -+ public void init() { -+ this.config = PaperConfig.config; // grab updated reference -+ log("-------- World Settings For [" + worldName + "] --------"); -+ PaperConfig.readConfig(PaperWorldConfig.class, this); -+ } -+ -+ private void set(String path, Object val) { -+ config.set("world-settings.default." + path, val); -+ if (config.get("world-settings." + worldName + "." + path) != null) { -+ config.set("world-settings." + worldName + "." + path, val); -+ } -+ } -+ -+ private boolean getBoolean(String path, boolean def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); -+ } -+ -+ private double getDouble(String path, double def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); -+ } -+ -+ private int getInt(String path, int def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); -+ } -+ -+ private float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private List getList(String path, List def) { -+ config.addDefault("world-settings.default." + path, def); -+ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); -+ } -+ -+ private String getString(String path, String def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index b746e30e6fc5ea0c17465b510d737316f1ab7004..89db31061fcc3420bc8e668533a4051cdbd12253 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -103,6 +103,12 @@ public class Main { - DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support - - dedicatedserversettings.save(); -+ // Paper start - load config files for access below if needed -+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); -+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); -+ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); -+ // Paper end -+ - java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); - EULA eula = new EULA(java_nio_file_path1); - -@@ -244,6 +250,20 @@ public class Main { - - } - -+ // Paper start - load config files -+ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { -+ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); -+ if (configFile.exists()) { -+ try { -+ config.load(configFile); -+ } catch (Exception ex) { -+ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); -+ } -+ } -+ return config; -+ } -+ // Paper end -+ - public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index d5628a0197125506f7aaeb89bab7bd8a811b3ad5..8e2e415a022ccd486465f19d9bbf1f287b21fb95 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -187,6 +187,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start -+ try { -+ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -+ } catch (Exception e) { -+ DedicatedServer.LOGGER.error("Unable to load server configuration", e); -+ return false; -+ } -+ com.destroystokyo.paper.PaperConfig.registerCommands(); -+ // Paper end - - this.setPVP(dedicatedserverproperties.pvp); - this.setAllowFlight(dedicatedserverproperties.allowFlight); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index e95f516756b2613972f20636443b3ff753342917..7fd6893c30fbb34367181620aa159ed79b803455 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -306,15 +306,15 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - -- @Override -- public boolean a(Entity entity) { -+ public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER -+ @Override public boolean a(Entity entity) { - long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); - - return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -- @Override -- public boolean a(ChunkCoordIntPair chunkcoordintpair) { -+ public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER -+ @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { - return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 4b0b782ab19a6cea4412b5e9d8c0524aee1402e4..a32bc63ff1960bdb874d546ee42633063834da24 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity; - - import com.google.common.collect.ImmutableSet; - import java.util.Optional; -+import java.util.Set; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -599,4 +600,10 @@ public class EntityTypes { - return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); - } - } -+ -+ // Paper start -+ public static Set getEntityNameList() { -+ return IRegistry.ENTITY_TYPE.keySet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 344b7f52e85af3e543da0bb1dd14b68eb41ebb84..f794113e7cc5809d1da0c85648fb7311fb633f40 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -129,6 +129,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -+ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ - public final SpigotTimings.WorldTimingsHandler timings; // Spigot - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; -@@ -149,6 +151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot -+ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b28ce2590d044dede6b9166e168c00d4ed6578f2..7b77bbf15e59c5a993fb1683c27e41425419e138 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -808,6 +808,7 @@ public final class CraftServer implements Server { - } - - org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (WorldServer world : console.getWorlds()) { - world.worldDataServer.setDifficulty(config.difficulty); - world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); -@@ -841,6 +842,7 @@ public final class CraftServer implements Server { - world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); - } - world.spigotConfig.init(); // Spigot -+ world.paperConfig.init(); // Paper - } - - pluginManager.clearPlugins(); -@@ -848,6 +850,7 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot -+ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper - overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); - -@@ -2105,4 +2108,35 @@ public final class CraftServer implements Server { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @SuppressWarnings({"rawtypes", "unchecked"}) -+ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { -+ try { -+ java.nio.file.Files.createDirectories(dir); -+ -+ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); -+ java.nio.file.Path file; -+ -+ try { -+ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); -+ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); -+ file = dir.resolve(name + ".phd"); -+ m.invoke(openj9Mbean, "heap", file.toString()); -+ } catch (ClassNotFoundException e) { -+ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); -+ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); -+ file = dir.resolve(name + ".hprof"); -+ m.invoke(hotspotMBean, file.toString(), true); -+ } -+ -+ return file; -+ } catch (Throwable t) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); -+ return null; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c6417a0594ffe2d3650ec54d44e575e347a1f724..3b48799d084f14722f815cb35cbd48b618380fca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -129,6 +129,14 @@ public class Main { - .defaultsTo(new File("spigot.yml")) - .describedAs("Yml file"); - // Spigot End -+ -+ // Paper Start -+ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("paper.yml")) -+ .describedAs("Yml file"); -+ // Paper end - } - }; - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 83d83ff7ceffbb77723da721b869dfd0091e496d..0efcbab8f8806aeb8dd8bd6384e5a7cee375d100 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -39,36 +39,36 @@ public class SpigotWorldConfig - config.set( "world-settings.default." + path, val ); - } - -- private boolean getBoolean(String path, boolean def) -+ public boolean getBoolean(String path, boolean def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); - } - -- private double getDouble(String path, double def) -+ public double getDouble(String path, double def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); - } - -- private int getInt(String path) -+ public int getInt(String path) // Paper - private -> public - { - return config.getInt( "world-settings." + worldName + "." + path ); - } - -- private int getInt(String path, int def) -+ public int getInt(String path, int def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); - } - -- private List getList(String path, T def) -+ public List getList(String path, T def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); - } - -- private String getString(String path, String def) -+ public String getString(String path, String def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/Spigot-Server-Patches/0003-MC-Dev-fixes.patch b/Spigot-Server-Patches/0003-MC-Dev-fixes.patch deleted file mode 100644 index b8a1a2f4466c..000000000000 --- a/Spigot-Server-Patches/0003-MC-Dev-fixes.patch +++ /dev/null @@ -1,893 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 19:36:20 -0400 -Subject: [PATCH] MC Dev fixes - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 14b1a51b9b675aa175c32990402551fa43ec1599..bc7757b929ecce998094ddcdf51a4703e165a6d6 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -65,8 +65,8 @@ public class SystemUtils { - return Collectors.toMap(Entry::getKey, Entry::getValue); - } - -- public static > String a(IBlockState iblockstate, Object object) { -- return iblockstate.a((Comparable) object); -+ public static > String a(IBlockState iblockstate, T object) { // Paper - decompile fix -+ return iblockstate.a(object); // Paper - decompile fix - } - - public static String a(String s, @Nullable MinecraftKey minecraftkey) { -@@ -234,8 +234,8 @@ public class SystemUtils { - public static T b(Iterable iterable, @Nullable T t0) { - Iterator iterator = iterable.iterator(); - -- Object object; -- Object object1; -+ T object; // Paper - decompile fix -+ T object1; // Paper - decompile fix - - for (object1 = null; iterator.hasNext(); object1 = object) { - object = iterator.next(); -@@ -260,7 +260,7 @@ public class SystemUtils { - } - - public static Strategy k() { -- return SystemUtils.IdentityHashingStrategy.INSTANCE; -+ return (Strategy) SystemUtils.IdentityHashingStrategy.INSTANCE; // Paper - decompile fix - } - - public static CompletableFuture> b(List> list) { -@@ -271,7 +271,7 @@ public class SystemUtils { - list.forEach((completablefuture1) -> { - int i = list1.size(); - -- list1.add((Object) null); -+ list1.add(null); // Paper - decompile fix - acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { - if (throwable != null) { - completablefuture.completeExceptionally(throwable); -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index f85889a232998520761731a17f3d293d3360fe2c..76675ad1633dbaebb180842b9914fac18741c62e 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -241,8 +241,8 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, int j, int k) { -- int l = i + j + k; -+ public static Iterable a(BlockPosition blockposition, int p_i, int p_j, int p_k) { // Paper - decompile issues - variable name conflicts to inner class field refs -+ int l_decompiled = p_i + p_j + p_k; // Paper - decompile issues - int i1 = blockposition.getX(); - int j1 = blockposition.getY(); - int k1 = blockposition.getZ(); -@@ -270,15 +270,15 @@ public class BlockPosition extends BaseBlockPosition { - ++this.l; - if (this.l > this.j) { - ++this.i; -- if (this.i > l) { -+ if (this.i > l_decompiled) { // Paper - use proper l above (first line of this method) - return (BlockPosition) this.endOfData(); - } - -- this.j = Math.min(i, this.i); -+ this.j = Math.min(p_i, this.i); // Paper - decompile issues - this.l = -this.j; - } - -- this.k = Math.min(j, this.i - Math.abs(this.l)); -+ this.k = Math.min(p_j, this.i - Math.abs(this.l)); // Paper - decompile issues - this.m = -this.k; - } - -@@ -286,7 +286,7 @@ public class BlockPosition extends BaseBlockPosition { - int i2 = this.m; - int j2 = this.i - Math.abs(l1) - Math.abs(i2); - -- if (j2 <= k) { -+ if (j2 <= p_k) { // Paper - decompile issues - this.n = j2 != 0; - blockposition_mutableblockposition = this.h.d(i1 + l1, j1 + i2, k1 + j2); - } -@@ -355,13 +355,13 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, EnumDirection enumdirection, EnumDirection enumdirection1) { -+ public static Iterable a(BlockPosition blockposition, int I, EnumDirection enumdirection, EnumDirection enumdirection1) { // Paper - decompile fix - Validate.validState(enumdirection.n() != enumdirection1.n(), "The two directions cannot be on the same axis", new Object[0]); - return () -> { - return new AbstractIterator() { - private final EnumDirection[] e = new EnumDirection[]{enumdirection, enumdirection1, enumdirection.opposite(), enumdirection1.opposite()}; - private final BlockPosition.MutableBlockPosition f = blockposition.i().c(enumdirection1); -- private final int g = 4 * i; -+ private final int g = 4 * I; - private int h = -1; - private int i; - private int j; -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index b173ed8a6abeee41ce48e03f6403f2eb4978155b..e543b6927280a14e1d1220534758289934e31282 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -27,7 +27,7 @@ public class RegistryBlockID implements Registry { - this.b.put(t0, i); - - while (this.c.size() <= i) { -- this.c.add((Object) null); -+ this.c.add(null); // Paper - decompile fix - } - - this.c.set(i, t0); -@@ -41,6 +41,13 @@ public class RegistryBlockID implements Registry { - this.a(t0, this.a); - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(T t) { -+ return getId(t); -+ } -+ // Paper end -+ - public int getId(T t0) { - Integer integer = (Integer) this.b.get(t0); - -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index 170a65cb13e7b87f64cd28331431ba55d53702cd..d6e51f82f6df2d7058806f3e483766e18398af77 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -20,7 +20,7 @@ public interface NBTBase { - - NBTTagType b(); - -- NBTBase clone(); -+ public NBTBase clone(); // Paper - decompile fix - - default String asString() { - return this.toString(); -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index be4d54099a0deb0e0275208ac61c8a172a48b398..850d3a7bb8ae4c43c0e2f737cfe69261f338b026 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -18,6 +18,7 @@ import java.util.zip.GZIPOutputStream; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; -+import io.netty.buffer.ByteBufInputStream; // Paper - - public class NBTCompressedStreamTools { - -@@ -137,7 +138,7 @@ public class NBTCompressedStreamTools { - - public static NBTTagCompound a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException { - // Spigot start -- if ( datainput instanceof io.netty.buffer.ByteBufInputStream ) -+ if ( datainput instanceof ByteBufInputStream) // Paper - { - datainput = new DataInputStream(new org.spigotmc.LimitStream((InputStream) datainput, nbtreadlimiter)); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 35cca76fb7c7aa736e64185b44016e65cfaef6cd..4f6f6f51f9807bafa88482c0fe776c8b163107d7 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -53,7 +53,7 @@ public class NBTTagList extends NBTList { - return "TAG_List"; - } - }; -- private static final ByteSet b = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); -+ private static final ByteSet b = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix - private final List list; - private byte type; - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index ab08336043d4f558434ed1f38d25cc555ace1ac0..a892521db1197369bf6363bd2f5da24bf53643ab 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -12,6 +12,8 @@ import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketListenerPlayIn; -+import net.minecraft.network.protocol.game.PacketListenerPlayOut; - import net.minecraft.network.protocol.game.PacketPlayInAbilities; - import net.minecraft.network.protocol.game.PacketPlayInAdvancements; - import net.minecraft.network.protocol.game.PacketPlayInArmAnimation; -@@ -146,24 +148,30 @@ import net.minecraft.network.protocol.game.PacketPlayOutWindowItems; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; -+import net.minecraft.network.protocol.handshake.PacketHandshakingInListener; - import net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol; - import net.minecraft.network.protocol.login.PacketLoginInCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginInEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginInListener; - import net.minecraft.network.protocol.login.PacketLoginInStart; - import net.minecraft.network.protocol.login.PacketLoginOutCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginOutDisconnect; - import net.minecraft.network.protocol.login.PacketLoginOutEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginOutListener; - import net.minecraft.network.protocol.login.PacketLoginOutSetCompression; - import net.minecraft.network.protocol.login.PacketLoginOutSuccess; -+import net.minecraft.network.protocol.status.PacketStatusInListener; - import net.minecraft.network.protocol.status.PacketStatusInPing; - import net.minecraft.network.protocol.status.PacketStatusInStart; -+import net.minecraft.network.protocol.status.PacketStatusOutListener; - import net.minecraft.network.protocol.status.PacketStatusOutPong; - import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; - import org.apache.logging.log4j.LogManager; - - public enum EnumProtocol { - -- HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); -+ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut -+ HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); - - private static final EnumProtocol[] e = new EnumProtocol[4]; - private static final Map>, EnumProtocol> f = Maps.newHashMap(); -@@ -248,7 +256,7 @@ public enum EnumProtocol { - private final List>> b; - - private a() { -- this.a = (Object2IntMap) SystemUtils.a((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { -+ this.a = (Object2IntMap) SystemUtils.a(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error - object2intopenhashmap.defaultReturnValue(-1); - }); - this.b = Lists.newArrayList(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a95c52035177cb86c7e3a580d5c26a5dd20a17e2..81cff54c93bc04d19e3cc0f5307799c62d139ab2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1675,9 +1675,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrantmap(resourcepackrepository::a).filter(Objects::nonNull).map(ResourcePackLoader::d).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error - }, this).thenCompose((immutablelist) -> { -- return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); -+ return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); // Paper - decompile error - }).thenAcceptAsync((datapackresources) -> { - this.dataPackResources.close(); - this.dataPackResources = datapackresources; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index 5a51f47f747382ec2a30bb47bcb1f7c61dd4c369..e066848127cb9a42e8c39422691cc65132cac6bb 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -179,7 +179,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - public void queueUpdate() { - if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -- this.b.a((Object) (() -> { -+ this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); - })); -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 1c500e1193296f92f03a94e2cf085b215daaad6c..51ef4adf66c1e21093e63ab46fa47e66c2425fdb 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -23,7 +23,7 @@ public final class Ticket implements Comparable> { - } else { - int j = Integer.compare(System.identityHashCode(this.a), System.identityHashCode(ticket.a)); - -- return j != 0 ? j : this.a.a().compare(this.identifier, ticket.identifier); -+ return j != 0 ? j : this.a.a().compare(this.identifier, (T)ticket.identifier); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 144c80a4f3f827d5ee0a9220d12c49ee9aa3f096..7f9a1d64d123ce54608497a0e0a37d161d8c9d3c 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1919,7 +1919,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - // CraftBukkit - decompile error -- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { -+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix - return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); - }).collect(Collectors.joining(",")); - } catch (Exception exception) { -diff --git a/src/main/java/net/minecraft/stats/ServerStatisticManager.java b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -index 322a4b584c6223b08581affb2e9919df19c0267b..1efab34e03199879f5e0dcee0ff79ce2c23c73bc 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatisticManager.java -+++ b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -@@ -203,7 +203,7 @@ public class ServerStatisticManager extends StatisticManager { - ObjectIterator objectiterator = this.a.object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - Statistic statistic = (Statistic) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); - - ((JsonObject) map.computeIfAbsent(statistic.getWrapper(), (statisticwrapper) -> { -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index e56b8e172d96c5508457fcf3f5a0cf0d2d2d8d7c..427daa94322f47b4eaf881d85a01fed239db549a 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -23,11 +23,11 @@ public class ArraySetSorted extends AbstractSet { - } - - public static > ArraySetSorted a(int i) { -- return new ArraySetSorted<>(i, Comparator.naturalOrder()); -+ return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } - - private static T[] a(Object[] aobject) { -- return (Object[]) aobject; -+ return (T[])aobject; // Paper - decompile fix - } - - private int c(T t0) { -@@ -101,7 +101,7 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean remove(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - if (i >= 0) { - this.d(i); -@@ -116,7 +116,7 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean contains(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - return i >= 0; - } -@@ -135,7 +135,7 @@ public class ArraySetSorted extends AbstractSet { - - public U[] toArray(U[] au) { - if (au.length < this.c) { -- return (Object[]) Arrays.copyOf(this.b, this.c, au.getClass()); -+ return (U[])Arrays.copyOf(this.b, this.c, au.getClass()); // Paper - decompile fix - } else { - System.arraycopy(this.b, 0, au, 0, this.c); - if (au.length > this.c) { -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index d88e55c64f80707b4a9b1e271714c2dbdee9a38a..6150f7a5c5004ac79414ab22dbaa3439dc8afdb4 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -18,11 +18,18 @@ public class RegistryID implements Registry { - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(K k) { -+ return getId(k); -+ } -+ // Paper end -+ - public int getId(@Nullable K k0) { - return this.c(this.b(k0, this.d(k0))); - } -@@ -56,9 +63,9 @@ public class RegistryID implements Registry { - K[] ak = this.b; - int[] aint = this.c; - -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 6abf1459cc97c261daf3c116521574d31a77a338..2b2c03ab62816f3d21ef953c4a45f55e3997cca6 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -55,7 +55,7 @@ public abstract class IAsyncTaskHandler implements Mailbox implements Mailbox implements Mailbox, AutoCloseable, Runnable { - - public void run() { - try { -- this.a((i) -> { -+ this.a((int i) -> { // Paper - decompile fix - return i == 0; - }); - } finally { -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index fe5dcce3873ca2724ac9d416d6f5d3c65d0fdafe..aa1d948e6aebef25f0f4c4c07f5131d2e8387e59 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -191,9 +191,9 @@ public class VillagePlace extends RegionFileSection { - } - - private static boolean a(ChunkSection chunksection) { -- Set set = VillagePlaceType.x; -+ Set set = VillagePlaceType.x; // Paper - decompile error - -- set.getClass(); -+ //set.getClass(); // Paper - decompile error - return chunksection.a(set::contains); - } - -@@ -211,7 +211,7 @@ public class VillagePlace extends RegionFileSection { - SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { - return Pair.of(sectionposition, this.d(sectionposition.s())); - }).filter((pair) -> { -- return !(Boolean) ((Optional) pair.getSecond()).map(VillagePlaceSection::a).orElse(false); -+ return !(Boolean) (pair.getSecond()).map(VillagePlaceSection::a).orElse(false); // Paper - decompile fix - }).map((pair) -> { - return ((SectionPosition) pair.getFirst()).r(); - }).filter((chunkcoordintpair) -> { -@@ -263,7 +263,7 @@ public class VillagePlace extends RegionFileSection { - - private final Predicate d; - -- private Occupancy(Predicate predicate) { -+ private Occupancy(Predicate predicate) { // Paper - decompile fix - this.d = predicate; - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index fc1f0cd4b70cdd0dda538d8867fab4cb8443120e..c181d5f5e6108ade54fc97c665897d1db5e90719 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -65,7 +65,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - this.goalSelector.a(2, new EntityIllagerAbstract.b(this)); - this.goalSelector.a(3, new EntityRaider.a(this, 10.0F)); - this.goalSelector.a(4, new EntityVindicator.c(this)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index fe1dde99f758daa730acacc78237d92aa443ab6d..764ff5d9ffb541a356a6bc8b321e619849dde747 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -47,12 +47,12 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - - public class VillagerTrades { - -- public static final Map> a = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { -+ public static final Map> a = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix - hashmap.put(VillagerProfession.FARMER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHEAT, 20, 16, 2), new VillagerTrades.b(Items.POTATO, 26, 16, 2), new VillagerTrades.b(Items.CARROT, 22, 16, 2), new VillagerTrades.b(Items.BEETROOT, 15, 16, 2), new VillagerTrades.h(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.h(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.h(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.COOKIE, 3, 18, 10), new VillagerTrades.b(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.i(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.i(MobEffects.JUMP, 160, 15), new VillagerTrades.i(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.i(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.i(MobEffects.POISON, 280, 15), new VillagerTrades.i(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.h(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); -- hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); -+ hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.SHEPHERD, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.h(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.b(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.b(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.h(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.b(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.b(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.b(Items.RED_DYE, 12, 16, 20), new VillagerTrades.b(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.h(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.b(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.b(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.b(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.b(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.b(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.PAINTING, 2, 3, 30)}))); - hashmap.put(VillagerProfession.FLETCHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STICK, 32, 16, 2), new VillagerTrades.h(Items.ARROW, 1, 16, 1), new VillagerTrades.g(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FLINT, 26, 12, 10), new VillagerTrades.h(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 14, 16, 20), new VillagerTrades.h(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FEATHER, 24, 16, 30), new VillagerTrades.e(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.es, 8, 12, 30), new VillagerTrades.e(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.j(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); -- hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); -+ hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.CARTOGRAPHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.h(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.dP, 11, 16, 10), new VillagerTrades.k(13, StructureGenerator.MONUMENT, MapIcon.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COMPASS, 1, 12, 20), new VillagerTrades.k(14, StructureGenerator.MANSION, MapIcon.Type.MANSION, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); - hashmap.put(VillagerProfession.CLERIC, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.h(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.h(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.h(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SCUTE, 4, 12, 30), new VillagerTrades.b(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.h(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.h(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); - hashmap.put(VillagerProfession.ARMORER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COAL, 15, 16, 2), new VillagerTrades.h(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.h(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.b(Items.DIAMOND, 1, 12, 20), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.e(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.e(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); -diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -index 54a636a3d5fdd0107cd0a41167ab1626469fe042..5ba58bf1a47c696235e6e7a4a6815104bc23de80 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -@@ -75,7 +75,7 @@ public class CraftingManager extends ResourceDataJson { - } - - this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { -- return (entry1.getValue()); // CraftBukkit -+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* - })); - CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); - } -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index d24f97593777d6929271520f7501a800f1aadaa6..4ece69851e7b05016f52c291ce911eb791cf3a23 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -167,22 +167,22 @@ public interface IEntityAccess { - - @Nullable - default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.a(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.b(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T a(List list, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { - double d3 = -1.0D; - T t0 = null; -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t1 = (EntityLiving) iterator.next(); -+ T t1 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t1)) { - double d4 = t1.h(d0, d1, d2); -@@ -215,10 +215,10 @@ public interface IEntityAccess { - default List a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { - List list = this.a(oclass, axisalignedbb, (Predicate) null); - List list1 = Lists.newArrayList(); -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (EntityLiving) iterator.next(); -+ T t0 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t0)) { - list1.add(t0); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 116a5e4ded3ccf935fd143f2512098c22ec2ad76..f3bcb96232d18abbcd86b079a7c5830bb30d75d2 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -38,13 +38,13 @@ public class NextTickListEntry { - return this.a.hashCode(); - } - -- public static Comparator> a() { -+ public static Comparator a() { // Paper - decompile fix - return Comparator.comparingLong((nextticklistentry) -> { -- return nextticklistentry.b; -+ return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix - }).thenComparing((nextticklistentry) -> { -- return nextticklistentry.c; -+ return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix - }).thenComparingLong((nextticklistentry) -> { -- return nextticklistentry.f; -+ return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 6672d74426d6a334d52f641c48d3a352c2bb6605..7147cdda756ccb3d4f6880802128f68601783883 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -49,8 +49,15 @@ import org.apache.logging.log4j.Logger; - public final class BiomeBase { - - public static final Logger LOGGER = LogManager.getLogger(); -+ // Paper start -+ private static class dProxy extends BiomeBase.d { -+ private dProxy(Precipitation biomebase_precipitation, float f, TemperatureModifier biomebase_temperaturemodifier, float f1) { -+ super(biomebase_precipitation, f, biomebase_temperaturemodifier, f1); -+ } -+ }; -+ // Paper end - public static final Codec b = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -@@ -67,7 +74,7 @@ public final class BiomeBase { - })).apply(instance, BiomeBase::new); - }); - public static final Codec c = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index a549195e67236c0146861b896fb9e4907073af58..8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -160,7 +160,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { - private static void a(EnumDirection enumdirection, Entity entity, double d0, EnumDirection enumdirection1) { - TileEntityPiston.h.set(enumdirection); - entity.move(EnumMoveType.PISTON, new Vec3D(d0 * (double) enumdirection1.getAdjacentX(), d0 * (double) enumdirection1.getAdjacentY(), d0 * (double) enumdirection1.getAdjacentZ())); -- TileEntityPiston.h.set((Object) null); -+ TileEntityPiston.h.set(null); // Paper - decompile fix - } - - private void g(float f) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index 074bd5f060c6bb80568b72d23ce84c27ba774578..e4b59a85ee9b435b2e86d4c7d78b7224773f6967 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -28,11 +28,11 @@ public abstract class IBlockDataHolder { - } else { - IBlockState iblockstate = (IBlockState) entry.getKey(); - -- return iblockstate.getName() + "=" + this.a(iblockstate, (Comparable) entry.getValue()); -+ return iblockstate.getName() + "=" + this.a((IBlockState) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix - } - } - -- private > String a(IBlockState iblockstate, Comparable comparable) { -+ private > String a(IBlockState iblockstate, T comparable) { // Paper - decompile error - return iblockstate.a(comparable); - } - }; -@@ -48,11 +48,11 @@ public abstract class IBlockDataHolder { - } - - public > S a(IBlockState iblockstate) { -- return this.set(iblockstate, (Comparable) a(iblockstate.getValues(), (Object) this.get(iblockstate))); -+ return this.set(iblockstate, a(iblockstate.getValues(), this.get(iblockstate))); // Paper - decompile error - } - - protected static T a(Collection collection, T t0) { -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - - do { - if (!iterator.hasNext()) { -@@ -94,7 +94,7 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c); - } else { -- return (Comparable) iblockstate.getType().cast(comparable); -+ return iblockstate.getType().cast(comparable); // Paper - decompile error - } - } - -@@ -110,7 +110,7 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c); - } else if (comparable == v0) { -- return this; -+ return (S) this; // Paper - decompile error - } else { - S s0 = this.e.get(iblockstate, v0); - -@@ -162,7 +162,7 @@ public abstract class IBlockDataHolder { - return codec.dispatch("Name", (iblockdataholder) -> { - return iblockdataholder.c; - }, (object) -> { -- S s0 = (IBlockDataHolder) function.apply(object); -+ S s0 = function.apply(object); // Paper - decompile error - - return s0.getStateMap().isEmpty() ? Codec.unit(s0) : s0.d.fieldOf("Properties").codec(); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index a6aaf0efed5a9c5e458ca04a80a7a5e71a31d886..de85894beae7ee7d276cf2af3daa77377ce131c3 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -21,10 +21,10 @@ public class BlockStateEnum & INamable> extends IBlockState - protected BlockStateEnum(String s, Class oclass, Collection collection) { - super(s, oclass); - this.a = ImmutableSet.copyOf(collection); -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (Enum) iterator.next(); -+ T t0 = iterator.next(); // Paper - Decompile fix - String s1 = ((INamable) t0).getName(); - - if (this.b.containsKey(s1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index 3e6ba74027685c6190426c825736e84cda87ca63..e3969bad5be64bb41e2973751605d6820c16f021 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -17,12 +17,10 @@ public abstract class IBlockState> { - private final Codec> e; - - protected IBlockState(String s, Class oclass) { -- this.d = Codec.STRING.comapFlatMap((s1) -> { -- return (DataResult) this.b(s1).map(DataResult::success).orElseGet(() -> { -- return DataResult.error("Unable to read property: " + this + " with value: " + s1); -- }); -- }, this::a); -- this.e = this.d.xmap(this::b, IBlockState.a::b); -+ this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error -+ return DataResult.error("Unable to read property: " + this + " with value: " + s1); -+ }), this::a); -+ this.e = this.d.xmap(this::b, (IBlockState.a param) -> param.b()); // Paper - decompile fix - this.a = oclass; - this.b = s; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 88c2643a18165bd7a9e6e056b926d6e894ff60d4..859561a5dccba6548967b685b20e8fcfc296db2a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -89,7 +89,7 @@ public class IOWorker implements AutoCloseable { - return this.a(() -> { - try { - this.d.a(); -- return Either.left((Object) null); -+ return Either.left(null); // Paper - decompile error - } catch (Exception exception) { - IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); - return Either.right(exception); -@@ -123,13 +123,13 @@ public class IOWorker implements AutoCloseable { - } - - private void c() { -- this.c.a((Object) (new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); -+ this.c.a((new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); // Paper - decompile error - } - - private void a(ChunkCoordIntPair chunkcoordintpair, IOWorker.a ioworker_a) { - try { - this.d.write(chunkcoordintpair, ioworker_a.a); -- ioworker_a.b.complete((Object) null); -+ ioworker_a.b.complete(null); // Paper - decompile fix - } catch (Exception exception) { - IOWorker.LOGGER.error("Failed to store chunk {}", chunkcoordintpair, exception); - ioworker_a.b.completeExceptionally(exception); -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 6fb0c92e7cb6117d919af613dae87fa4e99f5081..f727cc456bd23816c4e70be83c395d1d8ca7d876 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -430,7 +430,7 @@ public class EnderDragonBattle { - } - } - -- worldgenendtrophy.b((WorldGenFeatureConfiguration) WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); -+ worldgenendtrophy.b(WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); // Paper - decompile fix - } - - private EntityEnderDragon o() { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 44ad3fb2551f681b58b82e7c4f56bbc5a3b4486e..6724927be178cb9a358a9276d01894a63154b7b3 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -71,13 +71,13 @@ public abstract class StructureGenerator - public static final StructureGenerator BASTION_REMNANT = a("Bastion_Remnant", new WorldGenFeatureBastionRemnant(WorldGenFeatureVillageConfiguration.a), WorldGenStage.Decoration.SURFACE_STRUCTURES); - public static final List> t = ImmutableList.of(StructureGenerator.PILLAGER_OUTPOST, StructureGenerator.VILLAGE, StructureGenerator.NETHER_FOSSIL); - private static final MinecraftKey w = new MinecraftKey("jigsaw"); -- private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); -+ private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); // Paper - decompile fix - private final Codec>> y; - - private static > F a(String s, F f0, WorldGenStage.Decoration worldgenstage_decoration) { - StructureGenerator.a.put(s.toLowerCase(Locale.ROOT), f0); - StructureGenerator.u.put(f0, worldgenstage_decoration); -- return (StructureGenerator) IRegistry.a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), (Object) f0); -+ return (F) IRegistry.>a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), f0); // Paper - decomp fix - } - - public StructureGenerator(Codec codec) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 52564cce4146f49a906729b3ed9488a7a829ea3f..befc8f846c772d58ee687ad427bb71206b4dc43e 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -34,10 +34,10 @@ public class LightEngineStorageSky extends LightEngineStorage= l) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 45c1d79e0bb2fcffea31513c3d003d28140146b9..3910daeaa177639fa8055301304634c2014dc20f 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -44,7 +44,7 @@ public class WorldPersistentData { - if (t0 != null) { - return t0; - } else { -- T t1 = (PersistentBase) supplier.get(); -+ T t1 = supplier.get(); // Paper - decompile fix - - this.a(t1); - return t1; -@@ -53,7 +53,7 @@ public class WorldPersistentData { - - @Nullable - public T b(Supplier supplier, String s) { -- PersistentBase persistentbase = (PersistentBase) this.data.get(s); -+ T persistentbase = (T) this.data.get(s); // Paper - decompile fix - - if (persistentbase == null && !this.data.containsKey(s)) { - persistentbase = this.c(supplier, s); -@@ -69,7 +69,7 @@ public class WorldPersistentData { - File file = this.a(s); - - if (file.exists()) { -- T t0 = (PersistentBase) supplier.get(); -+ T t0 = supplier.get(); // Paper - decompile fix - NBTTagCompound nbttagcompound = this.a(s, SharedConstants.getGameVersion().getWorldVersion()); - - t0.a(nbttagcompound.getCompound("data")); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -index 9421e175fffab7014461aa02e7e36d719837ec11..b6abbe9f1de66cd8e9d2e7127813ce56a0446faf 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -@@ -43,7 +43,7 @@ public abstract class LootEntryAbstract implements LootEntryChildren { - - // CraftBukkit start - @Override -- public final void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { -+ public void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { // Paper - remove final - if (!org.apache.commons.lang3.ArrayUtils.isEmpty(t0.d)) { - jsonobject.add("conditions", jsonserializationcontext.serialize(t0.d)); - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index 0e3fe138fc11bd7e648296922c651cecaab8e71e..ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -132,7 +132,7 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - @Override - public T b(LootItemFunction.a lootitemfunction_a) { - this.c.add(lootitemfunction_a.b()); -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - protected LootItemFunction[] a() { -@@ -141,12 +141,12 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public T a(int i) { - this.a = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - public T b(int i) { - this.b = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index f516e7440ed306b1ace9b35ae82f70ca69df51f3..38125a60bad4830db9de3580ab6d85fd122a0689 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -89,7 +89,7 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - public b() {} - - public void a(JsonObject jsonobject, LootItemFunctionExplorationMap lootitemfunctionexplorationmap, JsonSerializationContext jsonserializationcontext) { -- super.a(jsonobject, (LootItemFunctionConditional) lootitemfunctionexplorationmap, jsonserializationcontext); -+ super.a(jsonobject, lootitemfunctionexplorationmap, jsonserializationcontext); // Paper - decompile fix - if (!lootitemfunctionexplorationmap.e.equals(LootItemFunctionExplorationMap.a)) { - jsonobject.add("destination", jsonserializationcontext.serialize(lootitemfunctionexplorationmap.e.i())); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index afd30320da51bf467d66e94f682936ed8db96d90..c58d380b96e81d65d7c254a9e53017e5157769b0 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -38,7 +38,7 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - double d1 = flag4 ? doublelist.getDouble(i++) : doublelist1.getDouble(j++); - - if ((i != 0 && flag2 || flag4 || flag1) && (j != 0 && flag3 || !flag4 || flag)) { -- if (d0 < d1 - 1.0E-7D) { -+ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.b.add(i - 1); - this.c.add(j - 1); - this.a.add(d1); diff --git a/Spigot-Server-Patches/0004-MC-Utils.patch b/Spigot-Server-Patches/0004-MC-Utils.patch deleted file mode 100644 index 605823b9b280..000000000000 --- a/Spigot-Server-Patches/0004-MC-Utils.patch +++ /dev/null @@ -1,4850 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:55:47 -0400 -Subject: [PATCH] MC Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4029dc68cf35d63aa70c4a76c35bf65a7fc6358f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -@@ -0,0 +1,68 @@ -+package com.destroystokyo.paper.util.concurrent; -+ -+import java.util.concurrent.atomic.AtomicLong; -+ -+/** -+ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java -+ * @author Spottedleaf -+ */ -+public final class WeakSeqLock { -+ // TODO when the switch to J11 is made, nuke this class from orbit -+ -+ protected final AtomicLong lock = new AtomicLong(); -+ -+ public WeakSeqLock() { -+ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed -+ } -+ -+ public void acquireWrite() { -+ // must be release-type write -+ this.lock.lazySet(this.lock.get() + 1); -+ } -+ -+ public boolean canRead(final long read) { -+ return (read & 1) == 0; -+ } -+ -+ public boolean tryAcquireWrite() { -+ this.acquireWrite(); -+ return true; -+ } -+ -+ public void releaseWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock + 1); -+ } -+ -+ public void abortWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock ^ 1); -+ } -+ -+ public long acquireRead() { -+ int failures = 0; -+ long curr; -+ -+ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { -+ // without j11, our only backoff is the yield() call... -+ -+ if (++failures > 5_000) { /* TODO determine a threshold */ -+ Thread.yield(); -+ } -+ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ -+ } -+ -+ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier -+ return curr; -+ } -+ -+ public boolean tryReleaseRead(final long read) { -+ return this.lock.get() == read; // volatile acts as the load-load barrier -+ } -+ -+ public long getSequentialCounter() { -+ return this.lock.get(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -new file mode 100644 -index 0000000000000000000000000000000000000000..59868f37d14bbc0ece0836095cdad148778995e6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -@@ -0,0 +1,162 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -+import it.unimi.dsi.fastutil.objects.ObjectIterator; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Int { -+ -+ protected final Long2IntOpenHashMap updatingMap; -+ protected final Long2IntOpenHashMap visibleMap; -+ protected final Long2IntOpenHashMap queuedPuts; -+ protected final LongOpenHashSet queuedRemove; -+ -+ protected int queuedDefaultReturnValue; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Int() { -+ this(16, 0.75f); -+ } -+ -+ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.queuedPuts = new Long2IntOpenHashMap(); -+ this.queuedRemove = new LongOpenHashSet(); -+ } -+ -+ public void queueDefaultReturnValue(final int dfl) { -+ this.queuedDefaultReturnValue = dfl; -+ this.updatingMap.defaultReturnValue(dfl); -+ } -+ -+ public int queueUpdate(final long k, final int v) { -+ this.queuedRemove.remove(k); -+ this.queuedPuts.put(k, v); -+ -+ return this.updatingMap.put(k, v); -+ } -+ -+ public int queueRemove(final long k) { -+ this.queuedPuts.remove(k); -+ this.queuedRemove.add(k); -+ -+ return this.updatingMap.remove(k); -+ } -+ -+ public int getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public int getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public int getVisibleAsync(final long k) { -+ long readlock; -+ int ret = 0; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean performUpdates() { -+ this.updatingMapSeqLock.acquireWrite(); -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ this.updatingMapSeqLock.releaseWrite(); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.put(key, val); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.remove(key); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.visibleMap.put(key, val); -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.visibleMap.remove(key); -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7bab31a312463cc963d9621cdc543a281459bd32 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -@@ -0,0 +1,202 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Object { -+ -+ protected static final Object REMOVED = new Object(); -+ -+ protected final Long2ObjectLinkedOpenHashMap updatingMap; -+ protected final Long2ObjectLinkedOpenHashMap visibleMap; -+ protected final Long2ObjectLinkedOpenHashMap queuedChanges; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Object() { -+ this(16, 0.75f); // dfl for fastutil -+ } -+ -+ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ -+ public V queueUpdate(final long k, final V value) { -+ this.queuedChanges.put(k, value); -+ return this.updatingMap.put(k, value); -+ } -+ -+ public V queueRemove(final long k) { -+ this.queuedChanges.put(k, REMOVED); -+ return this.updatingMap.remove(k); -+ } -+ -+ public V getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public boolean updatingContainsKey(final long k) { -+ return this.updatingMap.containsKey(k); -+ } -+ -+ public V getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public boolean visibleContainsKey(final long k) { -+ return this.visibleMap.containsKey(k); -+ } -+ -+ public V getVisibleAsync(final long k) { -+ long readlock; -+ V ret = null; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean visibleContainsKeyAsync(final long k) { -+ long readlock; -+ boolean ret = false; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.containsKey(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getVisibleMap() { -+ return this.visibleMap; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { -+ return this.updatingMap; -+ } -+ -+ public int getVisibleSize() { -+ return this.visibleMap.size(); -+ } -+ -+ public int getVisibleSizeAsync() { -+ long readlock; -+ int ret; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ ret = this.visibleMap.size(); -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getUpdatingValues() { -+ return this.updatingMap.values(); -+ } -+ -+ public List getUpdatingValuesCopy() { -+ return new ArrayList<>(this.updatingMap.values()); -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getVisibleValues() { -+ return this.visibleMap.values(); -+ } -+ -+ public List getVisibleValuesCopy() { -+ return new ArrayList<>(this.visibleMap.values()); -+ } -+ -+ public boolean performUpdates() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ -+ try { -+ this.updatingMapSeqLock.acquireWrite(); -+ -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bf63a0e87f8c9529e473269c0626051c81bb04ea ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.world.level.chunk.Chunk; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class ChunkList implements Iterable { -+ -+ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); -+ { -+ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Chunk[] EMPTY_LIST = new Chunk[0]; -+ -+ protected Chunk[] chunks = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Chunk chunk) { -+ return this.chunkToIndex.containsKey(chunk.coordinateKey); -+ } -+ -+ public boolean remove(final Chunk chunk) { -+ final int index = this.chunkToIndex.remove(chunk.coordinateKey); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Chunk end = this.chunks[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.chunkToIndex.put(end.coordinateKey, index); // update index -+ } -+ this.chunks[index] = end; -+ this.chunks[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Chunk chunk) { -+ final int count = this.count; -+ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Chunk[] list = this.chunks; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = chunk; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Chunk getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.chunks[index]; -+ } -+ -+ public Chunk getUnchecked(final int index) { -+ return this.chunks[index]; -+ } -+ -+ public Chunk[] getRawData() { -+ return this.chunks; -+ } -+ -+ public void clear() { -+ this.chunkToIndex.clear(); -+ Arrays.fill(this.chunks, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Chunk lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < ChunkList.this.count; -+ } -+ -+ @Override -+ public Chunk next() { -+ if (this.current >= ChunkList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = ChunkList.this.chunks[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Chunk lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ ChunkList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0133ea6feb1ab88f021f66855669f58367e7420b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import net.minecraft.world.entity.Entity; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class EntityList implements Iterable { -+ -+ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); -+ { -+ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Entity[] EMPTY_LIST = new Entity[0]; -+ -+ protected Entity[] entities = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Entity entity) { -+ return this.entityToIndex.containsKey(entity.getId()); -+ } -+ -+ public boolean remove(final Entity entity) { -+ final int index = this.entityToIndex.remove(entity.getId()); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Entity end = this.entities[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.entityToIndex.put(end.getId(), index); // update index -+ } -+ this.entities[index] = end; -+ this.entities[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Entity entity) { -+ final int count = this.count; -+ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Entity[] list = this.entities; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = entity; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Entity getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.entities[index]; -+ } -+ -+ public Entity getUnchecked(final int index) { -+ return this.entities[index]; -+ } -+ -+ public Entity[] getRawData() { -+ return this.entities; -+ } -+ -+ public void clear() { -+ this.entityToIndex.clear(); -+ Arrays.fill(this.entities, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Entity lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < EntityList.this.count; -+ } -+ -+ @Override -+ public Entity next() { -+ if (this.current >= EntityList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = EntityList.this.entities[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Entity lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ EntityList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d9fdc8196e53518ceac3aeb7bf3b98a0bd348f8f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -@@ -0,0 +1,128 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPaletteGlobal; -+import java.util.Arrays; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IBlockDataList { -+ -+ static final DataPaletteGlobal GLOBAL_PALETTE = (DataPaletteGlobal) ChunkSection.GLOBAL_PALETTE; -+ -+ // map of location -> (index | (location << 16) | (palette id << 32)) -+ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); -+ { -+ this.map.defaultReturnValue(Long.MAX_VALUE); -+ } -+ -+ private static final long[] EMPTY_LIST = new long[0]; -+ -+ private long[] byIndex = EMPTY_LIST; -+ private int size; -+ -+ public static int getLocationKey(final int x, final int y, final int z) { -+ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); -+ } -+ -+ public static IBlockData getBlockDataFromRaw(final long raw) { -+ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); -+ } -+ -+ public static int getIndexFromRaw(final long raw) { -+ return (int)(raw & 0xFFFF); -+ } -+ -+ public static int getLocationFromRaw(final long raw) { -+ return (int)((raw >>> 16) & 0xFFFF); -+ } -+ -+ public static long getRawFromValues(final int index, final int location, final IBlockData data) { -+ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); -+ } -+ -+ public static long setIndexRawValues(final long value, final int index) { -+ return value & ~(0xFFFF) | (index); -+ } -+ -+ public long add(final int x, final int y, final int z, final IBlockData data) { -+ return this.add(getLocationKey(x, y, z), data); -+ } -+ -+ public long add(final int location, final IBlockData data) { -+ final long curr = this.map.get((short)location); -+ -+ if (curr == Long.MAX_VALUE) { -+ final int index = this.size++; -+ final long raw = getRawFromValues(index, location, data); -+ this.map.put((short)location, raw); -+ -+ if (index >= this.byIndex.length) { -+ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); -+ } -+ -+ this.byIndex[index] = raw; -+ return raw; -+ } else { -+ final int index = getIndexFromRaw(curr); -+ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); -+ -+ this.map.put((short)location, raw); -+ -+ return raw; -+ } -+ } -+ -+ public long remove(final int x, final int y, final int z) { -+ return this.remove(getLocationKey(x, y, z)); -+ } -+ -+ public long remove(final int location) { -+ final long ret = this.map.remove((short)location); -+ final int index = getIndexFromRaw(ret); -+ if (ret == Long.MAX_VALUE) { -+ return ret; -+ } -+ -+ // move the entry at the end to this index -+ final int endIndex = --this.size; -+ final long end = this.byIndex[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); -+ } -+ this.byIndex[index] = end; -+ this.byIndex[endIndex] = 0L; -+ -+ return ret; -+ } -+ -+ public int size() { -+ return this.size; -+ } -+ -+ public long getRaw(final int index) { -+ return this.byIndex[index]; -+ } -+ -+ public int getLocation(final int index) { -+ return getLocationFromRaw(this.getRaw(index)); -+ } -+ -+ public IBlockData getData(final int index) { -+ return getBlockDataFromRaw(this.getRaw(index)); -+ } -+ -+ public void clear() { -+ this.size = 0; -+ this.map.clear(); -+ } -+ -+ public LongIterator getRawIterator() { -+ return this.map.values().iterator(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292ccc89356 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -@@ -0,0 +1,230 @@ -+package com.destroystokyo.paper.util.math; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IntegerUtil { -+ -+ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; -+ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; -+ -+ public static int ceilLog2(final int value) { -+ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static long ceilLog2(final long value) { -+ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final int value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final long value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int roundCeilLog2(final int value) { -+ // optimized variant of 1 << (32 - leading(val - 1)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) -+ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) -+ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static long roundCeilLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static int roundFloorLog2(final int value) { -+ // optimized variant of 1 << (31 - leading(val)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - 31 + leading(val)) -+ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); -+ } -+ -+ public static long roundFloorLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); -+ } -+ -+ public static boolean isPowerOfTwo(final int n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ public static boolean isPowerOfTwo(final long n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ -+ public static int getTrailingBit(final int n) { -+ return -n & n; -+ } -+ -+ public static long getTrailingBit(final long n) { -+ return -n & n; -+ } -+ -+ public static int trailingZeros(final int n) { -+ return Integer.numberOfTrailingZeros(n); -+ } -+ -+ public static long trailingZeros(final long n) { -+ return Long.numberOfTrailingZeros(n); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorMultiple(final long numbers) { -+ return (int)(numbers >>> 32); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorShift(final long numbers) { -+ return (int)numbers; -+ } -+ -+ // copied from hacker's delight (signed division magic value) -+ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt -+ public static long getDivisorNumbers(final int d) { -+ final int ad = IntegerUtil.branchlessAbs(d); -+ -+ if (ad < 2) { -+ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); -+ } -+ -+ final int two31 = 0x80000000; -+ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour -+ -+ int p = 31; -+ -+ // all these variables are UNSIGNED! -+ int t = two31 + (d >>> 31); -+ int anc = t - 1 - t%ad; -+ int q1 = (int)((two31 & mask)/(anc & mask)); -+ int r1 = two31 - q1*anc; -+ int q2 = (int)((two31 & mask)/(ad & mask)); -+ int r2 = two31 - q2*ad; -+ int delta; -+ -+ do { -+ p = p + 1; -+ q1 = 2*q1; // Update q1 = 2**p/|nc|. -+ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). -+ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) -+ q1 = q1 + 1; -+ r1 = r1 - anc; -+ } -+ q2 = 2*q2; // Update q2 = 2**p/|d|. -+ r2 = 2*r2; // Update r2 = rem(2**p, |d|). -+ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) -+ q2 = q2 + 1; -+ r2 = r2 - ad; -+ } -+ delta = ad - r2; -+ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); -+ -+ int magicNum = q2 + 1; -+ if (d < 0) { -+ magicNum = -magicNum; -+ } -+ int shift = p - 32; -+ return ((long)magicNum << 32) | shift; -+ } -+ -+ public static int branchlessAbs(final int val) { -+ // -n = -1 ^ n + 1 -+ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ public static long branchlessAbs(final long val) { -+ // -n = -1 ^ n + 1 -+ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ //https://github.com/skeeto/hash-prospector for hash functions -+ -+ //score = ~590.47984224483832 -+ public static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ //score = ~310.01596637036749 -+ public static int hash1(int x) { -+ x ^= x >>> 15; -+ x *= 0x356aaaad; -+ x ^= x >>> 17; -+ return x; -+ } -+ -+ public static int hash2(int x) { -+ x ^= x >>> 16; -+ x *= 0x7feb352d; -+ x ^= x >>> 15; -+ x *= 0x846ca68b; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public static int hash3(int x) { -+ x ^= x >>> 17; -+ x *= 0xed5ad4bb; -+ x ^= x >>> 11; -+ x *= 0xac4c1b51; -+ x ^= x >>> 15; -+ x *= 0x31848bab; -+ x ^= x >>> 14; -+ return x; -+ } -+ -+ //score = ~365.79959673201887 -+ public static long hash1(long x) { -+ x ^= x >>> 27; -+ x *= 0xb24924b71d2d354bL; -+ x ^= x >>> 28; -+ return x; -+ } -+ -+ //h2 hash -+ public static long hash2(long x) { -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ return x; -+ } -+ -+ public static long hash3(long x) { -+ x ^= x >>> 45; -+ x *= 0xc161abe5704b6c79L; -+ x ^= x >>> 41; -+ x *= 0xe3e5389aedbc90f7L; -+ x ^= x >>> 56; -+ x *= 0x1f9aba75a52db073L; -+ x ^= x >>> 53; -+ return x; -+ } -+ -+ private IntegerUtil() { -+ throw new RuntimeException(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..24407a3e653ba32ef6b921c346571ec734a72245 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -@@ -0,0 +1,453 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import javax.annotation.Nullable; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public abstract class AreaMap { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ -+ -+ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); -+ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); -+ -+ { -+ this.objectToViewDistance.defaultReturnValue(-1); -+ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ // we use linked for better iteration. -+ // map of: coordinate to set of objects in coordinate -+ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); -+ protected final PooledLinkedHashSets pooledHashSets; -+ -+ protected final ChangeCallback addCallback; -+ protected final ChangeCallback removeCallback; -+ protected final ChangeSourceCallback changeSourceCallback; -+ -+ public AreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public AreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null); -+ } -+ -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ this.pooledHashSets = pooledHashSets; -+ this.addCallback = addCallback; -+ this.removeCallback = removeCallback; -+ this.changeSourceCallback = changeSourceCallback; -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { -+ return this.areaMap.get(key); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkCoordIntPair chunkPos) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ // Long.MIN_VALUE indicates the object is not mapped -+ public final long getLastCoordinate(final E object) { -+ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); -+ } -+ -+ // -1 indicates the object is not mapped -+ public final int getLastViewDistance(final E object) { -+ return this.objectToViewDistance.getOrDefault(object, -1); -+ } -+ -+ // returns the total number of mapped chunks -+ public final int size() { -+ return this.areaMap.size(); -+ } -+ -+ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ -+ if (oldViewDistance == -1) { -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ } else { -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ } -+ -+ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); -+ if (oldViewDistance == -1) { -+ return false; -+ } else { -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (newPosition != oldPosition && this.changeSourceCallback != null) { -+ this.changeSourceCallback.accept(Object, oldPosition, newPosition); -+ } -+ } -+ -+ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); -+ if (oldViewDistance != -1) { -+ return false; -+ } -+ -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ this.objectToLastCoordinate.put(object, newPos); -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ -+ //this.validate(object, viewDistance); -+ -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ public final boolean remove(final E object) { -+ final long position = this.objectToLastCoordinate.removeLong(object); -+ final int viewDistance = this.objectToViewDistance.removeInt(object); -+ -+ if (viewDistance == -1) { -+ return false; -+ } -+ -+ final int currentX = MCUtil.getCoordinateX(position); -+ final int currentZ = MCUtil.getCoordinateZ(position); -+ -+ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); -+ this.removeObjectCallback(object, currentX, currentZ, viewDistance); -+ //this.validate(object, -1); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); -+ -+ // expensive op, only for debug -+ protected void validate(final E object, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ if (viewDistance < 0) { -+ expectedEntries = 0; -+ } -+ -+ final long currPosition = this.objectToLastCoordinate.getLong(object); -+ -+ final int centerX = MCUtil.getCoordinateX(currPosition); -+ final int centerZ = MCUtil.getCoordinateZ(currPosition); -+ -+ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); -+ iterator.hasNext();) { -+ -+ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.contains(object)) { -+ ++entiesGot; -+ -+ final int chunkX = MCUtil.getCoordinateX(key); -+ final int chunkZ = MCUtil.getCoordinateZ(key); -+ -+ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); -+ -+ if (current != null) { -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); -+ if (next == current) { -+ throw new IllegalStateException("Expected different map: got " + next.toString()); -+ } -+ this.areaMap.put(key, next); -+ -+ current = next; -+ // fall through to callback -+ } else { -+ current = empty; -+ } -+ -+ if (this.addCallback != null) { -+ try { -+ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); -+ -+ if (current == null) { -+ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); -+ -+ if (next == current) { -+ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ if (next != null) { -+ this.areaMap.put(key, next); -+ } else { -+ this.areaMap.remove(key); -+ } -+ -+ if (this.removeCallback != null) { -+ try { -+ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); -+ } -+ } -+ } -+ -+ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); -+ } -+ } -+ } -+ -+ /* math sign function except 0 returns 1 */ -+ protected static int sign(int val) { -+ return 1 | (val >> (Integer.SIZE - 1)); -+ } -+ -+ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); -+ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); -+ return; -+ } -+ -+ if (oldViewDistance != newViewDistance) { -+ // remove loop -+ -+ final int oldMinX = fromX - oldViewDistance; -+ final int oldMinZ = fromZ - oldViewDistance; -+ final int oldMaxX = fromX + oldViewDistance; -+ final int oldMaxZ = fromZ + oldViewDistance; -+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { -+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { -+ -+ // only remove if we're outside the new view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ // add loop -+ -+ final int newMinX = toX - newViewDistance; -+ final int newMinZ = toZ - newViewDistance; -+ final int newMaxX = toX + newViewDistance; -+ final int newMaxZ = toZ + newViewDistance; -+ for (int currX = newMinX; currX <= newMaxX; ++currX) { -+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { -+ -+ // only add if we're outside the old view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ // same view distance -+ -+ // used for relative positioning -+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise -+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeCallback { -+ -+ // if there is no previous position, then prevPos = Integer.MIN_VALUE -+ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); -+ -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeSourceCallback { -+ void accept(final E object, final long prevPos, final long newPos); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..905b76d1d65744fe35f56bb78ef75f49178a6a24 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -@@ -0,0 +1,175 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.ChunkCoordIntPair; -+ -+/** @author Spottedleaf */ -+public abstract class DistanceTrackingAreaMap extends AreaMap { -+ -+ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. -+ -+ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); -+ { -+ this.chunkToNearestDistance.defaultReturnValue(-1); -+ } -+ -+ protected final DistanceChangeCallback distanceChangeCallback; -+ -+ public DistanceTrackingAreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null, null); -+ } -+ -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, -+ final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback); -+ this.distanceChangeCallback = distanceChangeCallback; -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final long key) { -+ return this.chunkToNearestDistance.get(key); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final ChunkCoordIntPair chunkPos) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ protected final void recalculateDistance(final int chunkX, final int chunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); -+ if (state == null) { -+ final int oldDistance = this.chunkToNearestDistance.remove(key); -+ // nothing here. -+ if (oldDistance == -1) { -+ // nothing was here previously -+ return; -+ } -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); -+ } -+ return; -+ } -+ -+ int newDistance = Integer.MAX_VALUE; -+ -+ final Object[] rawData = state.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ final Object raw = rawData[i]; -+ -+ if (raw == null) { -+ continue; -+ } -+ -+ final E object = (E)raw; -+ final long location = this.objectToLastCoordinate.getLong(object); -+ -+ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); -+ -+ if (distance < newDistance) { -+ newDistance = distance; -+ } -+ } -+ -+ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); -+ -+ if (oldDistance != newDistance) { -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); -+ } -+ } -+ } -+ -+ @Override -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { -+ return; -+ } -+ -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); -+ this.addObjectCallback(object, toX, toZ, newViewDistance); -+ return; -+ } -+ -+ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); -+ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); -+ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); -+ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); -+ -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); -+ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); -+ -+ if (Math.max(distXOld, distZOld) <= oldViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ -+ final int distXNew = IntegerUtil.branchlessAbs(x - toX); -+ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); -+ -+ if (Math.max(distXNew, distZNew) <= newViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DistanceChangeCallback { -+ -+ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ed6133b07bc6c4662bd2099ea7dc8aabec37c853 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -@@ -0,0 +1,32 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class PlayerAreaMap extends AreaMap { -+ -+ public PlayerAreaMap() { -+ super(); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..eca1fea17184076635563717bb32c81187e2f6f7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -@@ -0,0 +1,24 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { -+ -+ public PlayerDistanceTrackingAreaMap() { -+ super(); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e51104e65a07b6ea7bbbcbb6afb066ef6401cc5b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -@@ -0,0 +1,287 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -+import java.lang.ref.WeakReference; -+ -+/** @author Spottedleaf */ -+public class PooledLinkedHashSets { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateAddCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateRemoveCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { -+ -+ public RawSetObjectLinkedOpenHashSet() { -+ super(); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity) { -+ super(capacity); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { -+ super(capacity, loadFactor); -+ } -+ -+ @Override -+ public RawSetObjectLinkedOpenHashSet clone() { -+ return (RawSetObjectLinkedOpenHashSet)super.clone(); -+ } -+ -+ public E[] getRawSet() { -+ return this.key; -+ } -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); -+ -+ final RawSetObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { -+ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this((PooledLinkedHashSets)null); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ private static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ return this.lastAddMap.get(); -+ } -+ -+ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ return this.lastRemoveMap.get(); -+ } -+ -+ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ public boolean contains(final Object element) { -+ return this.set.contains(element); -+ } -+ -+ public E[] getBackingSet() { -+ return this.set.getRawSet(); -+ } -+ -+ public int size() { -+ return this.set.size(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0c77068e9a53d1b8bbad0f3f6b420d6bc85f8c8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -@@ -0,0 +1,85 @@ -+package com.destroystokyo.paper.util.pooled; -+ -+import net.minecraft.server.MCUtil; -+import org.apache.commons.lang3.mutable.MutableInt; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class PooledObjects { -+ -+ /** -+ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. -+ */ -+ public class AutoReleased { -+ private final E object; -+ private final Runnable cleaner; -+ -+ public AutoReleased(E object, Runnable cleaner) { -+ this.object = object; -+ this.cleaner = cleaner; -+ } -+ -+ public final E getObject() { -+ return object; -+ } -+ -+ public final Runnable getCleaner() { -+ return cleaner; -+ } -+ } -+ -+ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); -+ -+ private final Supplier creator; -+ private final Consumer releaser; -+ private final int maxPoolSize; -+ private final ArrayDeque queue; -+ -+ public PooledObjects(final Supplier creator, int maxPoolSize) { -+ this(creator, maxPoolSize, null); -+ } -+ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { -+ if (creator == null) { -+ throw new NullPointerException("Creator must not be null"); -+ } -+ if (maxPoolSize <= 0) { -+ throw new IllegalArgumentException("Max pool size must be greater-than 0"); -+ } -+ -+ this.queue = new ArrayDeque<>(maxPoolSize); -+ this.maxPoolSize = maxPoolSize; -+ this.creator = creator; -+ this.releaser = releaser; -+ } -+ -+ public AutoReleased acquireCleaner(Object holder) { -+ return acquireCleaner(holder, this::release); -+ } -+ -+ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { -+ E resource = acquire(); -+ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); -+ return new AutoReleased(resource, cleaner); -+ } -+ -+ public final E acquire() { -+ E value; -+ synchronized (queue) { -+ value = this.queue.pollLast(); -+ } -+ return value != null ? value : this.creator.get(); -+ } -+ -+ public final void release(final E value) { -+ if (this.releaser != null) { -+ this.releaser.accept(value); -+ } -+ synchronized (this.queue) { -+ if (queue.size() < this.maxPoolSize) { -+ this.queue.addLast(value); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Collection; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class OptimizedSmallEnumSet> { -+ -+ private final Class enumClass; -+ private long backingSet; -+ -+ public OptimizedSmallEnumSet(final Class clazz) { -+ if (clazz == null) { -+ throw new IllegalArgumentException("Null class"); -+ } -+ if (!clazz.isEnum()) { -+ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); -+ } -+ this.enumClass = clazz; -+ } -+ -+ public boolean addUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev | key; -+ -+ return (prev & key) == 0; -+ } -+ -+ public boolean removeUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev & ~key; -+ -+ return (prev & key) != 0; -+ } -+ -+ public void clear() { -+ this.backingSet = 0L; -+ } -+ -+ public int size() { -+ return Long.bitCount(this.backingSet); -+ } -+ -+ public void addAllUnchecked(final Collection enums) { -+ for (final E element : enums) { -+ if (element == null) { -+ throw new NullPointerException("Null element"); -+ } -+ this.backingSet |= (1L << element.ordinal()); -+ } -+ } -+ -+ public long getBackingSet() { -+ return this.backingSet; -+ } -+ -+ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { -+ return (other.backingSet & this.backingSet) != 0; -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index bc7757b929ecce998094ddcdf51a4703e165a6d6..c8bb06a31242089ad950713bd5f94abbfe12adc8 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -78,7 +78,7 @@ public class SystemUtils { - } - - public static long getMonotonicNanos() { -- return SystemUtils.a.getAsLong(); -+ return System.nanoTime(); // Paper - } - - public static long getTimeMillis() { -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index fe3a3ce150de0e689c452b67d480b9d69471b330..25fdd55a7548cfaa45a541ad77f22f33c33e7471 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -18,9 +18,9 @@ public class BaseBlockPosition implements Comparable { - return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); - }); - public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); -- private int a; -- private int b; -- private int e; -+ private int a;public final void setX(final int x) { this.a = x; } // Paper - OBFHELPER -+ private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER -+ private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - - public BaseBlockPosition(int i, int j, int k) { - this.a = i; -@@ -64,15 +64,15 @@ public class BaseBlockPosition implements Comparable { - return this.e; - } - -- protected void o(int i) { -+ public void o(int i) { // Paper - protected -> public - this.a = i; - } - -- protected void p(int i) { -+ public void p(int i) { // Paper - protected -> public - this.b = i; - } - -- protected void q(int i) { -+ public void q(int i) { // Paper - protected -> public - this.e = i; - } - -@@ -108,6 +108,7 @@ public class BaseBlockPosition implements Comparable { - return this.distanceSquared(iposition.getX(), iposition.getY(), iposition.getZ(), true) < d0 * d0; - } - -+ public final double distanceSquared(BaseBlockPosition baseblockposition) { return j(baseblockposition); } // Paper - OBFHELPER - public double j(BaseBlockPosition baseblockposition) { - return this.distanceSquared((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ(), true); - } -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 76675ad1633dbaebb180842b9914fac18741c62e..9fb6db18c5c1f39b5a564c0f5f70498825defa97 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -105,6 +105,7 @@ public class BlockPosition extends BaseBlockPosition { - return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D ? this : new BlockPosition((double) this.getX() + d0, (double) this.getY() + d1, (double) this.getZ() + d2); - } - -+ public final BlockPosition add(int i, int j, int k) {return b(i, j, k);} // Paper - OBFHELPER - public BlockPosition b(int i, int j, int k) { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } -@@ -436,6 +437,7 @@ public class BlockPosition extends BaseBlockPosition { - return super.a(enumblockrotation).immutableCopy(); - } - -+ public final BlockPosition.MutableBlockPosition setValues(int i, int j, int k) { return d(i, j, k);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition d(int i, int j, int k) { - this.o(i); - this.p(j); -@@ -443,6 +445,7 @@ public class BlockPosition extends BaseBlockPosition { - return this; - } - -+ public final BlockPosition.MutableBlockPosition setValues(double d0, double d1, double d2) { return c(d0, d1, d2);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } -@@ -496,6 +499,7 @@ public class BlockPosition extends BaseBlockPosition { - } - } - -+ /* // Paper start - comment out useless overrides @Override - @Override - public void o(int i) { - super.o(i); -@@ -506,10 +510,10 @@ public class BlockPosition extends BaseBlockPosition { - super.p(i); - } - -- @Override - public void q(int i) { - super.q(i); - } -+ */ // Paper end - - @Override - public BlockPosition immutableCopy() { -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index e543b6927280a14e1d1220534758289934e31282..d5bec8b0e155ea5ae5746b6da571754a98e4125e 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -64,6 +64,7 @@ public class RegistryBlockID implements Registry { - return Iterators.filter(this.c.iterator(), Predicates.notNull()); - } - -+ public int size() { return this.a(); } // Paper - OBFHELPER - public int a() { - return this.b.size(); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index b2fb24e9ae19ab6e7039a98fc0c265f801be8a99..bf4826e90976fed2ae95e84cadc7f29433af1ddf 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -76,7 +76,7 @@ public class NBTTagCompound implements NBTBase { - return "TAG_Compound"; - } - }; -- private final Map map; -+ public final Map map; // Paper - - protected NBTTagCompound(Map map) { - this.map = map; -@@ -139,10 +139,16 @@ public class NBTTagCompound implements NBTBase { - this.map.put(s, NBTTagLong.a(i)); - } - -+ public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -+ -+ /** -+ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. -+ */ -+ public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { - return GameProfileSerializer.a(this.get(s)); - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 82d8a163df294e68b4db685b95553637f905db48..f093b465b868e6003bb2b5ee634a624b5b054493 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -168,6 +168,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER - private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - EnumProtocol enumprotocol = EnumProtocol.a(packet); - EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); -@@ -208,6 +209,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER - private void p() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.packetQueue; -@@ -344,9 +346,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - static class QueuedPacket { - -- private final Packet a; -+ private final Packet a; private final Packet getPacket() { return this.a; } // Paper - OBFHELPER - @Nullable -- private final GenericFutureListener> b; -+ private final GenericFutureListener> b; private final GenericFutureListener> getGenericFutureListener() { return this.b; } // Paper - OBFHELPER - - public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - this.a = packet; -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index f94e96406d6dc9c75091ae7563dd5b325f4f0c22..5413bf93f7f0f4491fca1f07c47a925fdace7751 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -49,6 +49,7 @@ public class PacketDataSerializer extends ByteBuf { - this.a = bytebuf; - } - -+ public static int countBytes(int i) { return PacketDataSerializer.a(i); } // Paper - OBFHELPER - public static int a(int i) { - for (int j = 1; j < 5; ++j) { - if ((i & -1 << j * 7) == 0) { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 06098698e4adc31aa96f9592975e441f965b5558..dc8cc8d6c00176c8562086282f726dc1b24b2c65 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -44,6 +44,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - packet.b(packetdataserializer); - } catch (Throwable throwable) { - PacketEncoder.LOGGER.error(throwable); -+ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? - if (packet.a()) { - throw new SkipEncodeException(throwable); - } else { -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -index d748e07f8870023e74796910a457d58ee0361ca6..2b8358995e4933d3fc3498407a7df7475d7b7e26 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -@@ -7,7 +7,7 @@ import net.minecraft.world.item.ItemStack; - - public class PacketPlayInBEdit implements Packet { - -- private ItemStack a; -+ private ItemStack a; public ItemStack getBook() { return a; } // Paper - OBFHELPER - private boolean b; - private int c; - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 820ba7c59e7bc7b6f3311f1a4ec3d724e265a2af..b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -28,7 +28,7 @@ public class PacketPlayOutMapChunk implements Packet { - private NBTTagCompound d; - @Nullable - private int[] e; -- private byte[] f; -+ private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER - private List g; - private boolean h; - -@@ -140,6 +140,7 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER - public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..18b56b59fd6efd618e6ff6f9cf3a02f57588d244 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +1,510 @@ -+package net.minecraft.server; -+ -+import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.RayTrace; -+import net.minecraft.world.level.World; -+import org.apache.commons.lang.exception.ExceptionUtils; -+import org.bukkit.Location; -+import org.bukkit.block.BlockFace; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.spigotmc.AsyncCatcher; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.List; -+import java.util.Queue; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ExecutionException; -+import java.util.concurrent.LinkedBlockingQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.function.BiConsumer; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class MCUtil { -+ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( -+ 0, 2, 60L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() -+ ); -+ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( -+ 1, 1, 0L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() -+ ); -+ -+ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); -+ -+ -+ public static Runnable once(Runnable run) { -+ AtomicBoolean ran = new AtomicBoolean(false); -+ return () -> { -+ if (ran.compareAndSet(false, true)) { -+ run.run(); -+ } -+ }; -+ } -+ -+ public static Runnable once(List list, Consumer cb) { -+ return once(() -> { -+ list.forEach(cb); -+ }); -+ } -+ -+ private static Runnable makeCleanerCallback(Runnable run) { -+ return once(() -> cleanerExecutor.execute(run)); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param run -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, Runnable run) { -+ // Wrap callback in its own method above or the lambda will leak object -+ Runnable cleaner = makeCleanerCallback(run); -+ co.aikar.cleaner.Cleaner.register(obj, cleaner); -+ return cleaner; -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param list -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { -+ return registerCleaner(obj, () -> { -+ list.forEach(cleaner); -+ list.clear(); -+ }); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param resource -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { -+ return registerCleaner(obj, () -> cleaner.accept(resource)); -+ } -+ -+ public static List getSpiralOutChunks(BlockPosition blockposition, int radius) { -+ List list = com.google.common.collect.Lists.newArrayList(); -+ -+ list.add(new ChunkCoordIntPair(blockposition.getX() >> 4, blockposition.getZ() >> 4)); -+ for (int r = 1; r <= radius; r++) { -+ int x = -r; -+ int z = r; -+ -+ // Iterates the edge of half of the box; then negates for other half. -+ while (x <= r && z > -r) { -+ list.add(new ChunkCoordIntPair((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); -+ list.add(new ChunkCoordIntPair((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); -+ -+ if (x < r) { -+ x++; -+ } else { -+ z--; -+ } -+ } -+ } -+ return list; -+ } -+ -+ public static int fastFloor(double x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static int fastFloor(float x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static float normalizeYaw(float f) { -+ float f1 = f % 360.0F; -+ -+ if (f1 >= 180.0F) { -+ f1 -= 360.0F; -+ } -+ -+ if (f1 < -180.0F) { -+ f1 += 360.0F; -+ } -+ -+ return f1; -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location -+ * -+ * @return Stacktrace -+ */ -+ public static String stack() { -+ return ExceptionUtils.getFullStackTrace(new Throwable()); -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location with message -+ * -+ * @param str -+ * @return Stacktrace -+ */ -+ public static String stack(String str) { -+ return ExceptionUtils.getFullStackTrace(new Throwable(str)); -+ } -+ -+ public static long getCoordinateKey(final BlockPosition blockPos) { -+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final Entity entity) { -+ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final ChunkCoordIntPair pair) { -+ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getChunkCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate) >> 4; -+ } -+ -+ public static int getBlockCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate); -+ } -+ -+ public static long getBlockKey(final int x, final int y, final int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ public static long getBlockKey(final BlockPosition pos) { -+ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); -+ } -+ -+ public static long getBlockKey(final Entity entity) { -+ return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); -+ } -+ -+ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable -+ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { -+ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); -+ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. -+ for (java.util.SortedSet set : sets) { -+ if (set != null) { -+ all.addAll(set); -+ } -+ } -+ all.forEach(consumer); -+ } -+ -+ private MCUtil() {} -+ -+ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { -+ if (!isMainThread()) { -+ MinecraftServer.getServer().execute(run); -+ } else { -+ run.run(); -+ } -+ }; -+ -+ public static CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); -+ } -+ -+ public static void thenOnMain(CompletableFuture future, Consumer consumer) { -+ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); -+ } -+ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { -+ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); -+ } -+ -+ public static boolean isMainThread() { -+ return MinecraftServer.getServer().isMainThread(); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { -+ return scheduleTask(ticks, runnable, null); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { -+ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); -+ } -+ -+ public static void processQueue() { -+ Runnable runnable; -+ Queue processQueue = getProcessQueue(); -+ while ((runnable = processQueue.poll()) != null) { -+ try { -+ runnable.run(); -+ } catch (Exception e) { -+ MinecraftServer.LOGGER.error("Error executing task", e); -+ } -+ } -+ } -+ public static T processQueueWhileWaiting(CompletableFuture future) { -+ try { -+ if (isMainThread()) { -+ while (!future.isDone()) { -+ try { -+ return future.get(1, TimeUnit.MILLISECONDS); -+ } catch (TimeoutException ignored) { -+ processQueue(); -+ } -+ } -+ } -+ return future.get(); -+ } catch (Exception e) { -+ throw new RuntimeException(e); -+ } -+ } -+ -+ public static void ensureMain(Runnable run) { -+ ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @return -+ */ -+ public static void ensureMain(String reason, Runnable run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); -+ } -+ getProcessQueue().add(run); -+ return; -+ } -+ run.run(); -+ } -+ -+ private static Queue getProcessQueue() { -+ return MinecraftServer.getServer().processQueue; -+ } -+ -+ public static T ensureMain(Supplier run) { -+ return ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @param -+ * @return -+ */ -+ public static T ensureMain(String reason, Supplier run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); -+ } -+ Waitable wait = new Waitable() { -+ @Override -+ protected T evaluate() { -+ return run.get(); -+ } -+ }; -+ getProcessQueue().add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException | ExecutionException e) { -+ e.printStackTrace(); -+ } -+ return null; -+ } -+ return run.get(); -+ } -+ -+ /** -+ * Calculates distance between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(Entity e1, Entity e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ -+ /** -+ * Calculates distance between 2 block positions -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(BlockPosition e1, BlockPosition e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ /** -+ * Gets the distance between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); -+ } -+ -+ /** -+ * Get's the distance squared between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distanceSq(Entity e1, Entity e2) { -+ return distanceSq(e1.locX(),e1.locY(),e1.locZ(), e2.locX(),e2.locY(),e2.locZ()); -+ } -+ -+ /** -+ * Gets the distance sqaured between 2 block positions -+ * @param pos1 -+ * @param pos2 -+ * @return -+ */ -+ public static double distanceSq(BlockPosition pos1, BlockPosition pos2) { -+ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); -+ } -+ -+ /** -+ * Gets the distance squared between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param x -+ * @param y -+ * @param z -+ * @return -+ */ -+ public static Location toLocation(World world, double x, double y, double z) { -+ return new Location(world.getWorld(), x, y, z); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param pos -+ * @return -+ */ -+ public static Location toLocation(World world, BlockPosition pos) { -+ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ /** -+ * Converts an NMS entity's current location to a Bukkit Location -+ * @param entity -+ * @return -+ */ -+ public static Location toLocation(Entity entity) { -+ return new Location(entity.getWorld().getWorld(), entity.locX(), entity.locY(), entity.locZ()); -+ } -+ -+ public static org.bukkit.block.Block toBukkitBlock(World world, BlockPosition pos) { -+ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ public static BlockPosition toBlockPosition(Location loc) { -+ return new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); -+ } -+ -+ public static boolean isEdgeOfChunk(BlockPosition pos) { -+ final int modX = pos.getX() & 15; -+ final int modZ = pos.getZ() & 15; -+ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); -+ } -+ -+ /** -+ * Posts a task to be executed asynchronously -+ * @param run -+ */ -+ public static void scheduleAsyncTask(Runnable run) { -+ asyncExecutor.execute(run); -+ } -+ -+ @Nonnull -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.World world) { -+ return ((CraftWorld) world).getHandle(); -+ } -+ -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { -+ return getNMSWorld(entity.getWorld()); -+ } -+ -+ public static RayTrace.FluidCollisionOption getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { -+ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { -+ return RayTrace.FluidCollisionOption.NONE; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { -+ return RayTrace.FluidCollisionOption.SOURCE_ONLY; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { -+ return RayTrace.FluidCollisionOption.ANY; -+ } -+ return null; -+ } -+ -+ public static BlockFace toBukkitBlockFace(EnumDirection enumDirection) { -+ switch (enumDirection) { -+ case DOWN: -+ return BlockFace.DOWN; -+ case UP: -+ return BlockFace.UP; -+ case NORTH: -+ return BlockFace.NORTH; -+ case SOUTH: -+ return BlockFace.SOUTH; -+ case WEST: -+ return BlockFace.WEST; -+ case EAST: -+ return BlockFace.EAST; -+ default: -+ return null; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 81cff54c93bc04d19e3cc0f5307799c62d139ab2..cd3e7b8a23e40c717829bd262bfa675e4e3532f9 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -884,6 +884,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant public - private final LightEngineThreaded lightEngine; - private final ChunkProviderServer.a serverThreadQueue; - public final PlayerChunkMap playerChunkMap; -@@ -62,6 +63,158 @@ public class ChunkProviderServer extends IChunkProvider { - private final IChunkAccess[] cacheChunk = new IChunkAccess[4]; - @Nullable - private SpawnerCreature.d p; -+ // Paper start -+ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); -+ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); -+ -+ private final Chunk[] lastLoadedChunks = new Chunk[4 * 4]; -+ -+ private static int getChunkCacheKey(int x, int z) { -+ return x & 3 | ((z & 3) << 2); -+ } -+ -+ public void addLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.put(chunk.coordinateKey, chunk); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ this.lastLoadedChunks[cacheKey] = chunk; -+ } -+ -+ public void removeLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.remove(chunk.coordinateKey); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { -+ this.lastLoadedChunks[cacheKey] = null; -+ } -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThread(int x, int z) { -+ int cacheKey = getChunkCacheKey(x, z); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { -+ return this.lastLoadedChunks[cacheKey]; -+ } -+ -+ long chunkKey = ChunkCoordIntPair.pair(x, z); -+ -+ cachedChunk = this.loadedChunkMap.get(chunkKey); -+ // Skipping a null check to avoid extra instructions to improve inline capability -+ this.lastLoadedChunks[cacheKey] = cachedChunk; -+ return cachedChunk; -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -+ return this.loadedChunkMap.get(ChunkCoordIntPair.pair(x, z)); -+ } -+ -+ public final Chunk getChunkAtMainThread(int x, int z) { -+ Chunk ret = this.getChunkAtIfLoadedMainThread(x, z); -+ if (ret != null) { -+ return ret; -+ } -+ return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); -+ } -+ -+ private long chunkFutureAwaitCounter; -+ -+ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getEntityTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 31, PlayerChunk::getEntityTickingFuture, onLoad); -+ } -+ -+ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 32, PlayerChunk::getTickingFuture, onLoad); -+ } -+ -+ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getFullChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 33, PlayerChunk::getFullChunkFuture, onLoad); -+ } -+ -+ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ throw new IllegalStateException(); -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ Long identifier = this.chunkFutureAwaitCounter++; -+ this.chunkMapDistance.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ this.tickDistanceManager(); -+ -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); -+ -+ if (chunk == null) { -+ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); -+ } -+ -+ CompletableFuture> future = futureGet.apply(chunk); -+ -+ future.whenCompleteAsync((either, throwable) -> { -+ try { -+ if (throwable != null) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", throwable); -+ } else if (either.right().isPresent()) { -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "': " + either.right().get().toString()); -+ } -+ -+ try { -+ if (onLoad != null) { -+ playerChunkMap.callbackExecutor.execute(() -> { -+ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. -+ }); -+ } -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", thr); -+ return; -+ } -+ } finally { -+ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. -+ ChunkProviderServer.this.chunkMapDistance.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); -+ ChunkProviderServer.this.chunkMapDistance.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ } -+ }, this.serverThreadQueue); -+ } -+ // Paper end - - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; -@@ -123,6 +276,49 @@ public class ChunkProviderServer extends IChunkProvider { - this.cacheChunk[0] = ichunkaccess; - } - -+ // Paper start - "real" get chunk if loaded -+ // Note: Partially copied from the getChunkAt method below -+ @Nullable -+ public Chunk getChunkAtIfCachedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getFullChunkIfCached(); -+ } -+ -+ @Nullable -+ public Chunk getChunkAtIfLoadedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ if (Thread.currentThread() == this.serverThread) { -+ return this.getChunkAtIfLoadedMainThread(x, z); -+ } -+ -+ Chunk ret = null; -+ long readlock; -+ do { -+ readlock = this.loadedChunkMapSeqLock.acquireRead(); -+ try { -+ ret = this.loadedChunkMap.get(k); -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // re-try, this means a CME occurred... -+ continue; -+ } -+ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ // Paper end -+ - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -@@ -405,10 +601,9 @@ public class ChunkProviderServer extends IChunkProvider { - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); -- List list = Lists.newArrayList(this.playerChunkMap.f()); -- -- Collections.shuffle(list); -- list.forEach((playerchunk) -> { -+ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper -+ //Collections.shuffle(list); // Paper -+ this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 2d297902e3b0f99a3d9f64606f9edcdabecbe83a..3fa2e077912949f6ca7b14da93c2206215ebcc7e 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -224,6 +224,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public Integer clientViewDistance; - // CraftBukkit end - -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -@@ -236,6 +238,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.c(worldserver); - this.co = minecraftserver.a(this); - -+ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -+ - // CraftBukkit start - this.displayName = this.getName(); - this.canPickUpLoot = true; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 254953c1d8ad80173bcc9ed703bacaf32ca89c9a..7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -46,9 +46,9 @@ public class PlayerChunk { - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); - private final AtomicReferenceArray>> statusFutures; -- private volatile CompletableFuture> fullChunkFuture; -- private volatile CompletableFuture> tickingFuture; -- private volatile CompletableFuture> entityTickingFuture; -+ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> entityTickingFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -@@ -64,6 +64,8 @@ public class PlayerChunk { - private boolean hasBeenLoaded; - private boolean x; - -+ private final PlayerChunkMap chunkMap; // Paper -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -79,10 +81,49 @@ public class PlayerChunk { - this.ticketLevel = this.oldTicketLevel; - this.n = this.oldTicketLevel; - this.a(i); -+ this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ } -+ -+ // Paper start -+ @Nullable -+ public final Chunk getEntityTickingChunk() { -+ CompletableFuture> completablefuture = this.entityTickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getTickingChunk() { -+ CompletableFuture> completablefuture = this.tickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getFullReadyChunk() { -+ CompletableFuture> completablefuture = this.fullChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ public final boolean isEntityTickingReady() { -+ return this.isEntityTickingReady; -+ } -+ -+ public final boolean isTickingReady() { -+ return this.isTickingReady; -+ } -+ -+ public final boolean isFullChunkReady() { -+ return this.isFullChunkReady; - } -+ // Paper end - - // CraftBukkit start -- public Chunk getFullChunk() { -+ public final Chunk getFullChunk() { // Paper - final for inline - if (!getChunkState(this.oldTicketLevel).isAtLeast(PlayerChunk.State.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks - return this.getFullChunkUnchecked(); - } -@@ -93,6 +134,14 @@ public class PlayerChunk { - return (either == null) ? null : (Chunk) either.left().orElse(null); - } - // CraftBukkit end -+ // Paper start - "real" get full chunk immediately -+ public final Chunk getFullChunkIfCached() { -+ // Note: Copied from above without ticket level check -+ CompletableFuture> statusFuture = this.getStatusFutureUnchecked(ChunkStatus.FULL); -+ Either either = (Either) statusFuture.getNow(null); -+ return either == null ? null : (Chunk) either.left().orElse(null); -+ } -+ // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { - CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c()); -@@ -104,20 +153,23 @@ public class PlayerChunk { - return getChunkStatus(this.ticketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE; - } - -- public CompletableFuture> a() { -+ public final CompletableFuture> getTickingFuture() { return this.a(); } // Paper - OBFHELPER -+ public final CompletableFuture> a() { // Paper - final for inline - return this.tickingFuture; - } - -- public CompletableFuture> b() { -+ public final CompletableFuture> getEntityTickingFuture() { return this.b(); } // Paper - OBFHELPER -+ public final CompletableFuture> b() { // Paper - final for inline - return this.entityTickingFuture; - } - -- public CompletableFuture> c() { -+ public final CompletableFuture> getFullChunkFuture() { return this.c(); } // Paper - OBFHELPER -+ public final CompletableFuture> c() { // Paper - final for inline - return this.fullChunkFuture; - } - - @Nullable -- public Chunk getChunk() { -+ public final Chunk getChunk() { // Paper - final for inline - CompletableFuture> completablefuture = this.a(); - Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error - -@@ -142,7 +194,7 @@ public class PlayerChunk { - return null; - } - -- public CompletableFuture getChunkSave() { -+ public final CompletableFuture getChunkSave() { // Paper - final for inline - return this.chunkSave; - } - -@@ -283,11 +335,11 @@ public class PlayerChunk { - }); - } - -- public ChunkCoordIntPair i() { -+ public final ChunkCoordIntPair i() { // Paper - final for inline - return this.location; - } - -- public int getTicketLevel() { -+ public final int getTicketLevel() { // Paper - final for inline - return this.ticketLevel; - } - -@@ -358,13 +410,27 @@ public class PlayerChunk { - - this.hasBeenLoaded |= flag3; - if (!flag2 && flag3) { -- this.fullChunkFuture = playerchunkmap.b(this); -+ // Paper start - cache ticking ready status -+ int expectCreateCount = ++this.fullChunkCreateCount; -+ this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk fullChunk = either.left().get(); -+ PlayerChunk.this.isFullChunkReady = true; -+ fullChunk.playerChunk = PlayerChunk.this; -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.fullChunkFuture); - } - - if (flag2 && !flag3) { - completablefuture = this.fullChunkFuture; - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -+ ++this.fullChunkCreateCount; // Paper - cache ticking ready status -+ this.isFullChunkReady = false; // Paper - cache ticking ready status - this.a(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error - playerchunkmap.getClass(); - return either1.ifLeft(playerchunkmap::a); -@@ -375,12 +441,24 @@ public class PlayerChunk { - boolean flag5 = playerchunk_state1.isAtLeast(PlayerChunk.State.TICKING); - - if (!flag4 && flag5) { -- this.tickingFuture = playerchunkmap.a(this); -+ // Paper start - cache ticking ready status -+ this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk tickingChunk = either.left().get(); -+ PlayerChunk.this.isTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.tickingFuture); - } - - if (flag4 && !flag5) { -- this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage - this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -@@ -392,12 +470,24 @@ public class PlayerChunk { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException())); - } - -- this.entityTickingFuture = playerchunkmap.b(this.location); -+ // Paper start - cache ticking ready status -+ this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk entityTickingChunk = either.left().get(); -+ PlayerChunk.this.isEntityTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.entityTickingFuture); - } - - if (flag6 && !flag7) { -- this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 565aa1690d5427f5059ab117c4c15b0754e8830b..19856555793f742abb1178ede72dea5623f0e383 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -54,6 +54,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -146,6 +147,26 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ // Paper start - distance maps -+ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ -+ void addPlayerToDistanceMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ -+ void removePlayerFromDistanceMaps(EntityPlayer player) { -+ -+ } -+ -+ void updateMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ // Paper end -+ - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - this.visibleChunks = this.updatingChunks.clone(); -@@ -235,6 +256,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - } - -+ // Paper start -+ public final int getEffectiveViewDistance() { -+ // TODO this needs to be checked on update -+ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. -+ return this.viewDistance - 1; -+ } -+ // Paper end -+ - private CompletableFuture, PlayerChunk.Failure>> a(ChunkCoordIntPair chunkcoordintpair, int i, IntFunction intfunction) { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; -@@ -953,6 +982,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag1) { - this.chunkDistanceManager.a(SectionPosition.a((Entity) entityplayer), entityplayer); - } -+ this.addPlayerToDistanceMaps(entityplayer); // Paper - distance maps - } else { - SectionPosition sectionposition = entityplayer.O(); - -@@ -960,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag2) { - this.chunkDistanceManager.b(sectionposition, entityplayer); - } -+ this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - - for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -@@ -1070,6 +1101,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ this.updateMaps(entityplayer); // Paper - distance maps -+ - } - - @Override -diff --git a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -index 91d9e6b554964e1f4dd67deea220a738f2715aee..04006caeeb42b523d986efc313828557854718d7 100644 ---- a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -+++ b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -@@ -141,6 +141,26 @@ public class RegionLimitedWorldAccess implements GeneratorAccessSeed { - return i >= this.n.x && i <= this.o.x && j >= this.n.z && j <= this.o.z; - } - -+ // Paper start - if loaded util -+ @Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return this.getChunkAt(x, z, ChunkStatus.FULL, false); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4).getType(blockposition); -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 9cae7fed34df3ff81d75105b2fcbc4510f2a0e71..285a03b57431bd6a4d26bb84e916d2c6e1eb0213 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -25,6 +25,7 @@ public class TicketType { - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit -+ public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 7f9a1d64d123ce54608497a0e0a37d161d8c9d3c..780e541b8d594a8a6dc3a8626a82218f2502a5c7 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.longs.LongSets; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - import java.io.BufferedWriter; -@@ -169,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); - private final List players = Lists.newArrayList(); -- private final ChunkProviderServer chunkProvider; -+ public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type -@@ -1688,7 +1689,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ObjectIterator objectiterator = spawnercreature_d.b().object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - - bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((EnumCreatureType) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).b(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 1a8f4ed15f7df5c734efc83c91444a42041af978..bc9321e77c6b2f9ac17821413fa1357da2f26b05 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -220,9 +220,9 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; -- private boolean awaitingKeepAlive; -- private long h; -+ private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER -+ private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 54974a941a334dc0c8e62ffb8ca094772888b8fa..0c0576c8730069fb5364d8383dec8ab7e698658d 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -84,6 +84,7 @@ public class DataBits { - return (int) (k >> l & this.d); - } - -+ public final long[] getDataBits() { return this.a(); } // Paper - OBFHELPER - public long[] a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 2b2c03ab62816f3d21ef953c4a45f55e3997cca6..e5641f2b41d89a57285fc072a48b951aa03a14a7 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -68,6 +68,15 @@ public abstract class IAsyncTaskHandler implements Mailbox entitytypes, World world) { - super(entitytypes, world); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index b91bb7f562d5c43ec1d0d88ba417e43b07dbf0f3..dbfcdc3cc7c1dccf785f5e13634e84c5af088985 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -225,6 +225,7 @@ public abstract class EntityInsentient extends EntityLiving { - return this.goalTarget; - } - -+ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper - public void setGoalTarget(@Nullable EntityLiving entityliving) { - // CraftBukkit start - fire event - setGoalTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 97591280da3bfb30703a95fbe4e34b56b70544f4..c76ab1e6a54399eddae1ef2a595778385cd50026 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -231,6 +231,7 @@ public abstract class EntityLiving extends Entity { - public boolean collides = true; - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; -+ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper - - @Override - public float getBukkitYaw() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index a32bc63ff1960bdb874d546ee42633063834da24..ac57ab9992e141c91cf48f033148ad78433b364c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity; - import com.google.common.collect.ImmutableSet; - import java.util.Optional; - import java.util.Set; // Paper -+import java.util.Map; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -441,8 +442,8 @@ public class EntityTypes { - return this.br.height; - } - -- @Nullable -- public T a(World world) { -+ public T create(World world) { return this.a(world); } // Paper - OBFHELPER -+ @Nullable public T a(World world) { // Paper - OBFHELPER - return this.bf.create(this, world); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -index acebee991eca1e19fc1094718dc40822b66756e1..c484e27650364b6537fe6b2e8e14de98382b86a3 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -@@ -27,6 +27,7 @@ import net.minecraft.world.level.WorldAccess; - - public abstract class EntityMonster extends EntityCreature implements IMonster { - -+ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper - protected EntityMonster(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.f = 5; -diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -index 97db41acf626eec3e587964d0e73c370e5695bf0..2df3ae0b72ccb5f816d55fed15396ba5a1affb7f 100644 ---- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -@@ -38,7 +38,7 @@ public class PlayerInventory implements IInventory, INamableTileEntity { - public final NonNullList items; - public final NonNullList armor; - public final NonNullList extraSlots; -- private final List> f; -+ private final List> f; public final List> getComponents() { return f; } // Paper - OBFHELPER - public int itemInHandIndex; - public final EntityHuman player; - private ItemStack carried; -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index dee2714cd9fc930a1a13e97d752ab2df39cd31ed..4010152dccc93019f2e7f284d80b92bae0d91c34 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -103,7 +103,7 @@ public final class ItemStack { - })).apply(instance, ItemStack::new); - }); - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ItemStack b = new ItemStack((Item) null); -+ public static final ItemStack b = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = b; // Paper - OBFHELPER - public static final DecimalFormat c = (DecimalFormat) SystemUtils.a((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); -@@ -660,6 +660,24 @@ public final class ItemStack { - return this.tag != null ? this.tag.getList("Enchantments", 10) : new NBTTagList(); - } - -+ // Paper start - (this is just a good no conflict location) -+ public org.bukkit.inventory.ItemStack asBukkitMirror() { -+ return CraftItemStack.asCraftMirror(this); -+ } -+ public org.bukkit.inventory.ItemStack asBukkitCopy() { -+ return CraftItemStack.asCraftMirror(this.cloneItemStack()); -+ } -+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { -+ return CraftItemStack.asNMSCopy(itemstack); -+ } -+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; -+ public org.bukkit.inventory.ItemStack getBukkitStack() { -+ if (bukkitStack == null || bukkitStack.getHandle() != this) { -+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); -+ } -+ return bukkitStack; -+ } -+ // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; - if (this.getItem().usesDurability()) { -@@ -758,6 +776,7 @@ public final class ItemStack { - return this.tag != null && this.tag.hasKeyOfType("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; - } - -+ public void getOrCreateTagAndSet(String s, NBTBase nbtbase) { a(s, nbtbase);} // Paper - OBFHELPER - public void a(String s, NBTBase nbtbase) { - this.getOrCreateTag().set(s, nbtbase); - } -@@ -843,6 +862,7 @@ public final class ItemStack { - // CraftBukkit start - @Deprecated - public void setItem(Item item) { -+ this.bukkitStack = null; // Paper - this.item = item; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -index daad63e731008eddccd3f51418a2a9b2d587f77b..795bc60a73e1e628590803fd515ffb78302d4f97 100644 ---- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -@@ -121,6 +121,7 @@ public class PotionUtil { - return nbttagcompound == null ? Potions.EMPTY : PotionRegistry.a(nbttagcompound.getString("Potion")); - } - -+ public static ItemStack addPotionToItemStack(ItemStack itemstack, PotionRegistry potionregistry) { return a(itemstack, potionregistry); } // Paper - OBFHELPER - public static ItemStack a(ItemStack itemstack, PotionRegistry potionregistry) { - MinecraftKey minecraftkey = IRegistry.POTION.getKey(potionregistry); - -diff --git a/src/main/java/net/minecraft/world/level/BlockAccessAir.java b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -index 5f8022745f709b6d542182d2ac94147aefdd3f0f..543b13c1e43135c044f834c2a6231e174536b623 100644 ---- a/src/main/java/net/minecraft/world/level/BlockAccessAir.java -+++ b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -@@ -20,6 +20,18 @@ public enum BlockAccessAir implements IBlockAccess { - return null; - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCache.java b/src/main/java/net/minecraft/world/level/ChunkCache.java -index 8541e87a34612e8bc86cf5c291164e091641d1af..7a760ef0264c9041c38bdfb8fd31333052c26139 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCache.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCache.java -@@ -4,6 +4,7 @@ import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -23,7 +24,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - protected final int b; - protected final IChunkAccess[][] c; - protected boolean d; -- protected final World e; -+ protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER - - public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { - this.e = world; -@@ -42,7 +43,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - - for (k = this.a; k <= i; ++k) { - for (l = this.b; l <= j; ++l) { -- this.c[k - this.a][l - this.b] = ichunkprovider.a(k, l); -+ this.c[k - this.a][l - this.b] = ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper - } - } - -@@ -67,7 +68,7 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - int k = i - this.a; - int l = j - this.b; - -- if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { // Paper - if this changes, update getChunkIfLoaded below - IChunkAccess ichunkaccess = this.c[k][l]; - - return (IChunkAccess) (ichunkaccess != null ? ichunkaccess : new ChunkEmpty(this.e, new ChunkCoordIntPair(i, j))); -@@ -86,6 +87,29 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - return this.a(i, j); - } - -+ // Paper start - if loaded util -+ private IChunkAccess getChunkIfLoaded(int x, int z) { -+ int k = x - this.a; -+ int l = z - this.b; -+ -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ return this.c[k][l]; -+ } -+ return null; -+ } -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ // Paper end -+ - @Nullable - @Override - public TileEntity getTileEntity(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 14e55bf842e928d1e8e2137f9efdef0f7c336362..9a88791be443a5b18934e7d752aee6dcdb8aa38f 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -12,27 +12,32 @@ public class ChunkCoordIntPair { - public static final long a = pair(1875016, 1875016); - public final int x; - public final int z; -+ public final long longKey; // Paper - - public ChunkCoordIntPair(int i, int j) { - this.x = i; - this.z = j; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(BlockPosition blockposition) { - this.x = blockposition.getX() >> 4; - this.z = blockposition.getZ() >> 4; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(long i) { - this.x = (int) i; - this.z = (int) (i >> 32); -+ this.longKey = pair(this.x, this.z); // Paper - } - - public long pair() { -- return pair(this.x, this.z); -+ return longKey; // Paper - } - -- public static long pair(int i, int j) { -+ public static long pair(final BlockPosition pos) { return pair(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER -+ public static long pair(int i, int j) { - return (long) i & 4294967295L | ((long) j & 4294967295L) << 32; - } - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index 25e50b57f42dde156443480d73c6c9985df6f0c6..e799765ecfada1eec78beb71651e52ad355a30aa 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -8,9 +8,11 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; -@@ -22,6 +24,19 @@ public interface IBlockAccess { - TileEntity getTileEntity(BlockPosition blockposition); - - IBlockData getType(BlockPosition blockposition); -+ // Paper start - if loaded util -+ IBlockData getTypeIfLoaded(BlockPosition blockposition); -+ default Material getMaterialIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getMaterial(); -+ } -+ -+ default Block getBlockIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getBlock(); -+ } -+ Fluid getFluidIfLoaded(BlockPosition blockposition); -+ // Paper end - - Fluid getFluid(BlockPosition blockposition); - -diff --git a/src/main/java/net/minecraft/world/level/IWorldReader.java b/src/main/java/net/minecraft/world/level/IWorldReader.java -index d3d33e77ce09d485552076c5ab6faf08a16d90db..5f12b290d59e0b5e843d644bf7f608a946ef02c0 100644 ---- a/src/main/java/net/minecraft/world/level/IWorldReader.java -+++ b/src/main/java/net/minecraft/world/level/IWorldReader.java -@@ -18,6 +18,7 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public interface IWorldReader extends IBlockLightAccess, ICollisionAccess, BiomeManager.Provider { - -+ @Nullable IChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) - @Nullable - IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index f794113e7cc5809d1da0c85648fb7311fb633f40..0cbebc2095489c240fecd3fd32f5373be2a3d684 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -74,6 +74,7 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -+import org.bukkit.craftbukkit.block.CraftBlockState; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -255,17 +256,50 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return i < 0 || i >= 256; - } - -- public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { -+ public final Chunk getChunkAtWorldCoords(BlockPosition blockposition) { // Paper - help inline - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); - } - - @Override -- public Chunk getChunkAt(int i, int j) { -- return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL); -+ public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline -+ return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump -+ } -+ -+ // Paper start - if loaded -+ @Nullable -+ @Override -+ public final IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return ((WorldServer)this).chunkProvider.getChunkAtIfLoadedImmediately(x, z); - } - - @Override -- public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ public final IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ // CraftBukkit start - tree generation -+ if (captureTreeGeneration) { -+ CraftBlockState previous = capturedBlockStates.get(blockposition); -+ if (previous != null) { -+ return previous.getHandle(); -+ } -+ } -+ // CraftBukkit end -+ if (!isValidLocation(blockposition)) { -+ return Blocks.AIR.getBlockData(); -+ } -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ -+ @Override -+ public final IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { // Paper - final for inline - IChunkAccess ichunkaccess = this.getChunkProvider().getChunkAt(i, j, chunkstatus, flag); - - if (ichunkaccess == null && flag) { -@@ -276,7 +310,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { -+ public final boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { // Paper - final for inline - return this.a(blockposition, iblockdata, i, 512); - } - -@@ -422,8 +456,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public void a(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - -- @Override -- public boolean a(BlockPosition blockposition, boolean flag) { -+ public boolean setAir(BlockPosition blockposition) { return this.a(blockposition, false); } // Paper - OBFHELPER -+ public boolean setAir(BlockPosition blockposition, boolean moved) { return this.a(blockposition, moved); } // Paper - OBFHELPER -+ @Override public boolean a(BlockPosition blockposition, boolean flag) { // Paper - OBFHELPER - Fluid fluid = this.getFluid(blockposition); - - return this.setTypeAndData(blockposition, fluid.getBlockData(), 3 | (flag ? 64 : 0)); -@@ -569,7 +604,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (isOutsideWorld(blockposition)) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- Chunk chunk = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ Chunk chunk = (Chunk) this.getChunkProvider().getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine - - return chunk.getType(blockposition); - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index ef652d8f3eb7371c9ddfc3afe67fd1bd669a77c0..2902117fd2803741b053a04fda7f4414fb8593cb 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -688,6 +688,7 @@ public abstract class BlockBase { - return this.a != null ? this.a.d : Block.a(this.getCollisionShape(iblockaccess, blockposition)); - } - -+ public final IBlockData getBlockData() { return p(); } // Paper - OBFHELPER - protected abstract IBlockData p(); - - public boolean isRequiresSpecialTool() { -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 79f645ff1b6274bbdf5dc3f96a762b3b63397c82..2bb03f1cb9671a7754a68059219f783d4508eeb9 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -47,6 +47,7 @@ public class WorldBorder { - return this.b(entity.locX(), entity.locZ()); - } - -+ public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER - public VoxelShape c() { - return this.j.m(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 4561cf94fe1dce51abad0ac8635749ed87c8b307..b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -60,7 +60,7 @@ public class Chunk implements IChunkAccess { - - private static final Logger LOGGER = LogManager.getLogger(); - @Nullable -- public static final ChunkSection a = null; -+ public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = a; // Paper - OBFHELPER - private final ChunkSection[] sections; - private BiomeStorage d; - private final Map e; -@@ -83,7 +83,7 @@ public class Chunk implements IChunkAccess { - private Supplier u; - @Nullable - private Consumer v; -- private final ChunkCoordIntPair loc; -+ private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key - private volatile boolean x; - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { -@@ -100,7 +100,8 @@ public class Chunk implements IChunkAccess { - this.n = new ShortList[16]; - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = (WorldServer) world; // CraftBukkit - type -- this.loc = chunkcoordintpair; -+ this.locX = chunkcoordintpair.x; this.locZ = chunkcoordintpair.z; // Paper - reduce need for field look ups -+ this.loc = chunkcoordintpair; this.coordinateKey = ChunkCoordIntPair.pair(locX, locZ); // Paper - cache long key - this.i = chunkconverter; - HeightMap.Type[] aheightmap_type = HeightMap.Type.values(); - int j = aheightmap_type.length; -@@ -146,6 +147,110 @@ public class Chunk implements IChunkAccess { - public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - // CraftBukkit end - -+ // Paper start -+ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); -+ public PlayerChunk playerChunk; -+ -+ static final int NEIGHBOUR_CACHE_RADIUS = 3; -+ public static int getNeighbourCacheRadius() { -+ return NEIGHBOUR_CACHE_RADIUS; -+ } -+ -+ boolean loadedTicketLevel; -+ private long neighbourChunksLoadedBitset; -+ private final Chunk[] loadedNeighbourChunks = new Chunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; -+ -+ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { -+ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) -+ // optimised variant of the above by moving some of the ops to compile time -+ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); -+ } -+ -+ public final Chunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { -+ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; -+ } -+ -+ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { -+ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; -+ } -+ -+ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final Chunk chunk) { -+ if (chunk == null) { -+ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.loc); -+ } -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = chunk; -+ this.neighbourChunksLoadedBitset |= (1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = null; -+ this.neighbourChunksLoadedBitset &= ~(1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void resetNeighbours() { -+ final long before = this.neighbourChunksLoadedBitset; -+ this.neighbourChunksLoadedBitset = 0L; -+ java.util.Arrays.fill(this.loadedNeighbourChunks, null); -+ this.onNeighbourChange(before, 0L); -+ } -+ -+ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ -+ } -+ -+ public final boolean isAnyNeighborsLoaded() { -+ return neighbourChunksLoadedBitset != 0; -+ } -+ public final boolean areNeighboursLoaded(final int radius) { -+ return Chunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); -+ } -+ -+ public static boolean areNeighboursLoaded(final long bitset, final int radius) { -+ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) -+ switch (radius) { -+ case 0: { -+ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; -+ } -+ case 1: { -+ long mask = 0L; -+ for (int dx = -1; dx <= 1; ++dx) { -+ for (int dz = -1; dz <= 1; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 2: { -+ long mask = 0L; -+ for (int dx = -2; dx <= 2; ++dx) { -+ for (int dz = -2; dz <= 2; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 3: { -+ long mask = 0L; -+ for (int dx = -3; dx <= 3; ++dx) { -+ for (int dz = -3; dz <= 3; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ -+ default: -+ throw new IllegalArgumentException("Radius not recognized: " + radius); -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ProtoChunk protochunk) { - this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); - Iterator iterator = protochunk.y().iterator(); -@@ -251,6 +356,18 @@ public class Chunk implements IChunkAccess { - } - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public Fluid getFluid(BlockPosition blockposition) { - return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -391,6 +508,7 @@ public class Chunk implements IChunkAccess { - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -+ this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); - } - -@@ -414,6 +532,7 @@ public class Chunk implements IChunkAccess { - } - - this.entitySlices[i].remove(entity); -+ this.entities.remove(entity); // Paper - } - - @Override -@@ -435,6 +554,7 @@ public class Chunk implements IChunkAccess { - return this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - } - -+ @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { - // CraftBukkit start -@@ -546,7 +666,25 @@ public class Chunk implements IChunkAccess { - - // CraftBukkit start - public void loadCallback() { -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourLoaded(-dx, -dz, this); -+ // should be in cached already -+ this.setNeighbourLoaded(dx, dz, neighbour); -+ } -+ } -+ } -+ this.setNeighbourLoaded(0, 0, this); -+ this.loadedTicketLevel = true; -+ // Paper end - neighbour cache - org.bukkit.Server server = this.world.getServer(); -+ ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside -@@ -585,6 +723,22 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(unloadEvent); - // note: saving can be prevented, but not forced if no saving is actually required - this.mustNotSave = !unloadEvent.isSaveChunk(); -+ ((WorldServer)this.world).getChunkProvider().removeLoadedChunk(this); // Paper -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourUnloaded(-dx, -dz); -+ } -+ } -+ } -+ this.loadedTicketLevel = false; -+ this.resetNeighbours(); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index cf2dd6da5ce88aafdcc4db63af18eda9396a066a..a4e2eb1a753e8fcb48982d78fe80e505bce5c476 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -139,6 +139,7 @@ public class ChunkSection { - return this.blockIds; - } - -+ public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - packetdataserializer.writeShort(this.nonEmptyBlockCount); - this.blockIds.b(packetdataserializer); -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -index f1dd62541187d007a69087f0279508b6b18d5166..44fe0ee179eebfa6c4c0403a7f06735d7da5c773 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -@@ -7,10 +7,12 @@ import net.minecraft.network.PacketDataSerializer; - - public interface DataPalette { - -+ default int getOrCreateIdFor(T object) { return this.a(object); } // Paper - OBFHELPER - int a(T t0); - - boolean a(Predicate predicate); - -+ @Nullable default T getObject(int dataBits) { return this.a(dataBits); } // Paper - OBFHELPER - @Nullable - T a(int i); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index fe441146757a4ac0562d5b493fb6430e33b9ee28..e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -19,7 +19,7 @@ import net.minecraft.util.MathHelper; - - public class DataPaletteBlock implements DataPaletteExpandable { - -- private final DataPalette b; -+ private final DataPalette b; private final DataPalette getDataPaletteGlobal() { return this.b; } // Paper - OBFHELPER - private final DataPaletteExpandable c = (i, object) -> { - return 0; - }; -@@ -27,9 +27,9 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -- protected DataBits a; -- private DataPalette h; -- private int i; -+ protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER -+ private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER -+ private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - - public void a() { -@@ -64,6 +64,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return j << 8 | k << 4 | i; - } - -+ private void initialize(int bitsPerObject) { this.b(bitsPerObject); } // Paper - OBFHELPER - private void b(int i) { - if (i != this.i) { - this.i = i; -@@ -141,6 +142,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - this.a(); - packetdataserializer.writeByte(this.i); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 4192d30ad2117a12a4058b48581d6cf93b50088c..7572ca53a5cca8ca5085d18c24048b85dda4daa9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -99,6 +99,18 @@ public class ProtoChunk implements IChunkAccess { - - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - int i = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 859561a5dccba6548967b685b20e8fcfc296db2a..9ebf2806122a308f7655cdbee1f642cd80c9932c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -27,7 +27,7 @@ public class IOWorker implements AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - private final AtomicBoolean b = new AtomicBoolean(); - private final ThreadedMailbox c; -- private final RegionFileCache d; -+ private final RegionFileCache d;public RegionFileCache getRegionFileCache() { return d; } // Paper - OBFHELPER - private final Map e = Maps.newLinkedHashMap(); - - protected IOWorker(File file, boolean flag, String s) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 5e3bbc6d89794e23df7b60b13ae48c0f5136f20e..d1b761055c508a4b80436b50a832e00d0449d8cb 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -112,6 +112,7 @@ public class RegionFile implements AutoCloseable { - return this.e.resolve(s); - } - -+ @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER - @Nullable - public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { - int i = this.getOffset(chunkcoordintpair); -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 633a484cebc99f4a2f071b7f84b0b63d0ec3f985..3941dd33da4b5c09d0087143f1d8a2d76fc18792 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -194,10 +194,12 @@ public class AxisAlignedBB { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final boolean intersects(AxisAlignedBB axisalignedbb) { return this.c(axisalignedbb); } // Paper - OBFHELPER - public boolean c(AxisAlignedBB axisalignedbb) { - return this.a(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ); - } - -+ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return a(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER - public boolean a(double d0, double d1, double d2, double d3, double d4, double d5) { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } -@@ -210,6 +212,7 @@ public class AxisAlignedBB { - return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; - } - -+ public final double getAverageSideLength(){return a();} // Paper - OBFHELPER - public double a() { - double d0 = this.b(); - double d1 = this.c(); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 44d37272a337fee9606ebaa1b6f647c0fd392320..fdd9e37a8c90fc3311e515355af0a0593efbdacc 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -31,10 +31,12 @@ public final class VoxelShapes { - public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); - -+ public static final VoxelShape empty() {return a();} // Paper - OBFHELPER - public static VoxelShape a() { - return VoxelShapes.c; - } - -+ public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER - public static VoxelShape b() { - return VoxelShapes.b; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 52fa8a38545be43a31363d1d57e42471bbb0c499..275b943a59ef28c831a068987e111e84ebba3bb7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -85,6 +85,7 @@ public final class CraftItemStack extends ItemStack { - } - - net.minecraft.world.item.ItemStack handle; -+ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper - - /** - * Mirror -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9ad17c560c8d99a396543ab9f97c34de648f6544..4bf48f77f3f7cd62a91590543f5af441c8268029 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -43,6 +43,7 @@ import org.bukkit.scheduler.BukkitWorker; - */ - public class CraftScheduler implements BukkitScheduler { - -+ static Plugin MINECRAFT = new MinecraftInternalPlugin(); - /** - * Counter for IDs. Order doesn't matter, only uniqueness. - */ -@@ -177,6 +178,11 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); - } - -+ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -+ final CraftTask task = new CraftTask(run, nextId(), taskName); -+ return handle(task, delay); -+ } -+ - public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); - if (delay < 0L) { -@@ -400,13 +406,20 @@ public class CraftScheduler implements BukkitScheduler { - task.run(); - task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { -- task.getOwner().getLogger().log( -+ // Paper start -+ String msg = String.format( -+ "Task #%s for %s generated an exception", -+ task.getTaskId(), -+ task.getOwner().getDescription().getFullName()); -+ if (task.getOwner() == MINECRAFT) { -+ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); -+ } else { -+ task.getOwner().getLogger().log( - Level.WARNING, -- String.format( -- "Task #%s for %s generated an exception", -- task.getTaskId(), -- task.getOwner().getDescription().getFullName()), -+ msg, - throwable); -+ } -+ // Paper end - } finally { - currentTask = null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 3c7066192ea4c05c101404bb56cbc839771f4200..09aa6809c5400ce8548ac902908b750ce7c964ec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -39,6 +39,21 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - CraftTask(final Object task) { - this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -+ // Paper start -+ public String taskName = null; -+ boolean internal = false; -+ CraftTask(final Object task, int id, String taskName) { -+ this.rTask = (Runnable) task; -+ this.cTask = null; -+ this.plugin = CraftScheduler.MINECRAFT; -+ this.taskName = taskName; -+ this.internal = true; -+ this.id = id; -+ this.period = CraftTask.NO_REPEATING; -+ this.taskName = taskName; -+ this.timings = null; // Will be changed in later patch -+ } -+ // Paper end - - CraftTask(final Plugin plugin, final Object task, final int id, final long period) { - this.plugin = plugin; -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -new file mode 100644 -index 0000000000000000000000000000000000000000..49dc0c441b9dd7e7745cf15ced67f383ebee1f99 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -@@ -0,0 +1,132 @@ -+package org.bukkit.craftbukkit.scheduler; -+ -+ -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.configuration.file.FileConfiguration; -+import org.bukkit.generator.ChunkGenerator; -+import org.bukkit.plugin.PluginBase; -+import org.bukkit.plugin.PluginDescriptionFile; -+import org.bukkit.plugin.PluginLoader; -+import org.bukkit.plugin.PluginLogger; -+ -+import java.io.File; -+import java.io.InputStream; -+import java.util.List; -+ -+public class MinecraftInternalPlugin extends PluginBase { -+ private boolean enabled = true; -+ -+ private final String pluginName; -+ private PluginDescriptionFile pdf; -+ -+ public MinecraftInternalPlugin() { -+ this.pluginName = "Minecraft"; -+ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); -+ } -+ -+ public void setEnabled(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public File getDataFolder() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginDescriptionFile getDescription() { -+ return pdf; -+ } -+ -+ @Override -+ public FileConfiguration getConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public InputStream getResource(String filename) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveDefaultConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveResource(String resourcePath, boolean replace) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void reloadConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLogger getLogger() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLoader getPluginLoader() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public Server getServer() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void onDisable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onLoad() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onEnable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isNaggable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void setNaggable(boolean canNag) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -index f4ea5809f48fda39e32738529b4ae8f74acadb90..b2b14eada44231a619622a2baef27abdb798aa47 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -@@ -168,7 +168,23 @@ public class DummyGeneratorAccess implements GeneratorAccess { - public Fluid getFluid(BlockPosition blockposition) { - throw new UnsupportedOperationException("Not supported yet."); - } -+ // Paper start - if loaded util -+ @javax.annotation.Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } - -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end - @Override - public WorldBorder getWorldBorder() { - throw new UnsupportedOperationException("Not supported yet."); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index 1aec70a1f1a9d8fd2cd06bde4033e19e769ab331..f72c13bedaa6fa45e26f5dcad564835bdd4af61f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -@@ -17,7 +17,7 @@ import java.util.RandomAccess; - public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { - private static final long serialVersionUID = 8683452581112892191L; - -- private transient Object[] data; -+ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get - private int size; - private int initialCapacity; - -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 724c6a47846f4266c858b783f68f162e0508d2fa..c04d912adf0da8f7a5b75dd2f58739a11ca31601 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -118,7 +118,11 @@ public class SpigotConfig - } - } - } -- -+ // Paper start -+ SpigotConfig.save(); -+ } -+ public static void save() { -+ // Paper end - try - { - config.save( CONFIG_FILE ); diff --git a/Spigot-Server-Patches/0005-Paper-Metrics.patch b/Spigot-Server-Patches/0005-Paper-Metrics.patch deleted file mode 100644 index be4c3154fbf4..000000000000 --- a/Spigot-Server-Patches/0005-Paper-Metrics.patch +++ /dev/null @@ -1,735 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 24 Mar 2017 23:56:01 -0500 -Subject: [PATCH] Paper Metrics - -Removes Spigot's mcstats metrics in favor of a system using bStats - -To disable for privacy or other reasons go to the bStats folder in your plugins folder -and edit the config.yml file present there. - -Please keep in mind the data collected is anonymous and collection should have no -tangible effect on server performance. The data is used to allow the authors of -PaperMC to track version and platform usage so that we can make better management -decisions on behalf of the project. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0b9e689d57705965721b5c55bc45d36657f360e4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -0,0 +1,670 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.plugin.Plugin; -+ -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import javax.net.ssl.HttpsURLConnection; -+import java.io.ByteArrayOutputStream; -+import java.io.DataOutputStream; -+import java.io.File; -+import java.io.IOException; -+import java.net.URL; -+import java.util.*; -+import java.util.concurrent.Callable; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ScheduledExecutorService; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import java.util.zip.GZIPOutputStream; -+ -+/** -+ * bStats collects some data for plugin authors. -+ * -+ * Check out https://bStats.org/ to learn more about bStats! -+ */ -+public class Metrics { -+ -+ // Executor service for requests -+ // We use an executor service because the Bukkit scheduler is affected by server lags -+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); -+ -+ // The version of this bStats class -+ public static final int B_STATS_VERSION = 1; -+ -+ // The url to which the data is sent -+ private static final String URL = "https://bStats.org/submitData/server-implementation"; -+ -+ // Should failed requests be logged? -+ private static boolean logFailedRequests = false; -+ -+ // The logger for the failed requests -+ private static Logger logger = Logger.getLogger("bStats"); -+ -+ // The name of the server software -+ private final String name; -+ -+ // The uuid of the server -+ private final String serverUUID; -+ -+ // A list with all custom charts -+ private final List charts = new ArrayList<>(); -+ -+ /** -+ * Class constructor. -+ * -+ * @param name The name of the server software. -+ * @param serverUUID The uuid of the server. -+ * @param logFailedRequests Whether failed requests should be logged or not. -+ * @param logger The logger for the failed requests. -+ */ -+ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { -+ this.name = name; -+ this.serverUUID = serverUUID; -+ Metrics.logFailedRequests = logFailedRequests; -+ Metrics.logger = logger; -+ -+ // Start submitting the data -+ startSubmitting(); -+ } -+ -+ /** -+ * Adds a custom chart. -+ * -+ * @param chart The chart to add. -+ */ -+ public void addCustomChart(CustomChart chart) { -+ if (chart == null) { -+ throw new IllegalArgumentException("Chart cannot be null!"); -+ } -+ charts.add(chart); -+ } -+ -+ /** -+ * Starts the Scheduler which submits our data every 30 minutes. -+ */ -+ private void startSubmitting() { -+ final Runnable submitTask = this::submitData; -+ -+ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the -+ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -+ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! -+ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! -+ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); -+ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); -+ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); -+ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); -+ } -+ -+ /** -+ * Gets the plugin specific data. -+ * -+ * @return The plugin specific data. -+ */ -+ private JSONObject getPluginData() { -+ JSONObject data = new JSONObject(); -+ -+ data.put("pluginName", name); // Append the name of the server software -+ JSONArray customCharts = new JSONArray(); -+ for (CustomChart customChart : charts) { -+ // Add the data of the custom charts -+ JSONObject chart = customChart.getRequestJsonObject(); -+ if (chart == null) { // If the chart is null, we skip it -+ continue; -+ } -+ customCharts.add(chart); -+ } -+ data.put("customCharts", customCharts); -+ -+ return data; -+ } -+ -+ /** -+ * Gets the server specific data. -+ * -+ * @return The server specific data. -+ */ -+ private JSONObject getServerData() { -+ // OS specific data -+ String osName = System.getProperty("os.name"); -+ String osArch = System.getProperty("os.arch"); -+ String osVersion = System.getProperty("os.version"); -+ int coreCount = Runtime.getRuntime().availableProcessors(); -+ -+ JSONObject data = new JSONObject(); -+ -+ data.put("serverUUID", serverUUID); -+ -+ data.put("osName", osName); -+ data.put("osArch", osArch); -+ data.put("osVersion", osVersion); -+ data.put("coreCount", coreCount); -+ -+ return data; -+ } -+ -+ /** -+ * Collects the data and sends it afterwards. -+ */ -+ private void submitData() { -+ final JSONObject data = getServerData(); -+ -+ JSONArray pluginData = new JSONArray(); -+ pluginData.add(getPluginData()); -+ data.put("plugins", pluginData); -+ -+ try { -+ // We are still in the Thread of the timer, so nothing get blocked :) -+ sendData(data); -+ } catch (Exception e) { -+ // Something went wrong! :( -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Could not submit stats of " + name, e); -+ } -+ } -+ } -+ -+ /** -+ * Sends the data to the bStats server. -+ * -+ * @param data The data to send. -+ * @throws Exception If the request failed. -+ */ -+ private static void sendData(JSONObject data) throws Exception { -+ if (data == null) { -+ throw new IllegalArgumentException("Data cannot be null!"); -+ } -+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); -+ -+ // Compress the data to save bandwidth -+ byte[] compressedData = compress(data.toString()); -+ -+ // Add headers -+ connection.setRequestMethod("POST"); -+ connection.addRequestProperty("Accept", "application/json"); -+ connection.addRequestProperty("Connection", "close"); -+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request -+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); -+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format -+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); -+ -+ // Send data -+ connection.setDoOutput(true); -+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); -+ outputStream.write(compressedData); -+ outputStream.flush(); -+ outputStream.close(); -+ -+ connection.getInputStream().close(); // We don't care about the response - Just send our data :) -+ } -+ -+ /** -+ * Gzips the given String. -+ * -+ * @param str The string to gzip. -+ * @return The gzipped String. -+ * @throws IOException If the compression failed. -+ */ -+ private static byte[] compress(final String str) throws IOException { -+ if (str == null) { -+ return null; -+ } -+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); -+ gzip.write(str.getBytes("UTF-8")); -+ gzip.close(); -+ return outputStream.toByteArray(); -+ } -+ -+ /** -+ * Represents a custom chart. -+ */ -+ public static abstract class CustomChart { -+ -+ // The id of the chart -+ final String chartId; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ */ -+ CustomChart(String chartId) { -+ if (chartId == null || chartId.isEmpty()) { -+ throw new IllegalArgumentException("ChartId cannot be null or empty!"); -+ } -+ this.chartId = chartId; -+ } -+ -+ private JSONObject getRequestJsonObject() { -+ JSONObject chart = new JSONObject(); -+ chart.put("chartId", chartId); -+ try { -+ JSONObject data = getChartData(); -+ if (data == null) { -+ // If the data is null we don't send the chart. -+ return null; -+ } -+ chart.put("data", data); -+ } catch (Throwable t) { -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); -+ } -+ return null; -+ } -+ return chart; -+ } -+ -+ protected abstract JSONObject getChartData() throws Exception; -+ -+ } -+ -+ /** -+ * Represents a custom simple pie. -+ */ -+ public static class SimplePie extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimplePie(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ String value = callable.call(); -+ if (value == null || value.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom advanced pie. -+ */ -+ public static class AdvancedPie extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedPie(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom drilldown pie. -+ */ -+ public static class DrilldownPie extends CustomChart { -+ -+ private final Callable>> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public DrilldownPie(String chartId, Callable>> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ public JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map> map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean reallyAllSkipped = true; -+ for (Map.Entry> entryValues : map.entrySet()) { -+ JSONObject value = new JSONObject(); -+ boolean allSkipped = true; -+ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { -+ value.put(valueEntry.getKey(), valueEntry.getValue()); -+ allSkipped = false; -+ } -+ if (!allSkipped) { -+ reallyAllSkipped = false; -+ values.put(entryValues.getKey(), value); -+ } -+ } -+ if (reallyAllSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom single line chart. -+ */ -+ public static class SingleLineChart extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SingleLineChart(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ int value = callable.call(); -+ if (value == 0) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom multi line chart. -+ */ -+ public static class MultiLineChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public MultiLineChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom simple bar chart. -+ */ -+ public static class SimpleBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimpleBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ for (Map.Entry entry : map.entrySet()) { -+ JSONArray categoryValues = new JSONArray(); -+ categoryValues.add(entry.getValue()); -+ values.put(entry.getKey(), categoryValues); -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom advanced bar chart. -+ */ -+ public static class AdvancedBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue().length == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ JSONArray categoryValues = new JSONArray(); -+ for (int categoryValue : entry.getValue()) { -+ categoryValues.add(categoryValue); -+ } -+ values.put(entry.getKey(), categoryValues); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ static class PaperMetrics { -+ static void startMetrics() { -+ // Get the config file -+ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); -+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); -+ -+ // Check if the config file exists -+ if (!config.isSet("serverUuid")) { -+ -+ // Add default values -+ config.addDefault("enabled", true); -+ // Every server gets it's unique random id. -+ config.addDefault("serverUuid", UUID.randomUUID().toString()); -+ // Should failed request be logged? -+ config.addDefault("logFailedRequests", false); -+ -+ // Inform the server owners about bStats -+ config.options().header( -+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + -+ "To honor their work, you should not disable it.\n" + -+ "This has nearly no effect on the server performance!\n" + -+ "Check out https://bStats.org/ to learn more :)" -+ ).copyDefaults(true); -+ try { -+ config.save(configFile); -+ } catch (IOException ignored) { -+ } -+ } -+ // Load the data -+ String serverUUID = config.getString("serverUuid"); -+ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); -+ // Only start Metrics, if it's enabled in the config -+ if (config.getBoolean("enabled", true)) { -+ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); -+ -+ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { -+ String minecraftVersion = Bukkit.getVersion(); -+ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); -+ return minecraftVersion; -+ })); -+ -+ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); -+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); -+ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { -+ Map> map = new HashMap<>(); -+ String javaVersion = System.getProperty("java.version"); -+ Map entry = new HashMap<>(); -+ entry.put(javaVersion, 1); -+ -+ // http://openjdk.java.net/jeps/223 -+ // Java decided to change their versioning scheme and in doing so modified the java.version system -+ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier -+ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ -+ String majorVersion = javaVersion.split("\\.")[0]; -+ String release; -+ -+ int indexOf = javaVersion.lastIndexOf('.'); -+ -+ if (majorVersion.equals("1")) { -+ release = "Java " + javaVersion.substring(0, indexOf); -+ } else { -+ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it -+ // valid strings for the major may potentially include values such as -ea to deannotate a pre release -+ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); -+ if (versionMatcher.find()) { -+ majorVersion = versionMatcher.group(0); -+ } -+ release = "Java " + majorVersion; -+ } -+ map.put(release, entry); -+ -+ return map; -+ })); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { -+ Map> map = new HashMap<>(); -+ -+ // count legacy plugins -+ int legacy = 0; -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { -+ legacy++; -+ } -+ } -+ -+ // insert real value as lower dimension -+ Map entry = new HashMap<>(); -+ entry.put(String.valueOf(legacy), 1); -+ -+ // create buckets as higher dimension -+ if (legacy == 0) { -+ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: -+ } else if (legacy <= 5) { -+ map.put("1-5", entry); -+ } else if (legacy <= 10) { -+ map.put("6-10", entry); -+ } else if (legacy <= 25) { -+ map.put("11-25", entry); -+ } else if (legacy <= 50) { -+ map.put("26-50", entry); -+ } else { -+ map.put("50+ \uD83D\uDE2D", entry); // :cry: -+ } -+ -+ return map; -+ })); -+ } -+ -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 2c0514892d3993bef57ecf677cf8bb0fbe0216e4..da922f395f0fff0881ead893c900c5b2623f48f0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -42,6 +42,7 @@ public class PaperConfig { - private static boolean verbose; - private static boolean fatalError; - /*========================================================================*/ -+ private static boolean metricsStarted; - - public static void init(File configFile) { - CONFIG_FILE = configFile; -@@ -84,6 +85,11 @@ public class PaperConfig { - for (Map.Entry entry : commands.entrySet()) { - MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); - } -+ -+ if (!metricsStarted) { -+ Metrics.PaperMetrics.startMetrics(); -+ metricsStarted = true; -+ } - } - - static void readConfig(Class clazz, Object instance) { -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index f08110a22646716bcdf6a8d25ec44df8d78e85a4..23c1ba33903f8913a33332d06b2fd1aa3c90f1a1 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -83,6 +83,7 @@ public class SpigotConfig - MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); - } - -+ /* // Paper - Replace with our own - if ( metrics == null ) - { - try -@@ -94,6 +95,7 @@ public class SpigotConfig - Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); - } - } -+ */ // Paper end - } - - static void readConfig(Class clazz, Object instance) diff --git a/Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch b/Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch deleted file mode 100644 index a390f7960d2a..000000000000 --- a/Spigot-Server-Patches/0006-Add-MinecraftKey-Information-to-Objects.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 01:40:13 -0400 -Subject: [PATCH] Add MinecraftKey Information to Objects - -Stores the reference to the objects respective MinecraftKey - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 68cd4134cb6a00c1768100462f8e9e94f3fa6279..6943524c2dd8b12691b8ac5b08daee823ce50c3d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -208,7 +208,7 @@ public class PaperCommand extends Command { - - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { -- MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ MinecraftKey key = e.getMinecraftKey(); - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java -new file mode 100644 -index 0000000000000000000000000000000000000000..500477f0d98a277145c2b0dbb4d1496e2a588542 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/KeyedObject.java -@@ -0,0 +1,11 @@ -+package net.minecraft.server; -+ -+import net.minecraft.resources.MinecraftKey; -+ -+public interface KeyedObject { -+ MinecraftKey getMinecraftKey(); -+ default String getMinecraftKeyString() { -+ MinecraftKey key = getMinecraftKey(); -+ return key != null ? key.toString() : null; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 3c8767d5fab575e61ca179b517f0bff1a38405ce..ec553e7d7595ef3652bfa3325a07483bb3c32245 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -136,7 +136,7 @@ import org.bukkit.event.player.PlayerTeleportEvent; - import org.bukkit.plugin.PluginManager; - // CraftBukkit end - --public abstract class Entity implements INamableTileEntity, ICommandListener { -+public abstract class Entity implements INamableTileEntity, ICommandListener, net.minecraft.server.KeyedObject { // Paper - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -@@ -1762,12 +1762,31 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { - return true; - } - -+ // Paper start -+ private MinecraftKey entityKey; -+ private String entityKeyString; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (entityKey == null) { -+ this.entityKey = EntityTypes.getName(this.getEntityType()); -+ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; -+ } -+ return entityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 -+ return entityKeyString; -+ } - @Nullable - public final String getSaveID() { - EntityTypes entitytypes = this.getEntityType(); - MinecraftKey minecraftkey = EntityTypes.getName(entitytypes); - -- return entitytypes.a() && minecraftkey != null ? minecraftkey.toString() : null; -+ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; -+ // Paper end - } - - protected abstract void loadData(NBTTagCompound nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index ac57ab9992e141c91cf48f033148ad78433b364c..dc92b112770955f9fa49a408262da2e5bbc4bf98 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -384,6 +384,7 @@ public class EntityTypes { - } - } - -+ public boolean isPersistable() { return a(); } // Paper - OBFHELPER - public boolean a() { - return this.bi; - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 72d43b38de3e797a509de6591874af12fa7b9ec0..2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -23,7 +23,7 @@ import org.bukkit.inventory.InventoryHolder; - - import org.spigotmc.CustomTimingsHandler; // Spigot - --public abstract class TileEntity { -+public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - - public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot - // CraftBukkit start - data containers -@@ -31,7 +31,7 @@ public abstract class TileEntity { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -- private final TileEntityTypes tileType; -+ private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; - protected BlockPosition position; -@@ -45,6 +45,26 @@ public abstract class TileEntity { - this.tileType = tileentitytypes; - } - -+ // Paper start -+ private String tileEntityKeyString = null; -+ private MinecraftKey tileEntityKey = null; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (tileEntityKey == null) { -+ tileEntityKey = TileEntityTypes.a(this.getTileEntityType()); -+ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; -+ } -+ return tileEntityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. -+ return tileEntityKeyString; -+ } -+ // Paper end -+ - @Nullable - public World getWorld() { - return this.world; diff --git a/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch deleted file mode 100644 index 873dc9de7e8b..000000000000 --- a/Spigot-Server-Patches/0007-Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:10:36 -0400 -Subject: [PATCH] Store reference to current Chunk for Entity and Block - Entities - -This enables us a fast reference to the entities current chunk instead -of having to look it up by hashmap lookups. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ec553e7d7595ef3652bfa3325a07483bb3c32245..2bea2f4748cadf479dd4f89792ef5ffdd88e9cab 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -261,7 +261,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isChunkLoaded() { -- return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); -+ return getCurrentChunk() != null; - } - // CraftBukkit end - -@@ -1763,6 +1763,23 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public java.lang.ref.WeakReference currentChunk = null; -+ -+ public void setCurrentChunk(net.minecraft.world.level.chunk.Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } -+ /** -+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null -+ */ -+ public net.minecraft.world.level.chunk.Chunk getCurrentChunk() { -+ final net.minecraft.world.level.chunk.Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ if (chunk != null && chunk.loaded) { -+ return chunk; -+ } -+ -+ return !inChunk ? null : ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(chunkX, chunkZ); -+ } -+ - private MinecraftKey entityKey; - private String entityKeyString; - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 2b58ae6d91fe0d0f36eedbb78a3c8a8a66d92405..75110c41af3e0097aef65091a2497dd87d08b4b2 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -11,6 +11,7 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.block.EnumBlockMirror; - import net.minecraft.world.level.block.EnumBlockRotation; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import org.apache.logging.log4j.util.Supplier; -@@ -63,6 +64,15 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - getMinecraftKey(); // Try to load if it doesn't exists. - return tileEntityKeyString; - } -+ -+ private java.lang.ref.WeakReference currentChunk = null; -+ public Chunk getCurrentChunk() { -+ final Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ return chunk != null && chunk.loaded ? chunk : null; -+ } -+ public void setCurrentChunk(Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } - // Paper end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index b15200c2a3923bd8be2ee5e73fdadfeea3e3a8dc..929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -90,11 +90,36 @@ public class Chunk implements IChunkAccess { - this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); - } - -+ // Paper start -+ private class TileEntityHashMap extends java.util.HashMap { -+ @Override -+ public TileEntity put(BlockPosition key, TileEntity value) { -+ TileEntity replaced = super.put(key, value); -+ if (replaced != null) { -+ replaced.setCurrentChunk(null); -+ } -+ if (value != null) { -+ value.setCurrentChunk(Chunk.this); -+ } -+ return replaced; -+ } -+ -+ @Override -+ public TileEntity remove(Object key) { -+ TileEntity removed = super.remove(key); -+ if (removed != null) { -+ removed.setCurrentChunk(null); -+ } -+ return removed; -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { - this.sections = new ChunkSection[16]; - this.e = Maps.newHashMap(); - this.heightMap = Maps.newEnumMap(HeightMap.Type.class); -- this.tileEntities = Maps.newHashMap(); -+ this.tileEntities = new TileEntityHashMap(); // Paper - this.l = Maps.newHashMap(); - this.m = Maps.newHashMap(); - this.n = new ShortList[16]; -@@ -505,6 +530,7 @@ public class Chunk implements IChunkAccess { - } - - entity.inChunk = true; -+ entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -@@ -517,6 +543,7 @@ public class Chunk implements IChunkAccess { - ((HeightMap) this.heightMap.get(heightmap_type)).a(along); - } - -+ public final void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER - public void b(Entity entity) { - this.a(entity, entity.chunkY); - } -@@ -531,7 +558,12 @@ public class Chunk implements IChunkAccess { - i = this.entitySlices.length - 1; - } - -- this.entitySlices[i].remove(entity); -+ // Paper start -+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (!this.entitySlices[i].remove(entity)) { -+ return; -+ } -+ // Paper end - this.entities.remove(entity); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index df7e5f1d17ddfeffc15df02906c3bf9f9461d82b..eea242af23825ad29ada6e997205e87edffb6bb9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; - import net.minecraft.world.phys.AxisAlignedBB; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - this.entity = entity; - } - -+ @Override -+ public Chunk getChunk() { -+ net.minecraft.world.level.chunk.Chunk currentChunk = entity.getCurrentChunk(); -+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); -+ } -+ - public static CraftEntity getEntity(CraftServer server, Entity entity) { - /* - * Order is *EXTREMELY* important -- keep it right! =D diff --git a/Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch b/Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch deleted file mode 100644 index 73d224306f1c..000000000000 --- a/Spigot-Server-Patches/0008-Store-counts-for-each-Entity-Block-Entity-Type.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:13:59 -0400 -Subject: [PATCH] Store counts for each Entity/Block Entity Type - -Opens door for future patches to optimize performance - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 929f6fcd4b9f1b9a1488e170d6a77a5d64beecf3..acdcece38a4b30d6c89eb4342918ae8997db9f0b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -91,15 +91,19 @@ public class Chunk implements IChunkAccess { - } - - // Paper start -+ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); -+ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public TileEntity put(BlockPosition key, TileEntity value) { - TileEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); -+ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); - } - if (value != null) { - value.setCurrentChunk(Chunk.this); -+ tileEntityCounts.increment(value.getMinecraftKeyString()); - } - return replaced; - } -@@ -109,6 +113,7 @@ public class Chunk implements IChunkAccess { - TileEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); -+ tileEntityCounts.decrement(removed.getMinecraftKeyString()); - } - return removed; - } -@@ -529,6 +534,7 @@ public class Chunk implements IChunkAccess { - k = this.entitySlices.length - 1; - } - -+ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; - entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; -@@ -563,6 +569,7 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ entityCounts.decrement(entity.getMinecraftKeyString()); - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Spigot-Server-Patches/0009-Timings-v2.patch b/Spigot-Server-Patches/0009-Timings-v2.patch deleted file mode 100644 index 40a97bbc13c3..000000000000 --- a/Spigot-Server-Patches/0009-Timings-v2.patch +++ /dev/null @@ -1,2304 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 04:00:11 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fed920e5ec65409377f181d74dcf9274d45aadc1 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +1,151 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.MapMaker; -+import net.minecraft.commands.CustomFunction; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntity; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.scheduler.BukkitTask; -+ -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+ -+import java.util.Map; -+ -+// TODO: Re-implement missing timers -+public final class MinecraftTimings { -+ -+ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing playerListTimer = Timings.ofSafe("Player List"); -+ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); -+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); -+ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); -+ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); -+ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); -+ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); -+ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); -+ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); -+ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); -+ public static final Timing savePlayers = Timings.ofSafe("Save Players"); -+ -+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); -+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); -+ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); -+ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); -+ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); -+ -+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); -+ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); -+ -+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); -+ -+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); -+ -+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); -+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ -+ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); -+ -+ private MinecraftTimings() {} -+ -+ public static Timing getInternalTaskName(String taskName) { -+ return Timings.ofSafe(taskName); -+ } -+ -+ /** -+ * Gets a timer associated with a plugins tasks. -+ * @param bukkitTask -+ * @param period -+ * @return -+ */ -+ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { -+ if (!bukkitTask.isSync()) { -+ return NullTimingHandler.NULL; -+ } -+ Plugin plugin; -+ -+ CraftTask craftTask = (CraftTask) bukkitTask; -+ -+ final Class taskClass = craftTask.getTaskClass(); -+ if (bukkitTask.getOwner() != null) { -+ plugin = bukkitTask.getOwner(); -+ } else { -+ plugin = TimingsManager.getPluginByClassloader(taskClass); -+ } -+ -+ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { -+ try { -+ String clsName = !clazz.isMemberClass() -+ ? clazz.getName() -+ : clazz.getCanonicalName(); -+ if (clsName != null && clsName.contains("$Lambda$")) { -+ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); -+ } -+ return clsName != null ? clsName : "UnknownTask"; -+ } catch (Throwable ex) { -+ new Exception("Error occurred detecting class name", ex).printStackTrace(); -+ return "MangledClassFile"; -+ } -+ }); -+ -+ StringBuilder name = new StringBuilder(64); -+ name.append("Task: ").append(taskname); -+ if (period > 0) { -+ name.append(" (interval:").append(period).append(")"); -+ } else { -+ name.append(" (Single)"); -+ } -+ -+ if (plugin == null) { -+ return Timings.ofSafe(null, name.toString()); -+ } -+ -+ return Timings.ofSafe(plugin, name.toString()); -+ } -+ -+ /** -+ * Get a named timer for the specified entity type to track type specific timings. -+ * @param entityType -+ * @return -+ */ -+ public static Timing getEntityTimings(String entityType, String type) { -+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); -+ } -+ -+ /** -+ * Get a named timer for the specified tile entity type to track type specific timings. -+ * @param entity -+ * @return -+ */ -+ public static Timing getTileEntityTimings(TileEntity entity) { -+ String entityType = entity.getClass().getName(); -+ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); -+ } -+ public static Timing getCancelTasksTimer() { -+ return Timings.ofSafe("Cancel Tasks"); -+ } -+ public static Timing getCancelTasksTimer(Plugin plugin) { -+ return Timings.ofSafe(plugin, "Cancel Tasks"); -+ } -+ -+ public static void stopServer() { -+ TimingsManager.stopServer(); -+ } -+ -+ public static Timing getBlockTiming(Block block) { -+ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); -+ } -+/* -+ public static Timing getStructureTiming(StructureGenerator structureGenerator) { -+ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); -+ }*/ -+ -+ public static Timing getPacketTiming(Packet packet) { -+ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); -+ } -+ -+ public static Timing getCommandFunctionTiming(CustomFunction function) { -+ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d4ebcf8f66197299256bd6b65710a1488c90ea41 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +1,377 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * 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. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.Sets; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang.StringUtils; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemorySection; -+import org.bukkit.craftbukkit.util.CraftChatMessage; -+import org.bukkit.entity.EntityType; -+import org.json.simple.JSONObject; -+import org.json.simple.JSONValue; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.OutputStream; -+import java.lang.management.ManagementFactory; -+import java.lang.management.OperatingSystemMXBean; -+import java.lang.management.RuntimeMXBean; -+import java.net.HttpURLConnection; -+import java.net.InetAddress; -+import java.net.URL; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.logging.Level; -+import java.util.zip.GZIPOutputStream; -+ -+import static co.aikar.timings.TimingsManager.HISTORY; -+import static co.aikar.util.JSONUtil.appendObjectData; -+import static co.aikar.util.JSONUtil.createObject; -+import static co.aikar.util.JSONUtil.pair; -+import static co.aikar.util.JSONUtil.toArray; -+import static co.aikar.util.JSONUtil.toArrayMapper; -+import static co.aikar.util.JSONUtil.toObjectMapper; -+ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public class TimingsExport extends Thread { -+ -+ private final TimingsReportListener listeners; -+ private final Map out; -+ private final TimingHistory[] history; -+ private static long lastReport = 0; -+ -+ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { -+ super("Timings paste thread"); -+ this.listeners = listeners; -+ this.out = out; -+ this.history = history; -+ } -+ -+ /** -+ * Checks if any pending reports are being requested, and builds one if needed. -+ */ -+ public static void reportTimings() { -+ if (Timings.requestingReport.isEmpty()) { -+ return; -+ } -+ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); -+ listeners.addConsoleIfNeeded(); -+ -+ Timings.requestingReport.clear(); -+ long now = System.currentTimeMillis(); -+ final long lastReportDiff = now - lastReport; -+ if (lastReportDiff < 60000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ final long lastStartDiff = now - TimingsManager.timingStart; -+ if (lastStartDiff < 180000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); -+ lastReport = now; -+ Map parent = createObject( -+ // Get some basic system details about the server -+ pair("version", Bukkit.getVersion()), -+ pair("maxplayers", Bukkit.getMaxPlayers()), -+ pair("start", TimingsManager.timingStart / 1000), -+ pair("end", System.currentTimeMillis() / 1000), -+ pair("online-mode", Bukkit.getServer().getOnlineMode()), -+ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ // Don't feel like obf helper'ing these, non fatal if its temp missed. -+ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); -+ })) -+ ); -+ if (!TimingsManager.privacy) { -+ appendObjectData(parent, -+ pair("server", Bukkit.getUnsafe().getTimingsServerName()), -+ pair("motd", Bukkit.getServer().getMotd()), -+ pair("icon", Bukkit.getServer().getServerIcon().getData()) -+ ); -+ } -+ -+ final Runtime runtime = Runtime.getRuntime(); -+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); -+ -+ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); -+ -+ parent.put("system", createObject( -+ pair("timingcost", getCost()), -+ pair("loadavg", osInfo.getSystemLoadAverage()), -+ pair("name", System.getProperty("os.name")), -+ pair("version", System.getProperty("os.version")), -+ pair("jvmversion", System.getProperty("java.version")), -+ pair("arch", System.getProperty("os.arch")), -+ pair("maxmem", runtime.maxMemory()), -+ pair("memory", createObject( -+ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), -+ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), -+ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) -+ )), -+ pair("cpu", runtime.availableProcessors()), -+ pair("runtime", runtimeBean.getUptime()), -+ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), -+ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) -+ ) -+ ); -+ -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( -+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { -+ return pair(rule, world.getWorld().getGameRuleValue(rule)); -+ })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ )); -+ })); -+ -+ Set tileEntityTypeSet = Sets.newHashSet(); -+ Set entityTypeSet = Sets.newHashSet(); -+ -+ int size = HISTORY.size(); -+ TimingHistory[] history = new TimingHistory[size + 1]; -+ int i = 0; -+ for (TimingHistory timingHistory : HISTORY) { -+ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); -+ entityTypeSet.addAll(timingHistory.entityTypeSet); -+ history[i++] = timingHistory; -+ } -+ -+ history[i] = new TimingHistory(); // Current snapshot -+ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); -+ entityTypeSet.addAll(history[i].entityTypeSet); -+ -+ -+ Map handlers = createObject(); -+ Map groupData; -+ synchronized (TimingIdentifier.GROUP_MAP) { -+ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { -+ synchronized (group.handlers) { -+ for (TimingHandler id : group.handlers) { -+ -+ if (!id.isTimed() && !id.isSpecial()) { -+ continue; -+ } -+ -+ String name = id.identifier.name; -+ if (name.startsWith("##")) { -+ name = name.substring(3); -+ } -+ handlers.put(id.id, toArray( -+ group.id, -+ name -+ )); -+ } -+ } -+ } -+ -+ groupData = toObjectMapper( -+ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); -+ } -+ -+ parent.put("idmap", createObject( -+ pair("groups", groupData), -+ pair("handlers", handlers), -+ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), -+ pair("tileentity", -+ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), -+ pair("entity", -+ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) -+ )); -+ -+ // Information about loaded plugins -+ -+ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), -+ plugin -> pair(plugin.getName(), createObject( -+ pair("version", plugin.getDescription().getVersion()), -+ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), -+ pair("website", plugin.getDescription().getWebsite()), -+ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) -+ )))); -+ -+ -+ -+ // Information on the users Config -+ -+ parent.put("config", createObject( -+ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), -+ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ )); -+ -+ new TimingsExport(listeners, parent, history).start(); -+ } -+ -+ static long getCost() { -+ // Benchmark the users System.nanotime() for cost basis -+ int passes = 100; -+ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); -+ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); -+ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); -+ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); -+ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); -+ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); -+ -+ long start = System.nanoTime(); -+ for (int i = 0; i < passes; i++) { -+ SAMPLER1.startTiming(); -+ SAMPLER2.startTiming(); -+ SAMPLER3.startTiming(); -+ SAMPLER3.stopTiming(); -+ SAMPLER4.startTiming(); -+ SAMPLER5.startTiming(); -+ SAMPLER6.startTiming(); -+ SAMPLER6.stopTiming(); -+ SAMPLER5.stopTiming(); -+ SAMPLER4.stopTiming(); -+ SAMPLER2.stopTiming(); -+ SAMPLER1.stopTiming(); -+ } -+ long timingsCost = (System.nanoTime() - start) / passes / 6; -+ SAMPLER1.reset(true); -+ SAMPLER2.reset(true); -+ SAMPLER3.reset(true); -+ SAMPLER4.reset(true); -+ SAMPLER5.reset(true); -+ SAMPLER6.reset(true); -+ return timingsCost; -+ } -+ -+ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { -+ -+ JSONObject object = new JSONObject(); -+ for (String key : config.getKeys(false)) { -+ String fullKey = (parentKey != null ? parentKey + "." + key : key); -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ continue; -+ } -+ final Object val = config.get(key); -+ -+ object.put(key, valAsJSON(val, fullKey)); -+ } -+ return object; -+ } -+ -+ private static Object valAsJSON(Object val, final String parentKey) { -+ if (!(val instanceof MemorySection)) { -+ if (val instanceof List) { -+ Iterable v = (Iterable) val; -+ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); -+ } else { -+ return String.valueOf(val); -+ } -+ } else { -+ return mapAsJSON((ConfigurationSection) val, parentKey); -+ } -+ } -+ -+ @Override -+ public void run() { -+ out.put("data", toArrayMapper(history, TimingHistory::export)); -+ -+ -+ String response = null; -+ String timingsURL = null; -+ try { -+ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); -+ con.setDoOutput(true); -+ String hostName = "BrokenHost"; -+ try { -+ hostName = InetAddress.getLocalHost().getHostName(); -+ } catch (Exception ignored) {} -+ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); -+ con.setRequestMethod("POST"); -+ con.setInstanceFollowRedirects(false); -+ -+ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ -+ this.def.setLevel(7); -+ }}; -+ -+ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); -+ request.close(); -+ -+ response = getResponse(con); -+ -+ if (con.getResponseCode() != 302) { -+ listeners.sendMessage( -+ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); -+ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ return; -+ } -+ -+ timingsURL = con.getHeaderField("Location"); -+ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); -+ -+ if (response != null && !response.isEmpty()) { -+ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); -+ } -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); -+ } finally { -+ this.listeners.done(timingsURL); -+ } -+ } -+ -+ private String getResponse(HttpURLConnection con) throws IOException { -+ InputStream is = null; -+ try { -+ is = con.getInputStream(); -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ -+ byte[] b = new byte[1024]; -+ int bytesRead; -+ while ((bytesRead = is.read(b)) != -1) { -+ bos.write(b, 0, bytesRead); -+ } -+ return bos.toString(); -+ -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); -+ return null; -+ } finally { -+ if (is != null) { -+ is.close(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fa154ed68187a2020e814db6345a8cc1119ab4ba ---- /dev/null -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +1,119 @@ -+package co.aikar.timings; -+ -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.storage.WorldDataServer; -+ -+/** -+ * Set of timers per world, to track world specific timings. -+ */ -+// TODO: Re-implement missing timers -+public class WorldTimingsHandler { -+ public final Timing mobSpawn; -+ public final Timing doChunkUnload; -+ public final Timing doPortalForcer; -+ public final Timing scheduledBlocks; -+ public final Timing scheduledBlocksCleanup; -+ public final Timing scheduledBlocksTicking; -+ public final Timing chunkTicks; -+ public final Timing lightChunk; -+ public final Timing chunkTicksBlocks; -+ public final Timing doVillages; -+ public final Timing doChunkMap; -+ public final Timing doChunkMapUpdate; -+ public final Timing doChunkMapToUpdate; -+ public final Timing doChunkMapSortMissing; -+ public final Timing doChunkMapSortSendToPlayers; -+ public final Timing doChunkMapPlayersNeedingChunks; -+ public final Timing doChunkMapPendingSendToPlayers; -+ public final Timing doChunkMapUnloadChunks; -+ public final Timing doChunkGC; -+ public final Timing doSounds; -+ public final Timing entityRemoval; -+ public final Timing entityTick; -+ public final Timing tileEntityTick; -+ public final Timing tileEntityPending; -+ public final Timing tracker1; -+ public final Timing tracker2; -+ public final Timing doTick; -+ public final Timing tickEntities; -+ public final Timing chunks; -+ public final Timing newEntities; -+ public final Timing raids; -+ public final Timing chunkProviderTick; -+ public final Timing broadcastChunkUpdates; -+ public final Timing countNaturalMobs; -+ -+ public final Timing chunkLoad; -+ public final Timing chunkLoadPopulate; -+ public final Timing syncChunkLoad; -+ public final Timing chunkLoadLevelTimer; -+ public final Timing chunkIO; -+ public final Timing chunkPostLoad; -+ public final Timing worldSave; -+ public final Timing worldSaveChunks; -+ public final Timing worldSaveLevel; -+ public final Timing chunkSaveData; -+ -+ -+ public final Timing miscMobSpawning; -+ -+ public WorldTimingsHandler(World server) { -+ String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; -+ -+ mobSpawn = Timings.ofSafe(name + "mobSpawn"); -+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); -+ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); -+ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); -+ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); -+ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); -+ lightChunk = Timings.ofSafe(name + "Light Chunk"); -+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); -+ doVillages = Timings.ofSafe(name + "doVillages"); -+ doChunkMap = Timings.ofSafe(name + "doChunkMap"); -+ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); -+ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); -+ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); -+ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); -+ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); -+ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); -+ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); -+ doSounds = Timings.ofSafe(name + "doSounds"); -+ doChunkGC = Timings.ofSafe(name + "doChunkGC"); -+ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); -+ entityTick = Timings.ofSafe(name + "entityTick"); -+ entityRemoval = Timings.ofSafe(name + "entityRemoval"); -+ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); -+ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); -+ -+ chunkLoad = Timings.ofSafe(name + "Chunk Load"); -+ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); -+ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); -+ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); -+ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); -+ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); -+ worldSave = Timings.ofSafe(name + "World Save"); -+ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); -+ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); -+ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); -+ -+ tracker1 = Timings.ofSafe(name + "tracker stage 1"); -+ tracker2 = Timings.ofSafe(name + "tracker stage 2"); -+ doTick = Timings.ofSafe(name + "doTick"); -+ tickEntities = Timings.ofSafe(name + "tickEntities"); -+ -+ chunks = Timings.ofSafe(name + "Chunks"); -+ newEntities = Timings.ofSafe(name + "New entity registration"); -+ raids = Timings.ofSafe(name + "Raids"); -+ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); -+ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); -+ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); -+ -+ -+ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ } -+ -+ public static Timing getTickList(WorldServer worldserver, String timingsType) { -+ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da922f395f0fff0881ead893c900c5b2623f48f0..1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -14,12 +14,15 @@ import java.util.concurrent.TimeUnit; - import java.util.logging.Level; - import java.util.regex.Pattern; - -+import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; - - public class PaperConfig { - -@@ -188,4 +191,30 @@ public class PaperConfig { - config.addDefault(path, def); - return config.getString(path, config.getString(path)); - } -+ -+ public static String timingsServerName; -+ private static void timings() { -+ boolean timings = getBoolean("timings.enabled", true); -+ boolean verboseTimings = getBoolean("timings.verbose", true); -+ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); -+ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); -+ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { -+ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); -+ } -+ int timingHistoryInterval = getInt("timings.history-interval", 300); -+ int timingHistoryLength = getInt("timings.history-length", 3600); -+ timingsServerName = getString("timings.server-name", "Unknown Server"); -+ -+ -+ Timings.setVerboseTimingsEnabled(verboseTimings); -+ Timings.setTimingsEnabled(timings); -+ Timings.setHistoryInterval(timingHistoryInterval * 20); -+ Timings.setHistoryLength(timingHistoryLength * 20); -+ -+ log("Timings: " + timings + -+ " - Verbose: " + verboseTimings + -+ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + -+ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + -+ " - Server Name: " + timingsServerName); -+ } - } -diff --git a/src/main/java/net/minecraft/commands/CustomFunction.java b/src/main/java/net/minecraft/commands/CustomFunction.java -index f96b132bb51c2d97703964a70fcb058f0649ac13..4c146ac041332230f6d9a01be28b6852c7624416 100644 ---- a/src/main/java/net/minecraft/commands/CustomFunction.java -+++ b/src/main/java/net/minecraft/commands/CustomFunction.java -@@ -15,12 +15,22 @@ public class CustomFunction { - - private final CustomFunction.c[] a; - private final MinecraftKey b; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - - public CustomFunction(MinecraftKey minecraftkey, CustomFunction.c[] acustomfunction_c) { - this.b = minecraftkey; - this.a = acustomfunction_c; - } - -+ public final MinecraftKey getMinecraftKey() { return this.a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index 989683265a99fc51607aa130733e00033b444a6a..e47da20ab8ce4da34755e105bf55d8542fb50138 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -6,6 +6,8 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -@@ -22,10 +24,13 @@ public class PlayerConnectionUtils { - - public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { - if (!iasynctaskhandler.isMainThread()) { -+ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings - iasynctaskhandler.execute(() -> { - if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (t0.a().isConnected()) { -+ try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); -+ } // Paper - timings - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } -diff --git a/src/main/java/net/minecraft/server/CustomFunctionData.java b/src/main/java/net/minecraft/server/CustomFunctionData.java -index 21f5474a1cd60168ca059da542a432d40d88b514..07ca1234ad6ffa797003f7317fb88abf732bc159 100644 ---- a/src/main/java/net/minecraft/server/CustomFunctionData.java -+++ b/src/main/java/net/minecraft/server/CustomFunctionData.java -@@ -75,7 +75,7 @@ public class CustomFunctionData { - } else { - int j; - -- try { -+ try (co.aikar.timings.Timing timing = customfunction.getTiming().startTiming()) { // Paper - this.d = true; - int k = 0; - CustomFunction.c[] acustomfunction_c = customfunction.b(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index cd3e7b8a23e40c717829bd262bfa675e4e3532f9..511d6094403d17522212fcdda6903a13517c44fa 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -174,7 +174,7 @@ import org.bukkit.craftbukkit.Main; - import org.bukkit.event.server.ServerLoadEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { -@@ -228,8 +228,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return !this.canSleepForTick(); -+ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick - }); - } - -@@ -1122,10 +1135,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return !this.canOversleep(); -+ }); -+ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ // Paper end -+ - ++this.ticks; - this.b(booleansupplier); - if (i - this.T >= 5000000000L) { -@@ -1143,14 +1164,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- SpigotTimings.worldSaveTimer.startTiming(); // Spigot - MinecraftServer.LOGGER.debug("Autosave started"); - this.methodProfiler.enter("save"); - this.playerList.savePlayers(); - this.saveChunks(true, false, false); - this.methodProfiler.exit(); - MinecraftServer.LOGGER.debug("Autosave finished"); -- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot - } - - this.methodProfiler.enter("snooper"); -@@ -1163,6 +1182,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - // CraftBukkit start - fire RemoteServerCommandEvent -@@ -680,10 +682,39 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - if (event.isCancelled()) { - return; - } -+ // Paper start -+ if (s.toLowerCase().startsWith("timings") && s.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { -+ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); -+ Waitable waitable = new Waitable() { -+ @Override -+ protected String evaluate() { -+ return sender.getBuffer(); -+ } -+ }; -+ waitableArray[0] = waitable; -+ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); -+ } else { -+ // Paper end - ServerCommand serverCommand = new ServerCommand(event.getCommand(), remoteControlCommandListener.getWrapper()); - server.dispatchServerCommand(remoteConsole, serverCommand); -+ } // Paper - // CraftBukkit end - }); -+ // Paper start -+ if (waitableArray[0] != null) { -+ //noinspection unchecked -+ Waitable waitable = waitableArray[0]; -+ try { -+ return waitable.get(); -+ } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + s, e); -+ } -+ -+ } -+ // Paper end - return this.remoteControlCommandListener.getMessages(); - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0b5bcb60472c778574702a5ac26a6d02d54bfeac..9ed97d5db81e3603ccccca7500420d7e401ef2a5 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -344,11 +344,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- world.timings.syncChunkLoadTimer.startTiming(); // Spigot - CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); - -+ if (!completablefuture.isDone()) { // Paper -+ this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -- world.timings.syncChunkLoadTimer.stopTiming(); // Spigot -+ this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; - }, (playerchunk_failure) -> { -@@ -535,7 +537,9 @@ public class ChunkProviderServer extends IChunkProvider { - - public void save(boolean flag) { - this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings - this.playerChunkMap.save(flag); -+ } // Paper - Timings - } - - @Override -@@ -572,7 +576,9 @@ public class ChunkProviderServer extends IChunkProvider { - this.tickDistanceManager(); - this.world.timings.doChunkMap.stopTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("chunks"); -+ this.world.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -+ this.world.timings.chunks.stopTiming(); // Paper - timings - this.world.timings.doChunkUnload.startTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("unload"); - this.playerChunkMap.unloadChunks(booleansupplier); -@@ -596,8 +602,10 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit - - this.world.getMethodProfiler().enter("naturalSpawnCount"); -+ this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); - SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); -@@ -608,7 +616,9 @@ public class ChunkProviderServer extends IChunkProvider { - - if (optional.isPresent()) { - this.world.getMethodProfiler().enter("broadcast"); -+ this.world.timings.broadcastChunkUpdates.startTiming(); // Paper - timings - playerchunk.a((Chunk) optional.get()); -+ this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings - this.world.getMethodProfiler().exit(); - Optional optional1 = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - -@@ -622,25 +632,25 @@ public class ChunkProviderServer extends IChunkProvider { - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -- this.world.timings.doTickTiles.startTiming(); // Spigot -+ this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); -- this.world.timings.doTickTiles.stopTiming(); // Spigot -+ this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper - } - } - } - }); - this.world.getMethodProfiler().enter("customSpawners"); - if (flag1) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.world.doMobSpawning(this.allowMonsters, this.allowAnimals); -+ } // Paper - timings - } - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().exit(); - } - -- this.world.timings.tracker.startTiming(); // Spigot - this.playerChunkMap.g(); -- this.world.timings.tracker.stopTiming(); // Spigot - } - - private void a(long i, Consumer consumer) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 19856555793f742abb1178ede72dea5623f0e383..62245fa420390dc0a70ba9a95505dc46cd8aa64a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1,7 +1,9 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.Timing; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; -+import com.google.common.collect.ComparisonChain; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Queues; - import com.google.common.collect.Sets; -@@ -554,11 +556,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { - return CompletableFuture.supplyAsync(() -> { -- try { -+ try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound = this.readChunkData(chunkcoordintpair); -+ NBTTagCompound nbttagcompound; // Paper -+ try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -+ nbttagcompound = this.readChunkData(chunkcoordintpair); -+ } // Paper end - -- if (nbttagcompound != null) { -+ if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings - boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); - - if (flag) { -@@ -570,7 +575,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair); -- } -+ }} // Paper - } catch (ReportedException reportedexception) { - Throwable throwable = reportedexception.getCause(); - -@@ -607,7 +612,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return "chunkGenerate " + chunkstatus.d(); - }); - return completablefuture.thenComposeAsync((either) -> { -- return (CompletableFuture) either.map((list) -> { -+ return either.map((list) -> { // Paper - Shut up. - try { - CompletableFuture> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> { - return this.c(playerchunk); -@@ -660,6 +665,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = PlayerChunk.getChunkStatus(playerchunk.getTicketLevel()); - - return !chunkstatus.b(ChunkStatus.FULL) ? PlayerChunk.UNLOADED_CHUNK_ACCESS : either.mapLeft((ichunkaccess) -> { -+ try (Timing ignored = world.timings.chunkPostLoad.startTimingIfSync()) { // Paper - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - Chunk chunk; - -@@ -719,6 +725,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - return chunk; -+ } // Paper - }); - }, (runnable) -> { - Mailbox mailbox = this.mailboxMain; -@@ -1177,6 +1184,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker; - ObjectIterator objectiterator; -+ world.timings.tracker1.startTiming(); // Paper - - for (objectiterator = this.trackedEntities.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.trackerEntry.a()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -@@ -1194,16 +1202,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunkmap_entitytracker.e = sectionposition1; - } - } -+ world.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.trackedEntities.values().iterator(); - -+ world.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); - playerchunkmap_entitytracker.track(list); - } -+ world.timings.tracker2.stopTiming(); // Paper - } - -+ - } - - protected void broadcast(Entity entity, Packet packet) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 780e541b8d594a8a6dc3a8626a82218f2502a5c7..cf38d517821659e25e786a805e229ef2d626d75f 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -2,6 +2,8 @@ package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; -+import co.aikar.timings.TimingHistory; // Paper -+import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -153,7 +155,6 @@ import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.storage.WorldDataServer; - import org.bukkit.Bukkit; - import org.bukkit.WeatherType; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.craftbukkit.util.WorldUUID; - import org.bukkit.event.entity.CreatureSpawnEvent; -@@ -209,10 +210,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - this.nextTickListBlock = new TickListServer<>(this, (block) -> { - return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings - this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a); -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -442,17 +443,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.Q(); - this.b(); - gameprofilerfiller.exitEnter("chunkSource"); -+ this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkProvider().tick(booleansupplier); -+ this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("tickPending"); -- timings.doTickPending.startTiming(); // Spigot -+ timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebugWorld()) { - this.nextTickListBlock.b(); - this.nextTickListFluid.b(); - } -- timings.doTickPending.stopTiming(); // Spigot -+ timings.scheduledBlocks.stopTiming(); // Paper - - gameprofilerfiller.exitEnter("raid"); -+ this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -+ this.timings.raids.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("blockEvents"); - timings.doSounds.startTiming(); // Spigot - this.ak(); -@@ -624,6 +629,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("tickBlocks"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - if (i > 0) { - ChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; -@@ -655,7 +661,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - } -- -+ timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.exit(); - } - -@@ -753,14 +759,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { - this.chunkCheck(entity); - } else { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); - entity.lastYaw = entity.yaw; - entity.lastPitch = entity.pitch; -@@ -787,7 +801,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } - } -@@ -865,6 +879,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - if (!flag1) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper - if (iprogressupdate != null) { - iprogressupdate.a(new ChatMessage("menu.savingLevel")); - } -@@ -874,7 +889,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - iprogressupdate.c(new ChatMessage("menu.savingChunks")); - } - -+ timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flag); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ } // Paper - } - - // CraftBukkit start - moved from MinecraftServer.saveChunks -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index bc9321e77c6b2f9ac17821413fa1357da2f26b05..4ed497ee04d9e9116e1f7d90bf975aeadd24aa93 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -211,6 +211,7 @@ import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.SmithingInventory; - import org.bukkit.util.NumberConversions; -+import co.aikar.timings.MinecraftTimings; // Paper - // CraftBukkit end - - public class PlayerConnection implements PacketListenerPlayIn { -@@ -293,7 +294,6 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -369,7 +369,6 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 - this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); - } -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot - - } - -@@ -1916,7 +1915,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - private void handleCommand(String s) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.startTiming(); // Paper - // CraftBukkit start - whole method - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getName() + " issued server command: " + s); -@@ -1927,7 +1926,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - -@@ -1940,7 +1939,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - } - // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5d1bbc42b4d65aa735570c53e4e6bc9e08899749..c601a5c577e438a3fa8dd4c5f36dbe9494b03d52 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import co.aikar.timings.MinecraftTimings; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1022,10 +1023,11 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } -- -+ MinecraftTimings.savePlayers.stopTiming(); // Paper - } - - public WhiteList getWhitelist() { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2bea2f4748cadf479dd4f89792ef5ffdd88e9cab..306f6c0db2333cce5dfc4bf1c09bfef05119a28b 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -116,7 +116,6 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; - import org.bukkit.entity.Hanging; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Vehicle; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.bukkit.event.entity.EntityCombustByEntityEvent; - import org.bukkit.event.hanging.HangingBreakByEntityEvent; - import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -248,7 +247,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -617,7 +615,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void move(EnumMoveType enummovetype, Vec3D vec3d) { -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot - if (this.noclip) { - this.a(this.getBoundingBox().c(vec3d)); - this.recalcPosition(); -@@ -753,7 +750,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - this.world.getMethodProfiler().exit(); - } -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot - } - - protected BlockPosition ap() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index c76ab1e6a54399eddae1ef2a595778385cd50026..661c3e2f12de36167bff149a3d979c4581402cbc 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -135,7 +135,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -2458,7 +2458,6 @@ public abstract class EntityLiving extends Entity { - - @Override - public void tick() { -- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot - super.tick(); - this.t(); - this.v(); -@@ -2507,9 +2506,7 @@ public abstract class EntityLiving extends Entity { - } - } - -- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot - this.movementTick(); -- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot - double d0 = this.locX() - this.lastX; - double d1 = this.locZ() - this.lastZ; - float f = (float) (d0 * d0 + d1 * d1); -@@ -2589,8 +2586,6 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.pitch = 0.0F; - } -- -- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot - } - - public void updateEquipment() { -@@ -2772,7 +2767,6 @@ public abstract class EntityLiving extends Entity { - - this.setMot(d4, d5, d6); - this.world.getMethodProfiler().enter("ai"); -- SpigotTimings.timerEntityAI.startTiming(); // Spigot - if (this.isFrozen()) { - this.jumping = false; - this.aR = 0.0F; -@@ -2782,7 +2776,6 @@ public abstract class EntityLiving extends Entity { - this.doTick(); - this.world.getMethodProfiler().exit(); - } -- SpigotTimings.timerEntityAI.stopTiming(); // Spigot - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("jump"); -@@ -2817,9 +2810,9 @@ public abstract class EntityLiving extends Entity { - this.r(); - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - -- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper - this.g(new Vec3D((double) this.aR, (double) this.aS, (double) this.aT)); -- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("push"); - if (this.bf > 0) { -@@ -2827,9 +2820,7 @@ public abstract class EntityLiving extends Entity { - this.a(axisalignedbb, this.getBoundingBox()); - } - -- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot - this.collideNearby(); -- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot - this.world.getMethodProfiler().exit(); - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index dc92b112770955f9fa49a408262da2e5bbc4bf98..a707ba365e25ea15e2e9d22110696b6136aa0c6f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -281,7 +281,9 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } - -- public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { -+ public final String id; -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { this(entitytypes_b, enumcreaturetype, flag, flag1, flag2, flag3, immutableset, entitysize, i, j, "custom"); } // Paper - old signature -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j, String id) { // Paper - add id - this.bf = entitytypes_b; - this.bg = enumcreaturetype; - this.bl = flag3; -@@ -292,6 +294,14 @@ public class EntityTypes { - this.br = entitysize; - this.bm = i; - this.bn = j; -+ -+ // Paper start - timings -+ this.id = id; -+ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); -+ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); -+ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); -+ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); -+ // Paper end - } - - @Nullable -@@ -512,6 +522,12 @@ public class EntityTypes { - return this.bn; - } - -+ // Paper start - timings -+ public final co.aikar.timings.Timing tickTimer; -+ public final co.aikar.timings.Timing inactiveTickTimer; -+ public final co.aikar.timings.Timing passengerTickTimer; -+ public final co.aikar.timings.Timing passengerInactiveTickTimer; -+ // Paper end - public boolean isDeltaTracking() { - return this != EntityTypes.PLAYER && this != EntityTypes.LLAMA_SPIT && this != EntityTypes.WITHER && this != EntityTypes.BAT && this != EntityTypes.ITEM_FRAME && this != EntityTypes.LEASH_KNOT && this != EntityTypes.PAINTING && this != EntityTypes.END_CRYSTAL && this != EntityTypes.EVOKER_FANGS; - } -@@ -599,7 +615,7 @@ public class EntityTypes { - SystemUtils.a(DataConverterTypes.ENTITY_TREE, s); - } - -- return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); -+ return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i, s); // Paper - add id - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index e7296b8684d6d8c2f256d4a9da87f408a198c331..c221e5caf518b8c588390e438346fa58fa8c5a38 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -38,12 +38,17 @@ public class TickListServer implements TickList { - private final List> g = Lists.newArrayList(); - private final Consumer> h; - -- public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer) { -+ public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper - this.a = predicate; - this.b = function; - this.e = worldserver; - this.h = consumer; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); - } -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ // Paper end - - public void b() { - int i = this.nextTickList.size(); -@@ -66,6 +71,7 @@ public class TickListServer implements TickList { - - this.e.getMethodProfiler().enter("cleaning"); - -+ this.timingCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; - - while (i > 0 && iterator.hasNext()) { -@@ -81,7 +87,9 @@ public class TickListServer implements TickList { - --i; - } - } -+ this.timingCleanup.stopTiming(); // Paper - -+ this.timingTicking.startTiming(); // Paper - this.e.getMethodProfiler().exitEnter("ticking"); - - while ((nextticklistentry = (NextTickListEntry) this.f.poll()) != null) { -@@ -101,6 +109,7 @@ public class TickListServer implements TickList { - } - } - -+ this.timingTicking.stopTiming(); // Paper - this.e.getMethodProfiler().exit(); - this.g.clear(); - this.f.clear(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0cbebc2095489c240fecd3fd32f5373be2a3d684..1b03c69fa7ffeca4083470a179e18be828b0a957 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -70,7 +70,6 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.border.IWorldBorderListener; - import org.bukkit.Bukkit; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -@@ -132,7 +131,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - -- public final SpigotTimings.WorldTimingsHandler timings; // Spigot -+ public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -217,7 +216,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void c(WorldBorder worldborder, double d0) {} - }); - // CraftBukkit end -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } -@@ -797,15 +796,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - timings.tileEntityPending.stopTiming(); // Spigot -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper - gameprofilerfiller.exit(); - spigotConfig.currentPrimedTnt = 0; // Spigot - } - - public void a(Consumer consumer, Entity entity) { - try { -- SpigotTimings.tickEntityTimer.startTiming(); // Spigot - consumer.accept(entity); -- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index bab55395ba92d0f3788e798ae0e154d62c4ec2fa..d285c4e3d9f938973bf7fb904680044b414e6236 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -61,6 +61,15 @@ public class Block extends BlockBase implements IMaterial { - }); - protected final BlockStateList blockStateList; - private IBlockData blockData; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - @Nullable - private String name; - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 75110c41af3e0097aef65091a2497dd87d08b4b2..9ebd91e1309938f81583eb3d4dd97fd39bcc930a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -23,10 +23,12 @@ import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot -+ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper - // CraftBukkit start - data containers - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - public CraftPersistentDataContainer persistentDataContainer; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index acdcece38a4b30d6c89eb4342918ae8997db9f0b..ac576d268b23148089d404cb22d8c2f9d1a79d6e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -733,6 +733,7 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); - - if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(world.getSeed()); -@@ -752,6 +753,7 @@ public class Chunk implements IChunkAccess { - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -+ } // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 27703b807735d52313b93f8f606aa263571525d2..f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk.storage; - -+import co.aikar.timings.Timings; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; -@@ -446,7 +447,6 @@ public class ChunkRegionLoader { - private static void loadEntities(NBTTagCompound nbttagcompound, Chunk chunk) { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); -@@ -458,8 +458,6 @@ public class ChunkRegionLoader { - chunk.d(true); - } - -- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot -- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - NBTTagList nbttaglist1 = nbttagcompound.getList("TileEntities", 10); - - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -477,8 +475,6 @@ public class ChunkRegionLoader { - } - } - } -- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot -- - } - - private static NBTTagCompound a(ChunkCoordIntPair chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7b77bbf15e59c5a993fb1683c27e41425419e138..ce68a6cf845af640e03819c44860590655f74cb1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2077,12 +2077,31 @@ public final class CraftServer implements Server { - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { - -+ @Deprecated - @Override - public YamlConfiguration getConfig() - { - return org.spigotmc.SpigotConfig.config; - } - -+ @Override -+ public YamlConfiguration getBukkitConfig() -+ { -+ return configuration; -+ } -+ -+ @Override -+ public YamlConfiguration getSpigotConfig() -+ { -+ return org.spigotmc.SpigotConfig.config; -+ } -+ -+ @Override -+ public YamlConfiguration getPaperConfig() -+ { -+ return com.destroystokyo.paper.PaperConfig.config; -+ } -+ - @Override - public void restart() { - org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -index ebf2c62e9ea126577a6cbcbbeb3f3aba259a1f63..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -@@ -1,163 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.World; --import net.minecraft.world.level.block.entity.TileEntity; --import net.minecraft.world.level.storage.WorldDataServer; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(World server) { -- String name = ((WorldDataServer) server.worldData).getName() + " - "; -- -- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c3a06eabbff3c37c88b1f09fe4bf806418e3a4d4..b51a874e4665f977a154792e6216e03e04525f39 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1808,6 +1808,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - packet.components = components; - getHandle().playerConnection.sendPacket(packet); - } -+ -+ // Paper start -+ @Override -+ public int getPing() -+ { -+ return getHandle().ping; -+ } -+ // Paper end - }; - - public Player.Spigot spigot() -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 4bf48f77f3f7cd62a91590543f5af441c8268029..ffe9cc1011226d604dc5499e7692e9a9a5132b72 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.scheduler; - -+import co.aikar.timings.MinecraftTimings; // Paper - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import java.util.ArrayList; - import java.util.Comparator; -@@ -179,7 +180,8 @@ public class CraftScheduler implements BukkitScheduler { - } - - public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -- final CraftTask task = new CraftTask(run, nextId(), taskName); -+ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); -+ task.internal = true; - return handle(task, delay); - } - -@@ -260,7 +262,7 @@ public class CraftScheduler implements BukkitScheduler { - } - return false; - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -295,7 +297,7 @@ public class CraftScheduler implements BukkitScheduler { - } - } - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -402,9 +404,7 @@ public class CraftScheduler implements BukkitScheduler { - if (task.isSync()) { - currentTask = task; - try { -- task.timings.startTiming(); // Spigot - task.run(); -- task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { - // Paper start - String msg = String.format( -@@ -438,8 +438,10 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); - } - } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); - temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); - } - -@@ -472,6 +474,7 @@ public class CraftScheduler implements BukkitScheduler { - } - - private void parsePending() { -+ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -490,6 +493,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -+ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 09aa6809c5400ce8548ac902908b750ce7c964ec..3c96807e97657502849093e4371e9fef3584a346 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -1,12 +1,15 @@ - package org.bukkit.craftbukkit.scheduler; - - import java.util.function.Consumer; -+ -+import co.aikar.timings.NullTimingHandler; - import org.bukkit.Bukkit; - import org.bukkit.plugin.Plugin; - import org.bukkit.scheduler.BukkitTask; - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public class CraftTask implements BukkitTask, Runnable { // Spigot - -@@ -26,12 +29,12 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - */ - private volatile long period; - private long nextRun; -- private final Runnable rTask; -- private final Consumer cTask; -+ public final Runnable rTask; // Paper -+ public final Consumer cTask; // Paper -+ public Timing timings; // Paper - private final Plugin plugin; - private final int id; - -- final CustomTimingsHandler timings; // Spigot - CraftTask() { - this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -@@ -51,7 +54,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.id = id; - this.period = CraftTask.NO_REPEATING; - this.taskName = taskName; -- this.timings = null; // Will be changed in later patch -+ this.timings = MinecraftTimings.getInternalTaskName(taskName); - } - // Paper end - -@@ -72,7 +75,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - } - this.id = id; - this.period = period; -- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot -+ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper - } - - @Override -@@ -92,11 +95,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -+ try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); - } else { - cTask.accept(this); - } -+ } // Paper - } - - long getPeriod() { -@@ -123,7 +128,7 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.next = next; - } - -- Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); - } - -@@ -147,9 +152,4 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - return true; - } - -- // Spigot start -- public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); -- } -- // Spigot end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae0027da2e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -@@ -5,6 +5,7 @@ import org.bukkit.util.CachedServerIcon; - public class CraftIconCache implements CachedServerIcon { - public final String value; - -+ public String getData() { return value; } // Paper - public CraftIconCache(final String value) { - this.value = value; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 972840fd32cd4b6cb73b7f97d06dcd5699c28ba4..65131f0977fa55c4761c34ce52720170feb61a72 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -158,6 +158,12 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } - // ======================================================================== -+ // Paper start -+ @Override -+ public void reportTimings() { -+ co.aikar.timings.TimingsExport.reportTimings(); -+ } -+ // Paper end - - public static byte toLegacyData(IBlockData data) { - return CraftLegacy.toLegacyData(data); -@@ -332,6 +338,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - return clazz; - } - -+ // Paper start -+ @Override -+ public String getTimingsServerName() { -+ return com.destroystokyo.paper.PaperConfig.timingsServerName; -+ } -+ // Paper end -+ - /** - * This helper class represents the different NBT Tags. - *

-diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 44a7323ffbdf91f8e0672e0fadf0d3d26ed9a290..69c5d4e51ebf747d931fadc819973e36f001f5bc 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -29,7 +29,7 @@ import net.minecraft.world.entity.raid.EntityRaider; - import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; --import org.bukkit.craftbukkit.SpigotTimings; -+import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -73,8 +73,8 @@ public class ActivationRange - /** - * These entities are excluded from Activation range checks. - * -- * @param entity -- * @param config -+ * @param entity Entity to initialize -+ * @param config Spigot config to determine ranges - * @return boolean If it should always tick. - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -109,7 +109,7 @@ public class ActivationRange - */ - public static void activateEntities(World world) - { -- SpigotTimings.entityActivationCheckTimer.startTiming(); -+ MinecraftTimings.entityActivationCheckTimer.startTiming(); - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -146,7 +146,7 @@ public class ActivationRange - } - } - } -- SpigotTimings.entityActivationCheckTimer.stopTiming(); -+ MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } - - /** -@@ -243,10 +243,8 @@ public class ActivationRange - */ - public static boolean checkIfActive(Entity entity) - { -- SpigotTimings.checkIfActiveTimer.startTiming(); - // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof EntityFireworks ) { -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return true; - } - -@@ -270,7 +268,6 @@ public class ActivationRange - { - isActive = false; - } -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return isActive; - } - } diff --git a/Spigot-Server-Patches/0010-Adventure.patch b/Spigot-Server-Patches/0010-Adventure.patch deleted file mode 100644 index 1067478faa6d..000000000000 --- a/Spigot-Server-Patches/0010-Adventure.patch +++ /dev/null @@ -1,3237 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:54:03 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -217,4 +217,9 @@ public class PaperConfig { - " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + - " - Server Name: " + timingsServerName); - } -+ -+ public static boolean useDisplayNameInQuit = false; -+ private static void useDisplayNameInQuit() { -+ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89597b4a3064c3c6001c7e927a848ee73a1b1fd9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -@@ -0,0 +1,77 @@ -+package io.papermc.paper.adventure; -+ -+import com.google.gson.JsonElement; -+import com.google.gson.JsonSerializationContext; -+import com.google.gson.JsonSerializer; -+import java.lang.reflect.Type; -+import java.util.List; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; -+import net.minecraft.network.chat.ChatModifier; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.network.chat.IChatMutableComponent; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class AdventureComponent implements IChatBaseComponent { -+ final Component wrapped; -+ private @MonotonicNonNull IChatBaseComponent converted; -+ -+ public AdventureComponent(final Component wrapped) { -+ this.wrapped = wrapped; -+ } -+ -+ public IChatBaseComponent deepConverted() { -+ IChatBaseComponent converted = this.converted; -+ if (converted == null) { -+ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); -+ this.converted = converted; -+ } -+ return converted; -+ } -+ -+ public @Nullable IChatBaseComponent deepConvertedIfPresent() { -+ return this.converted; -+ } -+ -+ @Override -+ public ChatModifier getChatModifier() { -+ return this.deepConverted().getChatModifier(); -+ } -+ -+ @Override -+ public String getText() { -+ if (this.wrapped instanceof TextComponent) { -+ return ((TextComponent) this.wrapped).content(); -+ } else { -+ return this.deepConverted().getText(); -+ } -+ } -+ -+ @Override -+ public String getString() { -+ return PaperAdventure.PLAIN.serialize(this.wrapped); -+ } -+ -+ @Override -+ public List getSiblings() { -+ return this.deepConverted().getSiblings(); -+ } -+ -+ @Override -+ public IChatMutableComponent g() { -+ return this.deepConverted().g(); -+ } -+ -+ @Override -+ public IChatMutableComponent mutableCopy() { -+ return this.deepConverted().mutableCopy(); -+ } -+ -+ public static class Serializer implements JsonSerializer { -+ @Override -+ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { -+ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); -+ } -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0cb9368dcffe08a1ab004c6e2803b43eb655ac43 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +1,215 @@ -+package io.papermc.paper.adventure; -+ -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.event.player.AbstractChatEvent; -+import io.papermc.paper.event.player.AsyncChatEvent; -+import io.papermc.paper.event.player.ChatEvent; -+import java.util.Set; -+import java.util.concurrent.ExecutionException; -+import java.util.function.Consumer; -+import java.util.regex.Pattern; -+ -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextReplacementConfig; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.minecraft.network.chat.ChatMessageType; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.AsyncPlayerChatEvent; -+import org.bukkit.event.player.PlayerChatEvent; -+ -+public final class ChatProcessor { -+ // <-- copied from adventure-text-serializer-legacy -+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); -+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); -+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() -+ .match(DEFAULT_URL_PATTERN) -+ .replacement(url -> { -+ String clickUrl = url.content(); -+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { -+ clickUrl = "http://" + clickUrl; -+ } -+ return url.clickEvent(ClickEvent.openUrl(clickUrl)); -+ }) -+ .build(); -+ // copied from adventure-text-serializer-legacy --> -+ final MinecraftServer server; -+ final EntityPlayer player; -+ final String message; -+ final boolean async; -+ -+ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) { -+ this.server = server; -+ this.player = player; -+ this.message = message; -+ this.async = async; -+ } -+ -+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) -+ public void process() { -+ this.processingLegacyFirst( -+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) -+ event -> { -+ this.processModern( -+ legacyComposer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent -+ event -> { -+ this.processModern( -+ legacyComposer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // no legacy events called, all nice and fresh! -+ () -> { -+ this.processModern( -+ ChatComposer.DEFAULT, -+ new LazyPlayerSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), -+ false -+ ); -+ } -+ ); -+ } -+ -+ @SuppressWarnings("deprecation") -+ private void processingLegacyFirst( -+ final Consumer continueAfterAsync, -+ final Consumer continueAfterAsyncAndSync, -+ final Runnable modernOnly -+ ) { -+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); -+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); -+ if (listenersOnAsyncEvent || listenersOnSyncEvent) { -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); -+ post(ae); -+ if (listenersOnSyncEvent) { -+ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ post(se); -+ return null; -+ } -+ }); -+ continueAfterAsyncAndSync.accept(se); -+ } else { -+ continueAfterAsync.accept(ae); -+ } -+ } else { -+ modernOnly.run(); -+ } -+ } -+ -+ private void processModern(final ChatComposer composer, final Set recipients, final Component message, final boolean cancelled) { -+ final AsyncChatEvent ae = this.createAsync(composer, recipients, message); -+ ae.setCancelled(cancelled); // propagate cancelled state -+ post(ae); -+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); -+ if (listenersOnSyncEvent) { -+ this.continueWithSyncFromWhereAsyncLeftOff(ae); -+ } else { -+ this.complete(ae); -+ } -+ } -+ -+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.composer(), ae.recipients(), ae.message()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ post(se); -+ ChatProcessor.this.complete(se); -+ return null; -+ } -+ }); -+ } -+ -+ private void complete(final AbstractChatEvent event) { -+ if (event.isCancelled()) { -+ return; -+ } -+ -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ -+ final Component message = event.composer().composeChat( -+ event.getPlayer(), -+ displayName(player), -+ event.message() -+ ); -+ -+ this.server.console.sendMessage(message); -+ -+ if (((LazyPlayerSet) event.recipients()).isLazy()) { -+ final IChatBaseComponent vanilla = PaperAdventure.asVanilla(message); -+ for (final EntityPlayer recipient : this.server.getPlayerList().players) { -+ recipient.sendMessage(vanilla, ChatMessageType.CHAT, this.player.getUniqueID()); -+ } -+ } else { -+ for (final Player recipient : event.recipients()) { -+ recipient.sendMessage(player, message, MessageType.CHAT); -+ } -+ } -+ } -+ -+ private AsyncChatEvent createAsync(final ChatComposer composer, final Set recipients, final Component message) { -+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, composer, message); -+ } -+ -+ private ChatEvent createSync(final ChatComposer composer, final Set recipients, final Component message) { -+ return new ChatEvent(this.player.getBukkitEntity(), recipients, composer, message); -+ } -+ -+ private static String legacyDisplayName(final CraftPlayer player) { -+ return player.getDisplayName(); -+ } -+ -+ private static Component displayName(final CraftPlayer player) { -+ return player.displayName(); -+ } -+ -+ private static ChatComposer legacyComposer(final String format) { -+ return (player, displayName, message) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); -+ } -+ -+ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { -+ if (this.async) { -+ this.server.processQueue.add(waitable); -+ } else { -+ waitable.run(); -+ } -+ try { -+ waitable.get(); -+ } catch (final InterruptedException e) { -+ Thread.currentThread().interrupt(); // tag, you're it -+ } catch (final ExecutionException e) { -+ throw new RuntimeException("Exception processing chat", e.getCause()); -+ } -+ } -+ -+ private static void post(final Event event) { -+ Bukkit.getPluginManager().callEvent(event); -+ } -+ -+ private static boolean anyListeners(final HandlerList handlers) { -+ return handlers.getRegisteredListeners().length > 0; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b1d9d6276eb577ed3c66df1f89b3266d2c48eaf2 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -@@ -0,0 +1,22 @@ -+package io.papermc.paper.adventure; -+ -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public final class DisplayNames { -+ private DisplayNames() { -+ } -+ -+ public static String getLegacy(final CraftPlayer player) { -+ return getLegacy(player.getHandle()); -+ } -+ -+ public static String getLegacy(final EntityPlayer player) { -+ final String legacy = player.displayName; -+ if (legacy != null) { -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..caa9708f321f04cd02534161231c05999bda4acd ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -@@ -0,0 +1,88 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import java.io.IOException; -+import java.util.UUID; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.event.HoverEvent; -+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTTagCompound; -+ -+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { -+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); -+ private static final Codec SNBT_CODEC = Codec.of(MojangsonParser::parse, NBTBase::toString); -+ -+ static final String ITEM_TYPE = "id"; -+ static final String ITEM_COUNT = "Count"; -+ static final String ITEM_TAG = "tag"; -+ -+ static final String ENTITY_NAME = "name"; -+ static final String ENTITY_TYPE = "type"; -+ static final String ENTITY_ID = "id"; -+ -+ NBTLegacyHoverEventSerializer() { -+ } -+ -+ @Override -+ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ final NBTTagCompound tag = contents.getCompound(ITEM_TAG); -+ return HoverEvent.ShowItem.of( -+ Key.key(contents.getString(ITEM_TYPE)), -+ contents.hasKey(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, -+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ return HoverEvent.ShowEntity.of( -+ Key.key(contents.getString(ENTITY_TYPE)), -+ UUID.fromString(contents.getString(ENTITY_ID)), -+ componentCodec.decode(contents.getString(ENTITY_NAME)) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ITEM_TYPE, input.item().asString()); -+ tag.setByte(ITEM_COUNT, (byte) input.count()); -+ if (input.nbt() != null) { -+ try { -+ tag.set(ITEM_TAG, input.nbt().get(SNBT_CODEC)); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+ -+ @Override -+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ENTITY_ID, input.id().toString()); -+ tag.setString(ENTITY_TYPE, input.type().asString()); -+ if (input.name() != null) { -+ tag.setString(ENTITY_NAME, componentCodec.encode(input.name())); -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c60457e9240c33a4721b82a00cef081fb320c8a7 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +1,344 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import io.netty.util.AttributeKey; -+import java.io.IOException; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Locale; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.inventory.Book; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.sound.Sound; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TranslatableComponent; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.translation.GlobalTranslator; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.EnumChatFormat; -+import net.minecraft.locale.LocaleLanguage; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.world.BossBattle; -+import net.minecraft.world.item.ItemStack; -+import org.bukkit.ChatColor; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class PaperAdventure { -+ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); -+ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); -+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() -+ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { -+ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); -+ -+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); -+ final List args = translatable.args(); -+ int argPosition = 0; -+ int lastIdx = 0; -+ while (matcher.find()) { -+ // append prior -+ if (lastIdx < matcher.start()) { -+ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); -+ } -+ lastIdx = matcher.end(); -+ -+ final @Nullable String argIdx = matcher.group(1); -+ // calculate argument position -+ if (argIdx != null) { -+ try { -+ final int idx = Integer.parseInt(argIdx) - 1; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } catch (final NumberFormatException ex) { -+ // ignore, drop the format placeholder -+ } -+ } else { -+ final int idx = argPosition++; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } -+ } -+ -+ // append tail -+ if (lastIdx < translated.length()) { -+ consumer.accept(Component.text(translated.substring(lastIdx))); -+ } -+ }) -+ .build(); -+ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); -+ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); -+ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .build(); -+ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .downsampleColors() -+ .build(); -+ private static final Codec NBT_CODEC = new Codec() { -+ @Override -+ public @NonNull NBTTagCompound decode(final @NonNull String encoded) throws IOException { -+ try { -+ return MojangsonParser.parse(encoded); -+ } catch (final CommandSyntaxException e) { -+ throw new IOException(e); -+ } -+ } -+ -+ @Override -+ public @NonNull String encode(final @NonNull NBTTagCompound decoded) { -+ return decoded.toString(); -+ } -+ }; -+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); -+ -+ private PaperAdventure() { -+ } -+ -+ // Key -+ -+ public static MinecraftKey asVanilla(final Key key) { -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ public static MinecraftKey asVanillaNullable(final Key key) { -+ if (key == null) { -+ return null; -+ } -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ // Component -+ -+ public static Component asAdventure(final IChatBaseComponent component) { -+ return GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(component), Component.class); -+ } -+ -+ public static ArrayList asAdventure(final List vanillas) { -+ final ArrayList adventures = new ArrayList<>(vanillas.size()); -+ for (final IChatBaseComponent vanilla : vanillas) { -+ adventures.add(asAdventure(vanilla)); -+ } -+ return adventures; -+ } -+ -+ public static ArrayList asAdventureFromJson(final List jsonStrings) { -+ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); -+ for (final String json : jsonStrings) { -+ adventures.add(GsonComponentSerializer.gson().deserialize(json)); -+ } -+ return adventures; -+ } -+ -+ public static List asJson(final List adventures) { -+ final List jsons = new ArrayList<>(adventures.size()); -+ for (final Component component : adventures) { -+ jsons.add(GsonComponentSerializer.gson().serialize(component)); -+ } -+ return jsons; -+ } -+ -+ public static IChatBaseComponent asVanilla(final Component component) { -+ if (true) return new AdventureComponent(component); -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(GSON.serializer().toJsonTree(component)); -+ } -+ -+ public static List asVanilla(final List adventures) { -+ final List vanillas = new ArrayList<>(adventures.size()); -+ for (final Component adventure : adventures) { -+ vanillas.add(asVanilla(adventure)); -+ } -+ return vanillas; -+ } -+ -+ public static String asJsonString(final Component component, final Locale locale) { -+ return GSON.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); -+ } -+ -+ public static String asJsonString(final IChatBaseComponent component, final Locale locale) { -+ if (component instanceof AdventureComponent) { -+ return asJsonString(((AdventureComponent) component).wrapped, locale); -+ } -+ return IChatBaseComponent.ChatSerializer.componentToJson(component); -+ } -+ -+ // thank you for being worse than wet socks, Bukkit -+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { -+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); -+ } -+ -+ // BossBar -+ -+ public static BossBattle.BarColor asVanilla(final BossBar.Color color) { -+ if (color == BossBar.Color.PINK) { -+ return BossBattle.BarColor.PINK; -+ } else if (color == BossBar.Color.BLUE) { -+ return BossBattle.BarColor.BLUE; -+ } else if (color == BossBar.Color.RED) { -+ return BossBattle.BarColor.RED; -+ } else if (color == BossBar.Color.GREEN) { -+ return BossBattle.BarColor.GREEN; -+ } else if (color == BossBar.Color.YELLOW) { -+ return BossBattle.BarColor.YELLOW; -+ } else if (color == BossBar.Color.PURPLE) { -+ return BossBattle.BarColor.PURPLE; -+ } else if (color == BossBar.Color.WHITE) { -+ return BossBattle.BarColor.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBar.Color asAdventure(final BossBattle.BarColor color) { -+ if(color == BossBattle.BarColor.PINK) { -+ return BossBar.Color.PINK; -+ } else if(color == BossBattle.BarColor.BLUE) { -+ return BossBar.Color.BLUE; -+ } else if(color == BossBattle.BarColor.RED) { -+ return BossBar.Color.RED; -+ } else if(color == BossBattle.BarColor.GREEN) { -+ return BossBar.Color.GREEN; -+ } else if(color == BossBattle.BarColor.YELLOW) { -+ return BossBar.Color.YELLOW; -+ } else if(color == BossBattle.BarColor.PURPLE) { -+ return BossBar.Color.PURPLE; -+ } else if(color == BossBattle.BarColor.WHITE) { -+ return BossBar.Color.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBattle.BarStyle asVanilla(final BossBar.Overlay overlay) { -+ if (overlay == BossBar.Overlay.PROGRESS) { -+ return BossBattle.BarStyle.PROGRESS; -+ } else if (overlay == BossBar.Overlay.NOTCHED_6) { -+ return BossBattle.BarStyle.NOTCHED_6; -+ } else if (overlay == BossBar.Overlay.NOTCHED_10) { -+ return BossBattle.BarStyle.NOTCHED_10; -+ } else if (overlay == BossBar.Overlay.NOTCHED_12) { -+ return BossBattle.BarStyle.NOTCHED_12; -+ } else if (overlay == BossBar.Overlay.NOTCHED_20) { -+ return BossBattle.BarStyle.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static BossBar.Overlay asAdventure(final BossBattle.BarStyle overlay) { -+ if (overlay == BossBattle.BarStyle.PROGRESS) { -+ return BossBar.Overlay.PROGRESS; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_6) { -+ return BossBar.Overlay.NOTCHED_6; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_10) { -+ return BossBar.Overlay.NOTCHED_10; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_12) { -+ return BossBar.Overlay.NOTCHED_12; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_20) { -+ return BossBar.Overlay.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { -+ if (value) { -+ bar.addFlag(flag); -+ } else { -+ bar.removeFlag(flag); -+ } -+ } -+ -+ // Book -+ -+ public static ItemStack asItemStack(final Book book, final Locale locale) { -+ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); -+ final NBTTagCompound tag = item.getOrCreateTag(); -+ tag.setString("title", asJsonString(book.title(), locale)); -+ tag.setString("author", asJsonString(book.author(), locale)); -+ final NBTTagList pages = new NBTTagList(); -+ for (final Component page : book.pages()) { -+ pages.add(NBTTagString.create(asJsonString(page, locale))); -+ } -+ tag.set("pages", pages); -+ return item; -+ } -+ -+ // Sounds -+ -+ public static SoundCategory asVanilla(final Sound.Source source) { -+ if (source == Sound.Source.MASTER) { -+ return SoundCategory.MASTER; -+ } else if (source == Sound.Source.MUSIC) { -+ return SoundCategory.MUSIC; -+ } else if (source == Sound.Source.RECORD) { -+ return SoundCategory.RECORDS; -+ } else if (source == Sound.Source.WEATHER) { -+ return SoundCategory.WEATHER; -+ } else if (source == Sound.Source.BLOCK) { -+ return SoundCategory.BLOCKS; -+ } else if (source == Sound.Source.HOSTILE) { -+ return SoundCategory.HOSTILE; -+ } else if (source == Sound.Source.NEUTRAL) { -+ return SoundCategory.NEUTRAL; -+ } else if (source == Sound.Source.PLAYER) { -+ return SoundCategory.PLAYERS; -+ } else if (source == Sound.Source.AMBIENT) { -+ return SoundCategory.AMBIENT; -+ } else if (source == Sound.Source.VOICE) { -+ return SoundCategory.VOICE; -+ } -+ throw new IllegalArgumentException(source.name()); -+ } -+ -+ public static @Nullable SoundCategory asVanillaNullable(final Sound.@Nullable Source source) { -+ if (source == null) { -+ return null; -+ } -+ return asVanilla(source); -+ } -+ -+ // NBT -+ -+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable NBTTagCompound tag) { -+ if (tag == null) { -+ return null; -+ } -+ try { -+ return BinaryTagHolder.encode(tag, NBT_CODEC); -+ } catch (final IOException e) { -+ return null; -+ } -+ } -+ -+ // Colors -+ -+ public static @NonNull TextColor asAdventure(EnumChatFormat minecraftColor) { -+ if (minecraftColor.e() == null) { -+ throw new IllegalArgumentException("Not a valid color"); -+ } -+ return TextColor.color(minecraftColor.e()); -+ } -+ -+ public static @Nullable EnumChatFormat asVanilla(TextColor color) { -+ return EnumChatFormat.getByHexValue(color.value()); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3a4158781e464d9a860bab72ed719a41929c8add ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -@@ -0,0 +1,41 @@ -+package io.papermc.paper.adventure; -+ -+import java.util.Set; -+import java.util.function.Consumer; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.text.Component; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; -+ -+ public VanillaBossBarListener(final Consumer action) { -+ this.action = action; -+ } -+ -+ @Override -+ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_NAME); -+ } -+ -+ @Override -+ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PCT); -+ } -+ -+ @Override -+ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..625b57a4274d6348a85897b92ff07fee7ae3a7ab ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -@@ -0,0 +1,20 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.serializer.ComponentSerializer; -+import net.minecraft.network.chat.IChatBaseComponent; -+ -+final class WrapperAwareSerializer implements ComponentSerializer { -+ @Override -+ public Component deserialize(final IChatBaseComponent input) { -+ if (input instanceof AdventureComponent) { -+ return ((AdventureComponent) input).wrapped; -+ } -+ return PaperAdventure.GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(input), Component.class); -+ } -+ -+ @Override -+ public IChatBaseComponent serialize(final Component component) { -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); -+ } -+} -diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b3e26b9ecca7055760d05975d36c9ae74e0d7d4b ---- /dev/null -+++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -@@ -0,0 +1,36 @@ -+package net.kyori.adventure.bossbar; -+ -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.adventure.VanillaBossBarListener; -+import net.minecraft.server.level.BossBattleServer; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public abstract class HackyBossBarPlatformBridge { -+ public BossBattleServer vanilla$bar; -+ private VanillaBossBarListener vanilla$listener; -+ -+ public final void paper$playerShow(final CraftPlayer player) { -+ if (this.vanilla$bar == null) { -+ final BossBar $this = (BossBar) this; -+ this.vanilla$bar = new BossBattleServer( -+ PaperAdventure.asVanilla($this.name()), -+ PaperAdventure.asVanilla($this.color()), -+ PaperAdventure.asVanilla($this.overlay()) -+ ); -+ this.vanilla$bar.adventure = $this; -+ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::sendUpdate); -+ $this.addListener(this.vanilla$listener); -+ } -+ this.vanilla$bar.addPlayer(player.getHandle()); -+ } -+ -+ public final void paper$playerHide(final CraftPlayer player) { -+ if (this.vanilla$bar != null) { -+ this.vanilla$bar.removePlayer(player.getHandle()); -+ if (this.vanilla$bar.getPlayers().isEmpty()) { -+ ((BossBar) this).removeListener(this.vanilla$listener); -+ this.vanilla$bar = null; -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/EnumChatFormat.java b/src/main/java/net/minecraft/EnumChatFormat.java -index 75e38f05c10713f773a8763100dfc0777521dba6..cd93f99e939438c572a4258d299a6038ebfc60a8 100644 ---- a/src/main/java/net/minecraft/EnumChatFormat.java -+++ b/src/main/java/net/minecraft/EnumChatFormat.java -@@ -61,6 +61,7 @@ public enum EnumChatFormat { - return !this.A && this != EnumChatFormat.RESET; - } - -+ @Nullable public Integer getHexValue() { return this.e(); } // Paper - OBFHELPER - @Nullable - public Integer e() { - return this.D; -@@ -84,6 +85,18 @@ public enum EnumChatFormat { - return s == null ? null : (EnumChatFormat) EnumChatFormat.w.get(c(s)); - } - -+ // Paper start -+ @Nullable public static EnumChatFormat getByHexValue(int i) { -+ for (EnumChatFormat value : values()) { -+ if (value.getHexValue() != null && value.getHexValue() == i) { -+ return value; -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Nullable - public static EnumChatFormat a(int i) { - if (i < 0) { -diff --git a/src/main/java/net/minecraft/nbt/NBTTagString.java b/src/main/java/net/minecraft/nbt/NBTTagString.java -index e26ef49d9dde8ed0fb4267b48cb597563967f313..0e41fdb6ba711fbd2240d62e2030b3a12e14c8d6 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagString.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagString.java -@@ -43,6 +43,7 @@ public class NBTTagString implements NBTBase { - this.data = s; - } - -+ public static NBTTagString create(final String value) { return a(value); } // Paper - OBFHELPER - public static NBTTagString a(String s) { - return s.isEmpty() ? NBTTagString.b : new NBTTagString(s); - } -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5413bf93f7f0f4491fca1f07c47a925fdace7751..5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -10,6 +10,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.handler.codec.DecoderException; - import io.netty.handler.codec.EncoderException; - import io.netty.util.ByteProcessor; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.DataInput; - import java.io.DataOutput; - import java.io.IOException; -@@ -44,6 +45,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit - public class PacketDataSerializer extends ByteBuf { - - private final ByteBuf a; -+ public java.util.Locale adventure$locale; // Paper - - public PacketDataSerializer(ByteBuf bytebuf) { - this.a = bytebuf; -@@ -165,8 +167,15 @@ public class PacketDataSerializer extends ByteBuf { - return IChatBaseComponent.ChatSerializer.a(this.e(262144)); - } - -+ // Paper start -+ public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { -+ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); -+ } -+ // Paper end -+ - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -- return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); -+ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment -+ return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper - } - - public > T a(Class oclass) { -@@ -349,6 +358,7 @@ public class PacketDataSerializer extends ByteBuf { - return this.a(s, 32767); - } - -+ public PacketDataSerializer writeUtf(final String string, final int maxLength) { return this.a(string, maxLength); } // Paper - OBFHELPER - public PacketDataSerializer a(String s, int i) { - byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index dc8cc8d6c00176c8562086282f726dc1b24b2c65..2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -3,6 +3,7 @@ package net.minecraft.network; - import io.netty.buffer.ByteBuf; - import io.netty.channel.ChannelHandlerContext; - import io.netty.handler.codec.MessageToByteEncoder; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.IOException; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -@@ -37,6 +38,7 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw new IOException("Can't serialize unregistered packet"); - } else { - PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); -+ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - - packetdataserializer.d(integer); - -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index 85140d961722e86abfe7006a0ad752751e73c721..e96fa348a37a39c381b6659f612232933686c2a7 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.chat; - -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; - import com.google.gson.JsonArray; -@@ -111,6 +112,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { - - private IChatBaseComponent a; -+ public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot - private ChatMessageType b; - private UUID c; -@@ -32,6 +33,11 @@ public class PacketPlayOutChat implements Packet { - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -+ // Paper start -+ if (this.adventure$message != null) { -+ packetdataserializer.writeComponent(this.adventure$message); -+ } else -+ // Paper end - // Spigot start - if (components != null) { - packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -index 0268b8e6595ee919bcd55a74ba872a2b7d2a17d8..4ff73a4fc5e8a8739e57d2bac65076812cbe5132 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -@@ -9,6 +9,10 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet { - - private PacketPlayOutTitle.EnumTitleAction a; - private IChatBaseComponent b; -+ public net.kyori.adventure.text.Component adventure$text; // Paper - private int c; - private int d; - private int e; -@@ -51,6 +52,11 @@ public class PacketPlayOutTitle implements Packet { - public void b(PacketDataSerializer packetdataserializer) throws IOException { - packetdataserializer.a((Enum) this.a); - if (this.a == PacketPlayOutTitle.EnumTitleAction.TITLE || this.a == PacketPlayOutTitle.EnumTitleAction.SUBTITLE || this.a == PacketPlayOutTitle.EnumTitleAction.ACTIONBAR) { -+ // Paper start -+ if (this.adventure$text != null) { -+ packetdataserializer.writeComponent(this.adventure$text); -+ } else -+ // Paper end - packetdataserializer.a(this.b); - } - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3fa2e077912949f6ca7b14da93c2206215ebcc7e..5ef8b66cf266488df75ce7399596f75273b90761 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -143,6 +143,7 @@ import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.level.block.BlockChest; - import net.minecraft.world.level.dimension.DimensionManager; - import net.minecraft.world.scores.Scoreboard; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import org.bukkit.Bukkit; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -212,6 +213,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - // CraftBukkit start - public String displayName; -+ public net.kyori.adventure.text.Component adventure$displayName; // Paper - public IChatBaseComponent listName; - public org.bukkit.Location compassTarget; - public int newExp = 0; -@@ -242,6 +244,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - // CraftBukkit start - this.displayName = this.getName(); -+ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); - } -@@ -695,23 +698,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - -- String deathmessage = defaultMessage.getString(); -- org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); -+ org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { - this.closeInventory(); - } - -- String deathMessage = event.getDeathMessage(); -+ net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure - -- if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? -- IChatBaseComponent ichatbasecomponent; -- if (deathMessage.equals(deathmessage)) { -- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); -- } else { -- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); -- } -+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? -+ IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - - this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { - if (!future.isSuccess()) { -@@ -1669,6 +1666,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.a(ichatbasecomponent, ChatMessageType.SYSTEM, uuid); - } - -+ public void sendMessage(final IChatBaseComponent message, final ChatMessageType type, final UUID sender) { this.a(message, type, sender); } // Paper - OBFHELPER - public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype, uuid)), (future) -> { - if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { -@@ -1691,6 +1689,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { -@@ -1702,6 +1701,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.server.server.getPluginManager().callEvent(event); - } - this.locale = packetplayinsettings.locale; -+ // Paper start -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); -+ this.playerConnection.networkManager.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); -+ // Paper end - this.clientViewDistance = packetplayinsettings.viewDistance; - // CraftBukkit end - this.bY = packetplayinsettings.d(); -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 16275208954bfc008115aa169c5bfc149f6a4eeb..49a0aefc7f9544b36175fdf3161b255e878952a6 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -37,6 +37,7 @@ import org.apache.logging.log4j.Logger; - - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -301,7 +302,7 @@ public class LoginListener implements PacketLoginInListener { - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); - if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { -- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); -+ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure - } - Waitable waitable = new Waitable() { - @Override -@@ -312,12 +313,12 @@ public class LoginListener implements PacketLoginInListener { - - LoginListener.this.server.processQueue.add(waitable); - if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(event.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return; - } - } else { - if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(asyncEvent.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure - return; - } - } -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index 2a96564c1656d42a74c331a6178e511cd5347a66..d219eda271a71f786808a6958b829fca40a1aaba 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -56,7 +56,7 @@ public class PacketStatusListener implements PacketStatusInListener { - CraftIconCache icon = minecraftServer.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); -+ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 4ed497ee04d9e9116e1f7d90bf975aeadd24aa93..a39f58e0c60b5e3ccc3b725f1f4167d52b230e11 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -159,6 +159,8 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.ChatProcessor; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; -@@ -390,21 +392,24 @@ public class PlayerConnection implements PacketListenerPlayIn { - return this.minecraftServer.a(this.player.getProfile()); - } - -- // CraftBukkit start -- @Deprecated -- public void disconnect(IChatBaseComponent ichatbasecomponent) { -- disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); -+ public void disconnect(String s) { -+ // Paper start -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); - } -- // CraftBukkit end - -- public void disconnect(String s) { -+ public void disconnect(final IChatBaseComponent reason) { -+ this.disconnect(PaperAdventure.asAdventure(reason)); -+ } -+ -+ public void disconnect(net.kyori.adventure.text.Component reason) { -+ // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { - return; - } -- String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; -+ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); -+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure - - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -415,8 +420,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - // Send the possibly modified leave message -- s = event.getReason(); -- final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; -+ final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { -@@ -1632,9 +1636,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - */ - - this.player.p(); -- String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -- if ((quitMessage != null) && (quitMessage.length() > 0)) { -- this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); -+ // Paper start - Adventure -+ net.kyori.adventure.text.Component quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -+ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.minecraftServer.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); -+ // Paper end - } - // CraftBukkit end - ITextFilter itextfilter = this.player.Q(); -@@ -1850,8 +1856,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -- } else { -- Player player = this.getPlayer(); -+ // Paper start -+ } else if (true) { -+ final ChatProcessor cp = new ChatProcessor(this.minecraftServer, this.player, s, async); -+ cp.process(); -+ // Paper end -+ } else if (false) { // Paper -+ Player player = this.getPlayer(); // Paper - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); - this.server.getPluginManager().callEvent(event); - -@@ -2669,21 +2680,20 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - -- // CraftBukkit start -- Player player = this.server.getPlayer(this.player); -- int x = packetplayinupdatesign.b().getX(); -- int y = packetplayinupdatesign.b().getY(); -- int z = packetplayinupdatesign.b().getZ(); -- String[] lines = new String[4]; -+ // CraftBukkit start // Paper start - Adventure -+ List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines[i] = EnumChatFormat.a(new ChatComponentText(EnumChatFormat.a((String) list.get(i))).getString()); -+ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); - } -- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.player), lines); -+ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); -+ for (int i = 0; i < 4; i++) { -+ tileentitysign.a(i, PaperAdventure.asVanilla(event.line(i))); -+ } -+ // Paper end - tileentitysign.isEditable = false; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c601a5c577e438a3fa8dd4c5f36dbe9494b03d52..6ebd4ec781aa215c2b941261250c15c87c223cab 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -8,6 +8,7 @@ import com.mojang.authlib.GameProfile; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; - import java.io.File; - import java.net.SocketAddress; - import java.text.SimpleDateFormat; -@@ -92,6 +93,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - -@@ -255,7 +257,7 @@ public abstract class PlayerList { - } - // CraftBukkit start - chatmessage.a(EnumChatFormat.YELLOW); -- String joinMessage = CraftChatMessage.fromComponent(chatmessage); -+ IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure - - playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); - this.players.add(entityplayer); -@@ -264,19 +266,18 @@ public abstract class PlayerList { - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - - if (!entityplayer.playerConnection.networkManager.isConnected()) { - return; - } - -- joinMessage = playerJoinEvent.getJoinMessage(); -+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - -- if (joinMessage != null && joinMessage.length() > 0) { -- for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { -- server.getPlayerList().sendAll(new PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b)); -- } -+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -+ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -+ server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure - } - // CraftBukkit end - -@@ -473,7 +474,7 @@ public abstract class PlayerList { - - } - -- public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string -+ public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component - WorldServer worldserver = entityplayer.getWorldServer(); - - entityplayer.a(StatisticList.LEAVE_GAME); -@@ -484,7 +485,7 @@ public abstract class PlayerList { - entityplayer.closeInventory(); - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -@@ -545,7 +546,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.getQuitMessage(); // CraftBukkit -+ return playerQuitEvent.quitMessage(); // Paper - Adventure - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -591,10 +592,10 @@ public abstract class PlayerList { - } - - // return chatmessage; -- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot -+ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure - } else if (!this.isWhitelisted(gameprofile)) { - chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -604,17 +605,17 @@ public abstract class PlayerList { - } - - // return chatmessage; -- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); -+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; - if (this.players.size() >= this.maxPlayers && !this.f(gameprofile)) { -- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure - } - } - - cserver.getPluginManager().callEvent(event); - if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { -- loginlistener.disconnect(event.getKickMessage()); -+ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return null; - } - return entity; -@@ -1135,7 +1136,7 @@ public abstract class PlayerList { - public void shutdown() { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { -- player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message -+ player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/BossBattle.java b/src/main/java/net/minecraft/world/BossBattle.java -index f9154b306379c45f15fe55406aaa00351b0471e8..1fb9fea7683075f427edfa411c7747d60928d537 100644 ---- a/src/main/java/net/minecraft/world/BossBattle.java -+++ b/src/main/java/net/minecraft/world/BossBattle.java -@@ -1,5 +1,6 @@ - package net.minecraft.world; - -+import io.papermc.paper.adventure.PaperAdventure; - import java.util.UUID; - import net.minecraft.EnumChatFormat; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -14,6 +15,7 @@ public abstract class BossBattle { - protected boolean e; - protected boolean f; - protected boolean g; -+ public net.kyori.adventure.bossbar.BossBar adventure; // Paper - - public BossBattle(UUID uuid, IChatBaseComponent ichatbasecomponent, BossBattle.BarColor bossbattle_barcolor, BossBattle.BarStyle bossbattle_barstyle) { - this.h = uuid; -@@ -28,61 +30,75 @@ public abstract class BossBattle { - } - - public IChatBaseComponent j() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.name()); // Paper - return this.title; - } - - public void a(IChatBaseComponent ichatbasecomponent) { -+ if (this.adventure != null) this.adventure.name(PaperAdventure.asAdventure(ichatbasecomponent)); // Paper - this.title = ichatbasecomponent; - } - - public float getProgress() { -+ if (this.adventure != null) return this.adventure.progress(); // Paper - return this.b; - } - - public void a(float f) { -+ if (this.adventure != null) this.adventure.progress(f); // Paper - this.b = f; - } - - public BossBattle.BarColor l() { -+ if (this.adventure != null) return PaperAdventure.asVanilla(this.adventure.color()); // Paper - return this.color; - } - - public void a(BossBattle.BarColor bossbattle_barcolor) { -+ if(this.adventure != null) this.adventure.color(PaperAdventure.asAdventure(bossbattle_barcolor)); // Paper - this.color = bossbattle_barcolor; - } - - public BossBattle.BarStyle m() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.overlay()); // Paper - return this.style; - } - - public void a(BossBattle.BarStyle bossbattle_barstyle) { -+ if(this.adventure != null) this.adventure.overlay(PaperAdventure.asAdventure(bossbattle_barstyle)); // Paper - this.style = bossbattle_barstyle; - } - - public boolean isDarkenSky() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN); // Paper - return this.e; - } - - public BossBattle a(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN, flag); // Paper - this.e = flag; - return this; - } - - public boolean isPlayMusic() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC); // Paper - return this.f; - } - - public BossBattle b(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, flag); // Paper - this.f = flag; - return this; - } - - public BossBattle c(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, flag); // Paper - this.g = flag; - return this; - } - - public boolean isCreateFog() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG); // Paper - return this.g; - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 4010152dccc93019f2e7f284d80b92bae0d91c34..f1a780768e3f4bdb43a7ca6d7850befefb71bf57 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -867,6 +867,7 @@ public final class ItemStack { - } - // CraftBukkit end - -+ public IChatBaseComponent displayName() { return this.C(); } // Paper - OBFHELPER - public IChatBaseComponent C() { - IChatMutableComponent ichatmutablecomponent = (new ChatComponentText("")).addSibling(this.getName()); - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 0134bbda9e6fc900b7eefa05442e25539bab3431..b76ef55145336cc8dc4857b79767f5a738ad5144 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -94,6 +94,7 @@ public abstract class Enchantment { - return this.f(); - } - -+ public final IChatBaseComponent getTranslationComponentForLevel(int level) { return this.d(level); } // Paper - OBFHELPER - public IChatBaseComponent d(int i) { - ChatMessage chatmessage = new ChatMessage(this.g()); - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 7ec93ddd7e7c9dc54e3e4dcfe0d1654c0b0a8536..3f057f0bd23bc1c693c8f04ee8acd6626c620008 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -32,6 +32,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.UUID; - - import org.bukkit.craftbukkit.CraftServer; -@@ -473,7 +474,7 @@ public class WorldMap extends PersistentBase { - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - - if (cursor.isVisible()) { -- icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); -+ icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ce68a6cf845af640e03819c44860590655f74cb1..cb470baa3533e4502c13982ef4e03041fac91ce5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -563,8 +563,11 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper start - public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ this.sendMessage(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message)); -+ return this.getOnlinePlayers().size() + 1; -+ // Paper end - } - - public Player getPlayer(final EntityPlayer entity) { -@@ -1310,7 +1313,15 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); - } - -+ // Paper start - @Override -+ public net.kyori.adventure.text.Component shutdownMessage() { -+ String msg = getShutdownMessage(); -+ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; -+ } -+ // Paper end -+ @Override -+ @Deprecated // Paper - public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); - } -@@ -1426,7 +1437,15 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper - public int broadcast(String message, String permission) { -+ // Paper start - Adventure -+ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message, String permission) { -+ // Paper end - Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { - if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -1434,14 +1453,14 @@ public final class CraftServer implements Server { - } - } - -- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); -+ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); - - if (broadcastMessageEvent.isCancelled()) { - return 0; - } - -- message = broadcastMessageEvent.getMessage(); -+ message = broadcastMessageEvent.message(); // Paper - Adventure - - for (CommandSender recipient : recipients) { - recipient.sendMessage(message); -@@ -1667,6 +1686,14 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -1679,13 +1706,28 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, size); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { - Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); - return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); - } - -+ // Paper start - @Override -+ public Merchant createMerchant(net.kyori.adventure.text.Component title) { -+ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); -+ } -+ // Paper end -+ @Override -+ @Deprecated // Paper - public Merchant createMerchant(String title) { - return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); - } -@@ -1729,6 +1771,12 @@ public final class CraftServer implements Server { - return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component motd() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.ChatComponentText(console.getMotd())); -+ } -+ // Paper end - @Override - public String getMotd() { - return console.getMotd(); -@@ -2157,5 +2205,15 @@ public final class CraftServer implements Server { - return null; - } - } -+ -+ // Paper start -+ private Iterable adventure$audiences; -+ @Override -+ public Iterable audiences() { -+ if (this.adventure$audiences == null) { -+ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); -+ } -+ return this.adventure$audiences; -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 3b48799d084f14722f815cb35cbd48b618380fca..cf6d350e6afc46bb58678192fe0b24b7d923412e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -19,6 +19,12 @@ public class Main { - public static boolean useConsole = true; - - public static void main(String[] args) { -+ // Paper start -+ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); -+ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { -+ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); -+ } -+ // Paper end - // Todo: Installation script - OptionParser parser = new OptionParser() { - { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index ae735836accc6bf6f0831f72ff882720b69df792..d3ae5cadd88f9012203d2c04cbe38af9b215ef0b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme - this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null; - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final TileEntityBeacon be = this.getSnapshot(); -+ return be.customName != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.customName) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - TileEntityBeacon beacon = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -index e8ce890c551c9b809e8ba3f7449dc33f3a3a6b80..c99a59573653ee5d14e780137c769116bf781ea7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -@@ -32,6 +32,19 @@ public abstract class CraftContainer extends Craf - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final T be = this.getSnapshot(); -+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - T container = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -index a559a77aae870988f4dd5e6f5f1f08feb3fad054..75ee5cc96c0e54f99e2ce820289bb74f57c426a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { - - // Lazily initialized only if requested: -- private String[] originalLines = null; -- private String[] lines = null; -+ // Paper start -+ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess -+ private java.util.ArrayList lines = null; // ArrayList for RandomAccess -+ // Paper end - - public CraftSign(final Block block) { - super(block, TileEntitySign.class); -@@ -24,27 +26,52 @@ public class CraftSign extends CraftBlockEntityState implements - super(material, te); - } - -+ // Paper start - @Override -- public String[] getLines() { -- if (lines == null) { -- // Lazy initialization: -- TileEntitySign sign = this.getSnapshot(); -- lines = new String[sign.lines.length]; -- System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length); -- originalLines = new String[lines.length]; -- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); -+ public java.util.List lines() { -+ this.loadLines(); -+ return this.lines; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component line(int index) { -+ this.loadLines(); -+ return this.lines.get(index); -+ } -+ -+ @Override -+ public void line(int index, net.kyori.adventure.text.Component line) { -+ this.loadLines(); -+ this.lines.set(index, line); -+ } -+ -+ private void loadLines() { -+ if (lines != null) { -+ return; - } -- return lines; -+ -+ // Lazy initialization: -+ TileEntitySign sign = this.getSnapshot(); -+ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.lines)); -+ originalLines = new java.util.ArrayList<>(lines); -+ } -+ // Paper end -+ @Override -+ public String[] getLines() { -+ this.loadLines(); -+ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper - } - - @Override - public String getLine(int index) throws IndexOutOfBoundsException { -- return getLines()[index]; -+ this.loadLines(); -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper - } - - @Override - public void setLine(int index, String line) throws IndexOutOfBoundsException { -- getLines()[index] = line; -+ this.loadLines(); -+ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper - } - - @Override -@@ -72,16 +99,32 @@ public class CraftSign extends CraftBlockEntityState implements - super.applyTo(sign); - - if (lines != null) { -- for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { -+ // Paper start -+ for (int i = 0; i < this.lines.size(); ++i) { -+ net.kyori.adventure.text.Component component = this.lines.get(i); -+ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); -+ if (component.equals(origComp)) { - continue; // The line contents are still the same, skip. - } -- sign.lines[i] = CraftChatMessage.fromString(line)[0]; -+ sign.lines[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); - } -+ // Paper end - } - } - -+ // Paper start -+ public static IChatBaseComponent[] sanitizeLines(java.util.List lines) { -+ IChatBaseComponent[] components = new IChatBaseComponent[4]; -+ for (int i = 0; i < 4; i++) { -+ if (i < lines.size() && lines.get(i) != null) { -+ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); -+ } else { -+ components[i] = new ChatComponentText(""); -+ } -+ } -+ return components; -+ } -+ // Paper end - public static IChatBaseComponent[] sanitizeLines(String[] lines) { - IChatBaseComponent[] components = new IChatBaseComponent[4]; - -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public boolean isConversing() { - return conversationTracker.isConversing(); - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 8f694de2fb3827b9be0dd768ad90eb72c7d708e4..5a14430f63894bbe9daa42900cf5a6519bea4f45 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment { - CraftEnchantment ench = (CraftEnchantment) other; - return !target.isCompatible(ench.target); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); -+ } -+ // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index eea242af23825ad29ada6e997205e87edffb6bb9..3cf81734c8580f4d88ea97b6ac737a370b413c84 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -768,6 +768,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().getVehicle().getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final IChatBaseComponent name = this.getHandle().getCustomName(); -+ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public void setCustomName(String name) { - // sane limit for name length -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 3a4e2261d0b0cd17df3f96e75f3c509156679c48..105d0388998d1e35e634d2163fe1a44aa7037ac8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -316,9 +316,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - container = CraftEventFactory.callInventoryOpenEvent(player, container); - if (container == null) return; - -- String title = container.getBukkitView().getTitle(); -+ //String title = container.getBukkitView().getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -387,8 +390,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - // Now open the window - Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); -- String title = inventory.getTitle(); -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ -+ //String title = inventory.getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b51a874e4665f977a154792e6216e03e04525f39..6ab14bccb1fcd108931bf7ec331e60f652e0b42d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -240,14 +240,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getDisplayName() { -+ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; - } - - @Override - public void setDisplayName(final String name) { -+ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper - getHandle().displayName = name == null ? getName() : name; - } - -+ // Paper start -+ @Override -+ public void playerListName(net.kyori.adventure.text.Component name) { -+ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); -+ for (EntityPlayer player : server.getHandle().players) { -+ if (player.getBukkitEntity().canSee(this)) { -+ player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); -+ } -+ } -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListName() { -+ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListHeader() { -+ return playerListHeader; -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListFooter() { -+ return playerListFooter; -+ } -+ // Paper end - @Override - public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); -@@ -266,35 +291,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -- private IChatBaseComponent playerListHeader; -- private IChatBaseComponent playerListFooter; -+ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure -+ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure - - @Override - public String getPlayerListHeader() { -- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); -+ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure - } - - @Override - public String getPlayerListFooter() { -- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); -+ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure - } - - @Override - public void setPlayerListHeader(String header) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListFooter(String footer) { -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListHeaderFooter(String header, String footer) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - -@@ -302,8 +327,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (getHandle().playerConnection == null) return; - - PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -- packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; -- packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; -+ packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure -+ packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure - getHandle().playerConnection.sendPacket(packet); - } - -@@ -335,6 +360,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.disconnect(message == null ? "" : message); - } - -+ // Paper start -+ @Override -+ public void kick(final net.kyori.adventure.text.Component message) { -+ org.spigotmc.AsyncCatcher.catchOp("player kick"); -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection != null) { -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ } -+ } -+ // Paper end -+ - @Override - public void setCompassTarget(Location loc) { - if (getHandle().playerConnection == null) return; -@@ -561,6 +597,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.sendPacket(packet); - } - -+ // Paper start -+ @Override -+ public void sendSignChange(Location loc, List lines) { -+ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); -+ } -+ @Override -+ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { -+ if (getHandle().playerConnection == null) { -+ return; -+ } -+ if (lines == null) { -+ lines = new java.util.ArrayList<>(4); -+ } -+ Validate.notNull(loc, "Location cannot be null"); -+ Validate.notNull(dyeColor, "DyeColor cannot be null"); -+ if (lines.size() < 4) { -+ throw new IllegalArgumentException("Must have at least 4 lines"); -+ } -+ IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -+ this.sendSignChange0(components, loc, dyeColor); -+ } -+ -+ private void sendSignChange0(IChatBaseComponent[] components, Location loc, DyeColor dyeColor) { -+ TileEntitySign sign = new TileEntitySign(); -+ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -+ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); -+ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); -+ -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ } -+ // Paper end - @Override - public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); -@@ -583,12 +650,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -- TileEntitySign sign = new TileEntitySign(); -+ /*TileEntitySign sign = new TileEntitySign(); // Paper - sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); - sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); - System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); - -- getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper -+ this.sendSignChange0(components, loc, dyeColor); // Paper - } - - @Override -@@ -1688,6 +1756,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; - } - -+ // Paper start -+ @Override -+ public java.util.Locale locale() { -+ return getHandle().adventure$locale; -+ } -+ // Paper end - @Override - public int getPing() { - return getHandle().ping; -@@ -1716,6 +1790,138 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getInventory().setItemInMainHand(hand); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return this.getHandle().adventure$displayName; -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); -+ this.getHandle().displayName = null; -+ } -+ -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ final PacketPlayOutChat packet = new PacketPlayOutChat(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatMessageType.CHAT : net.minecraft.network.chat.ChatMessageType.SYSTEM, identity.uuid()); -+ packet.adventure$message = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final PacketPlayOutTitle packet = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, null); -+ packet.adventure$text = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { -+ this.playerListHeader = header; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { -+ this.playerListHeader = header; -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ private void adventure$sendPlayerListHeaderAndFooter() { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection == null) return; -+ final PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; -+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; -+ connection.sendPacket(packet); -+ } -+ -+ @Override -+ public void showTitle(final net.kyori.adventure.title.Title title) { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ final net.kyori.adventure.title.Title.Times times = title.times(); -+ if (times != null) { -+ connection.sendPacket(new PacketPlayOutTitle(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); -+ } -+ final PacketPlayOutTitle sp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, null); -+ sp.adventure$text = title.subtitle(); -+ connection.sendPacket(sp); -+ final PacketPlayOutTitle tp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, null); -+ tp.adventure$text = title.title(); -+ connection.sendPacket(tp); -+ } -+ -+ private static int ticks(final java.time.Duration duration) { -+ if (duration == null) { -+ return -1; -+ } -+ return (int) (duration.toMillis() / 50L); -+ } -+ -+ @Override -+ public void clearTitle() { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, null)); -+ } -+ -+ // resetTitle implemented above -+ -+ @Override -+ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); -+ } -+ -+ @Override -+ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound) { -+ final Vec3D pos = this.getHandle().getPositionVector(); -+ this.playSound(sound, pos.x, pos.y, pos.z); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { -+ final MinecraftKey name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); -+ final java.util.Optional event = net.minecraft.core.IRegistry.SOUND_EVENT.getOptional(name); -+ if (event.isPresent()) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); -+ } else { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3D(x, y, z), sound.volume(), sound.pitch())); -+ } -+ } -+ -+ @Override -+ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound( -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) -+ )); -+ } -+ -+ @Override -+ public void openBook(final net.kyori.adventure.inventory.Book book) { -+ final java.util.Locale locale = this.getHandle().adventure$locale; -+ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); -+ final EntityPlayer player = this.getHandle(); -+ final PlayerConnection connection = player.playerConnection; -+ final net.minecraft.world.entity.player.PlayerInventory inventory = player.inventory; -+ final int slot = inventory.items.size() + inventory.itemInHandIndex; -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, item)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 8e83eb95ffce62aad10f4d9b259dc5dd076b7640..418becfe2b4fe5ca808f250469bbb46414a5cbc0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -785,9 +785,9 @@ public class CraftEventFactory { - return event; - } - -- public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, String deathMessage, boolean keepInventory) { -+ public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure - CraftPlayer entity = victim.getBukkitEntity(); -- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); -+ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -@@ -811,7 +811,7 @@ public class CraftEventFactory { - * Server methods - */ - public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { -- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); -+ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure - craftServer.getPluginManager().callEvent(event); - return event; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index 384520dd734449d4e4f5243fbaad5f666b0c965c..614ab2d73db2293116f2272f6cd5c16da446132d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -@@ -39,6 +39,7 @@ public class CraftContainer extends Container { - - private final InventoryView view; - private InventoryType cachedType; -+ private net.kyori.adventure.text.Component adventure$title; // Paper - private String cachedTitle; - private Container delegate; - private final int cachedSize; -@@ -50,7 +51,9 @@ public class CraftContainer extends Container { - IInventory top = ((CraftInventory) view.getTopInventory()).getInventory(); - PlayerInventory bottom = (PlayerInventory) ((CraftInventory) view.getBottomInventory()).getInventory(); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - cachedSize = getSize(); - setupSlots(top, bottom, player); - } -@@ -77,6 +80,13 @@ public class CraftContainer extends Container { - return inventory.getType(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); -@@ -95,7 +105,8 @@ public class CraftContainer extends Container { - - @Override - public boolean c(EntityHuman entityhuman) { -- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { -+ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper -+ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment - return true; - } - // If the window type has changed for some reason, update the player -@@ -103,7 +114,9 @@ public class CraftContainer extends Container { - // as good a place as any to put something like this. - boolean typeChanged = (cachedType != view.getType()); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - if (view.getPlayer() instanceof CraftPlayer) { - CraftPlayer player = (CraftPlayer) view.getPlayer(); - Containers type = getNotchInventoryType(view.getTopInventory()); -@@ -115,7 +128,8 @@ public class CraftContainer extends Container { - setupSlots(top, bottom, player.getHandle()); - } - int size = getSize(); -- player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); -+ player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper -+ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment - player.updateInventory(); - } - return true; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index a537cc4ac5d052168f96a1ae73b6b17a380436ab..21347cf02cc01c90a81e7dd8264ef11968d9f145 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, type)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, type, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { - super(new MinecraftInventory(owner, type, title)); - } -@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, size)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, size, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, int size, String title) { - super(new MinecraftInventory(owner, size, title)); - } -@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory { - private int maxStack = MAX_STACK; - private final List viewers; - private final String title; -+ private final net.kyori.adventure.text.Component adventure$title; // Paper - private InventoryType type; - private final InventoryHolder owner; - -+ // Paper start -+ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ this(owner, type.getDefaultSize(), title); -+ this.type = type; -+ } -+ // Paper end -+ - public MinecraftInventory(InventoryHolder owner, InventoryType type) { - this(owner, type.getDefaultSize(), type.getDefaultTitle()); - this.type = type; -@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory { - Validate.notNull(title, "Title cannot be null"); - this.items = NonNullList.a(size, ItemStack.b); - this.title = title; -+ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); - this.viewers = new ArrayList(); - this.owner = owner; - this.type = InventoryType.CHEST; - } - -+ // Paper start -+ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.items = NonNullList.a(size, ItemStack.b); -+ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.adventure$title = title; -+ this.viewers = new ArrayList(); -+ this.owner = owner; -+ this.type = InventoryType.CHEST; -+ } -+ // Paper end -+ - @Override - public int getSize() { - return items.size(); -@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory { - return null; - } - -+ // Paper start -+ public net.kyori.adventure.text.Component title() { -+ return this.adventure$title; -+ } -+ // Paper end -+ - public String getTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -index 04073ed45f8068d80e58d3927b5ebc3160c6a8c6..9949bb8cac73b2f1f02b51079c0e244f923af8e9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView { - return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 89a3617068421bb86baf4e8bfd9df2d0626adff7..ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -334,4 +334,17 @@ public final class CraftItemFactory implements ItemFactory { - public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { - return ((CraftMetaItem) meta).updateMaterial(material); - } -+ -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { -+ final net.minecraft.nbt.NBTTagCompound tag = CraftItemStack.asNMSCopy(item).getTag(); -+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); -+ } -+ -+ @Override -+ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index ef10c7ab1d615cdba182eca63eb14309339a5314..206c133ebc6c44038585236b0628543b8bed278c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate; - - public class CraftMerchantCustom extends CraftMerchant { - -+ @Deprecated // Paper - Adventure - public CraftMerchantCustom(String title) { - super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; - } -+ // Paper start -+ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { -+ super(new MinecraftMerchant(title)); -+ getMerchant().craftMerchant = this; -+ } -+ // Paper end - - @Override - public String toString() { -@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant { - private World tradingWorld; - protected CraftMerchant craftMerchant; - -+ @Deprecated // Paper - Adventure - public MinecraftMerchant(String title) { - Validate.notNull(title, "Title cannot be null"); - this.title = new ChatComponentText(title); - } -+ // Paper start -+ public MinecraftMerchant(net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); -+ } -+ // Paper end - - @Override - public CraftMerchant getCraftMerchant() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 4cdc504df4cad6f7725f6d18482e88433523943a..65b6d32e3e1130a64df33082f3292cb1ce6f500a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -1,8 +1,9 @@ - package org.bukkit.craftbukkit.inventory; - - import com.google.common.collect.ImmutableList; --import com.google.common.collect.ImmutableMap.Builder; - import com.google.common.collect.Lists; -+ -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; -@@ -21,6 +22,7 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.BookMeta.Generation; -+import org.checkerframework.checker.nullness.qual.NonNull; - - // Spigot start - import static org.spigotmc.ValidateUtils.*; -@@ -269,6 +271,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - this.generation = (generation == null) ? null : generation.ordinal(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { -+ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component author() { -+ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { -+ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component page(final int page) { -+ Validate.isTrue(isValidPage(page), "Invalid page number"); -+ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); -+ } -+ -+ @Override -+ public void page(final int page, net.kyori.adventure.text.Component data) { -+ if (!isValidPage(page)) { -+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); -+ } -+ if (data == null) { -+ data = net.kyori.adventure.text.Component.empty(); -+ } -+ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); -+ } -+ -+ @Override -+ public List pages() { -+ if (this.pages == null) return ImmutableList.of(); -+ if (this instanceof CraftMetaBookSigned) -+ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); -+ else -+ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); -+ } -+ -+ @Override -+ public BookMeta pages(List pages) { -+ if (this.pages != null) this.pages.clear(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ addPages(page); -+ } -+ return this; -+ } -+ -+ @Override -+ public BookMeta pages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages != null) this.pages.clear(); -+ addPages(pages); -+ return this; -+ } -+ -+ @Override -+ public void addPages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages == null) this.pages = new ArrayList<>(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ if (this.pages.size() >= MAX_PAGES) { -+ return; -+ } -+ -+ if (page == null) { -+ page = net.kyori.adventure.text.Component.empty(); -+ } -+ -+ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); -+ } -+ } -+ -+ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { -+ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); -+ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); -+ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); -+ } -+ -+ static final class CraftMetaBookBuilder implements BookMetaBuilder { -+ private net.kyori.adventure.text.Component title = null; -+ private net.kyori.adventure.text.Component author = null; -+ private final List pages = new java.util.ArrayList<>(); -+ -+ @Override -+ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { -+ this.title = title; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { -+ this.author = author; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { -+ this.pages.add(page); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { -+ java.util.Collections.addAll(this.pages, pages); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(java.util.Collection pages) { -+ this.pages.addAll(pages); -+ return this; -+ } -+ -+ @Override -+ public BookMeta build() { -+ return new CraftMetaBook(title, author, pages); -+ } -+ } -+ -+ @Override -+ public BookMetaBuilder toBuilder() { -+ return new CraftMetaBookBuilder(); -+ } -+ -+ // Paper end - @Override - public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); -@@ -413,7 +550,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - - if (hasTitle()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 0835541f51e643ae824c197be7100d5849b5e92a..0d58ec9834797ad7b9acaae6353dcf0385c53fd4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -1,6 +1,6 @@ - package org.bukkit.craftbukkit.inventory; - --import com.google.common.collect.ImmutableMap.Builder; -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.Map; - import net.minecraft.nbt.NBTTagCompound; - import org.bukkit.Material; -@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - return builder; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 928328c292a1322cab478bc748761baf8608e4b0..7a11b2ddfa4244459253c918315aaab78ef2eb4a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - return CraftChatMessage.fromJSONComponent(displayName); -@@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore != null && !this.lore.isEmpty(); - } - -+ // Paper start -+ @Override -+ public List lore() { -+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; -+ } -+ -+ @Override -+ public void lore(final List lore) { -+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasRepairCost() { - return repairCost > 0; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(holder, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - return new CraftInventoryCustom(owner, type, title); -@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(owner, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder owner, int size, String title) { - return new CraftInventoryCustom(owner, size, title); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index b51321c8dd70a90ab149f456c7ffb4587c4fbd34..94d807c5d09f165c6eedd0a1c4026c2b833806a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -43,6 +43,17 @@ public final class CraftInventoryCreator { - return converterMap.get(type).createInventory(holder, type); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end -+ return converterMap.get(type).createInventory(holder, type, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); - } -@@ -51,6 +62,12 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { -+ return DEFAULT_CONVERTER.createInventory(holder, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); - } -@@ -59,6 +76,10 @@ public final class CraftInventoryCreator { - - Inventory createInventory(InventoryHolder holder, InventoryType type); - -+ // Paper start -+ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); -+ // Paper end -+ - Inventory createInventory(InventoryHolder holder, InventoryType type, String title); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -index f35e66dab9ff63ca05d7e303c71106c0e9971309..2bd4e644ffbde2e1133b25824a2829bc6b33fa84 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return getInventory(getTileEntity()); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory te = getTileEntity(); -+ if (te instanceof TileEntityLootable) { -+ ((TileEntityLootable) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ -+ return getInventory(te); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - IInventory te = getTileEntity(); -@@ -54,6 +66,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return furnace; - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory tileEntity = getTileEntity(); -+ ((TileEntityFurnace) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - IInventory tileEntity = getTileEntity(); -@@ -74,6 +95,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new TileEntityBrewingStand(); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ // BrewingStand does not extend TileEntityLootable -+ IInventory tileEntity = getTileEntity(); -+ if (tileEntity instanceof TileEntityBrewingStand) { -+ ((TileEntityBrewingStand) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - // BrewingStand does not extend TileEntityLootable -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -index 8fedca656af0783f3d97a7ccde3a113f97911084..df3deee12b11508b76c5f8f927fac8db54a7e397 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -@@ -31,6 +31,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective - return objective.getName(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ CraftScoreboard scoreboard = checkState(); -+ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ // Paper end - @Override - public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 954389b818de93cf0ab046edc5dc032fceea391b..6ea491f6308317059c4bc6735abbdce370df0f34 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -28,6 +28,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { - return registerNewObjective(name, criteria, name); - } -+ // Paper start -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { -+ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); -+ } -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ Validate.notNull(name, "Objective name cannot be null"); -+ Validate.notNull(criteria, "Criteria cannot be null"); -+ Validate.notNull(displayName, "Display name cannot be null"); -+ Validate.notNull(renderType, "RenderType cannot be null"); -+ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); -+ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); -+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -+ return new CraftObjective(this, objective); -+ } -+ // Paper end - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { -@@ -36,7 +57,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { -- Validate.notNull(name, "Objective name cannot be null"); -+ /*Validate.notNull(name, "Objective name cannot be null"); // Paper - Validate.notNull(criteria, "Criteria cannot be null"); - Validate.notNull(displayName, "Display name cannot be null"); - Validate.notNull(renderType, "RenderType cannot be null"); -@@ -46,7 +67,8 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -- return new CraftObjective(this, objective); -+ return new CraftObjective(this, objective);*/ // Paper -+ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index a213c2e3b2680c6d1bd38853580cbdb52ae7779e..c631934fe9d205a06956c900d5b58a1d8a781c19 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -29,6 +29,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - return team.getName(); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPrefix()); -+ } -+ @Override -+ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { -+ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getSuffix()); -+ } -+ @Override -+ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { -+ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); -+ } -+ @Override -+ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); -+ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); -+ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); -+ return (net.kyori.adventure.text.format.NamedTextColor) color; -+ } -+ @Override -+ public void color(net.kyori.adventure.text.format.NamedTextColor color) { -+ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; -+ CraftScoreboard scoreboard = checkState(); -+ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); -+ } -+ // Paper end - - @Override - public String getDisplayName() throws IllegalStateException { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 6a0b4cd36ac54df41642e8499c50e59f2b347b48..666af6cc91bd12ba5d5a846d663a5aabf861fbc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -290,6 +290,7 @@ public final class CraftChatMessage { - - public static String fromComponent(IChatBaseComponent component) { - if (component == null) return ""; -+ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); - StringBuilder out = new StringBuilder(); - - boolean hadFormat = false; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 65131f0977fa55c4761c34ce52720170feb61a72..8f737f63f280c00c1276bd1dc3ecf60448732ca8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -59,6 +59,33 @@ public final class CraftMagicNumbers implements UnsafeValues { - - private CraftMagicNumbers() {} - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { -+ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.PLAIN; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; -+ } -+ // Paper end -+ - public static IBlockData getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); - } diff --git a/Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch deleted file mode 100644 index d184572c6bc8..000000000000 --- a/Spigot-Server-Patches/0011-Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:02:51 -0600 -Subject: [PATCH] Configurable cactus bamboo and reed growth heights - -Bamboo - Both the minimum fully-grown heights and the maximum are configurable -- Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b31109d2dadd29e8852468c19265066b773d2be0..3618cc017feb60e257a28f67cbddca3f792a9833 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -65,4 +65,17 @@ public class PaperWorldConfig { - config.addDefault("world-settings.default." + path, def); - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } -+ -+ public int cactusMaxHeight; -+ public int reedMaxHeight; -+ public int bambooMaxHeight; -+ public int bambooMinHeight; -+ private void blockGrowthHeight() { -+ cactusMaxHeight = getInt("max-growth-height.cactus", 3); -+ reedMaxHeight = getInt("max-growth-height.reeds", 3); -+ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); -+ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); -+ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); -+ -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -index 6d10a7cb48627f37dc91b73064edc5f18c2b5ce9..cd132eff3f82349518555d1d5a16778ca08a521b 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -@@ -124,7 +124,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot - int i = this.b(worldserver, blockposition) + 1; - -- if (i < 16) { -+ if (i < worldserver.paperConfig.bambooMaxHeight) { // Paper - this.a(iblockdata, (World) worldserver, blockposition, random, i); - } - } -@@ -155,7 +155,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - int i = this.a(iblockaccess, blockposition); - int j = this.b(iblockaccess, blockposition); - -- return i + j + 1 < 16 && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; -+ return i + j + 1 < ((World) iblockaccess).paperConfig.bambooMaxHeight && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; // Paper - } - - @Override -@@ -174,7 +174,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - BlockPosition blockposition1 = blockposition.up(i); - IBlockData iblockdata1 = worldserver.getType(blockposition1); - -- if (k >= 16 || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here -+ if (k >= worldserver.paperConfig.bambooMaxHeight || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights - return; - } - -@@ -215,7 +215,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - } - - int j = (Integer) iblockdata.get(BlockBamboo.d) != 1 && !iblockdata2.a(Blocks.BAMBOO) ? 0 : 1; -- int k = (i < 11 || random.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; -+ int k = (i < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && i != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper - - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.up(), (IBlockData) ((IBlockData) ((IBlockData) this.getBlockData().set(BlockBamboo.d, j)).set(BlockBamboo.e, blockpropertybamboosize)).set(BlockBamboo.f, k), 3)) { -@@ -230,7 +230,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int a(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -@@ -240,7 +240,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int b(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -index c2316e346f9b647edae4c9709defa4531e04eaa6..9f1e9fc5361cd051b909e2e1b2095722064185da 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -@@ -55,7 +55,7 @@ public class BlockCactus extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockCactus.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot -diff --git a/src/main/java/net/minecraft/world/level/block/BlockReed.java b/src/main/java/net/minecraft/world/level/block/BlockReed.java -index eb95d65e1a37b91a71a9ad8968710ba9047f3980..a4ede7968ba0134f0d2cf880a6b4a6b9a81f2fcd 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockReed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockReed.java -@@ -51,7 +51,7 @@ public class BlockReed extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.reedMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockReed.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch b/Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch deleted file mode 100644 index 060f23376f6e..000000000000 --- a/Spigot-Server-Patches/0012-Configurable-baby-zombie-movement-speed.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:09:16 -0600 -Subject: [PATCH] Configurable baby zombie movement speed - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3618cc017feb60e257a28f67cbddca3f792a9833..796c17e0941922a9716212c6eae91643d8360418 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -78,4 +78,15 @@ public class PaperWorldConfig { - log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); - - } -+ -+ public double babyZombieMovementModifier; -+ private void babyZombieMovementModifier() { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); -+ if (PaperConfig.version < 20) { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); -+ set("baby-zombie-movement-modifier", babyZombieMovementModifier); -+ } -+ -+ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index daa6d1ca20f952971a2ad6a0c4cba0bef6e43bf6..219e3b1626d68ede57b08a706d24bb6bc4b13fac 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -82,7 +82,7 @@ import org.bukkit.event.entity.EntityTransformEvent; - public class EntityZombie extends EntityMonster { - - private static final UUID b = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); -- private static final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); -+ private final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.c; // Paper - remove static - Make baby speed configurable - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -@@ -185,9 +185,9 @@ public class EntityZombie extends EntityMonster { - if (this.world != null && !this.world.isClientSide) { - AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(EntityZombie.c); -+ attributemodifiable.removeModifier(this.babyModifier); // Paper - if (flag) { -- attributemodifiable.b(EntityZombie.c); -+ attributemodifiable.b(this.babyModifier); // Paper - } - } - diff --git a/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch b/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch deleted file mode 100644 index 7d7162311aa9..000000000000 --- a/Spigot-Server-Patches/0013-Configurable-fishing-time-ranges.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:14:11 -0600 -Subject: [PATCH] Configurable fishing time ranges - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 796c17e0941922a9716212c6eae91643d8360418..78948c42b13194005bdbbbc69c2b7ae0732a78c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -89,4 +89,12 @@ public class PaperWorldConfig { - - log("Baby zombies will move at the speed of " + babyZombieMovementModifier); - } -+ -+ public int fishingMinTicks; -+ public int fishingMaxTicks; -+ private void fishingTickRange() { -+ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); -+ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); -+ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 2b75eab985b0f39e1624e5f4cab7e5b5bde6ae14..bcc411107d531529dbce9d1d43896a3c70e63012 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -85,6 +85,10 @@ public class EntityFishingHook extends IProjectile { - entityhuman.hookedFish = this; - this.an = Math.max(0, i); - this.lureLevel = Math.max(0, j); -+ // Paper start -+ minWaitTime = world.paperConfig.fishingMinTicks; -+ maxWaitTime = world.paperConfig.fishingMaxTicks; -+ // paper end - } - - public EntityFishingHook(EntityHuman entityhuman, World world, int i, int j) { diff --git a/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch deleted file mode 100644 index cbf2e1e52ce9..000000000000 --- a/Spigot-Server-Patches/0014-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 13:24:16 -0600 -Subject: [PATCH] Allow nerfed mobs to jump and take water damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 78948c42b13194005bdbbbc69c2b7ae0732a78c5..b41e7922dd96c3358eb849ab39982a75736e3476 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -97,4 +97,9 @@ public class PaperWorldConfig { - fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); - log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); - } -+ -+ public boolean nerfedMobsShouldJump; -+ private void nerfedMobsShouldJump() { -+ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index db8970539f7f69c9087abe43286bca008cb4594d..0b86c697541e3ee6083b3c10ab3618ef740b1904 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1105,6 +1105,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain(); - } - -+ public final boolean isInWaterOrRainOrBubble() { return aG(); } // Paper - OBFHELPER - public boolean aG() { - return this.isInWater() || this.isInRain() || this.k(); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index dbfcdc3cc7c1dccf785f5e13634e84c5af088985..28aa0a9361e8a32763d7fe1af060f0016e8c1e50 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -98,6 +98,7 @@ public abstract class EntityInsentient extends EntityLiving { - private final EntityAIBodyControl c; - protected NavigationAbstract navigation; - public PathfinderGoalSelector goalSelector; -+ @Nullable public PathfinderGoalFloat goalFloat; // Paper - public PathfinderGoalSelector targetSelector; - private EntityLiving goalTarget; - private final EntitySenses bo; -@@ -784,7 +785,17 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected final void doTick() { - ++this.ticksFarFromPlayer; -- if (!this.aware) return; // CraftBukkit -+ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage -+ if (goalFloat != null) { -+ if (goalFloat.validConditions()) goalFloat.update(); -+ this.getControllerJump().jumpIfSet(); -+ } -+ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ damageEntity(DamageSource.DROWN, 1.0F); -+ } -+ return; -+ } -+ // Paper end - this.world.getMethodProfiler().enter("sensing"); - this.bo.a(); - this.world.getMethodProfiler().exit(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -index 9767ac416fcd60a8a57b648dcb3f1e427bacd54d..1a9b3e0e0c090683e332dfa53708f8a62c8f14e0 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -@@ -15,6 +15,7 @@ public class ControllerJump { - this.a = true; - } - -+ public final void jumpIfSet() { this.b(); } // Paper - OBFHELPER - public void b() { - this.b.setJumping(this.a); - this.a = false; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -index 8dfa1a6ade7f51e5d68b290f5376d999bb4c60ab..a6c8763139ed18fe73b2d6f6ec511e59666dc843 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -@@ -11,15 +11,18 @@ public class PathfinderGoalFloat extends PathfinderGoal { - - public PathfinderGoalFloat(EntityInsentient entityinsentient) { - this.a = entityinsentient; -+ if (entityinsentient.getWorld().paperConfig.nerfedMobsShouldJump) entityinsentient.goalFloat = this; // Paper - this.a(EnumSet.of(PathfinderGoal.Type.JUMP)); - entityinsentient.getNavigation().d(true); - } - -+ public final boolean validConditions() { return this.a(); } // Paper - OBFHELPER - @Override - public boolean a() { - return this.a.isInWater() && this.a.b((Tag) TagsFluid.WATER) > this.a.cx() || this.a.aQ(); - } - -+ public void update() { this.e(); } // Paper - OBFHELPER - @Override - public void e() { - if (this.a.getRandom().nextFloat() < 0.8F) { diff --git a/Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch b/Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch deleted file mode 100644 index edb9677fb557..000000000000 --- a/Spigot-Server-Patches/0015-Add-configurable-despawn-distances-for-living-entiti.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Suddenly -Date: Tue, 1 Mar 2016 13:51:54 -0600 -Subject: [PATCH] Add configurable despawn distances for living entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b41e7922dd96c3358eb849ab39982a75736e3476..2f0d582baf0eb2bb477944d0cb1369db6ca33956 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -102,4 +102,20 @@ public class PaperWorldConfig { - private void nerfedMobsShouldJump() { - nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); - } -+ -+ public int softDespawnDistance; -+ public int hardDespawnDistance; -+ private void despawnDistances() { -+ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default -+ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default -+ -+ if (softDespawnDistance > hardDespawnDistance) { -+ softDespawnDistance = hardDespawnDistance; -+ } -+ -+ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); -+ -+ softDespawnDistance = softDespawnDistance*softDespawnDistance; -+ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 28aa0a9361e8a32763d7fe1af060f0016e8c1e50..f93af56f68d5fd27eca38d333ca429ce22fc397b 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -763,14 +763,14 @@ public abstract class EntityInsentient extends EntityLiving { - int i = this.getEntityType().e().f(); - int j = i * i; - -- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (d0 > (double) world.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); - } - - int k = this.getEntityType().e().g(); - int l = k * k; - -- if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > world.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); - } else if (d0 < (double) l) { - this.ticksFarFromPlayer = 0; diff --git a/Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch b/Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch deleted file mode 100644 index 126f048726ab..000000000000 --- a/Spigot-Server-Patches/0016-Allow-for-toggling-of-spawn-chunks.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 3 Mar 2016 03:53:43 -0600 -Subject: [PATCH] Allow for toggling of spawn chunks - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f0d582baf0eb2bb477944d0cb1369db6ca33956..89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -118,4 +118,10 @@ public class PaperWorldConfig { - softDespawnDistance = softDespawnDistance*softDespawnDistance; - hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; - } -+ -+ public boolean keepSpawnInMemory; -+ private void keepSpawnInMemory() { -+ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); -+ log("Keep spawn chunk loaded: " + keepSpawnInMemory); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 1b03c69fa7ffeca4083470a179e18be828b0a957..62735e7908f86e31f7a89ce2071ddebe176c0385 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -217,6 +217,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }); - // CraftBukkit end - timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings -+ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } diff --git a/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch deleted file mode 100644 index 26dfa439bc13..000000000000 --- a/Spigot-Server-Patches/0017-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 14:14:15 -0600 -Subject: [PATCH] Drop falling block and tnt entities at the specified height - -* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 89e76dd73811fd0f6f8c8e7e5af804d5a4bb5a75..d16ae924bcbe31c964f7fb448757c748e5c4418c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -124,4 +124,14 @@ public class PaperWorldConfig { - keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); - log("Keep spawn chunk loaded: " + keepSpawnInMemory); - } -+ -+ public int fallingBlockHeightNerf; -+ public int entityTNTHeightNerf; -+ private void heightNerfs() { -+ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); -+ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); -+ -+ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); -+ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0b86c697541e3ee6083b3c10ab3618ef740b1904..d7dfb89faa47817c51257bb124cfb3806c5e27da 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1850,6 +1850,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.a(itemstack, 0.0F); - } - -+ @Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER - @Nullable - public EntityItem a(ItemStack itemstack, float f) { - if (itemstack.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index b3dea8d65c3d1e27e59be142ec9e2ebb4164aed0..901522f24b8bc58861e46eda400dbab92bb6401d 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -124,6 +124,17 @@ public class EntityFallingBlock extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ -+ // Paper start - Configurable EntityFallingBlock height nerf -+ if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { -+ if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { -+ this.a(block); -+ } -+ -+ this.die(); -+ return; -+ } -+ // Paper end - if (!this.world.isClientSide) { - blockposition = this.getChunkCoordinates(); - boolean flag = this.block.getBlock() instanceof BlockConcretePowder; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index c2e7161dc103c971908ff217eaf972e9f175d044..4f4b2b8d58223fa22d6a7af5c94cfb36399b9641 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -70,6 +70,12 @@ public class EntityTNTPrimed extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - this.setMot(this.getMot().a(0.98D)); - if (this.onGround) { - this.setMot(this.getMot().d(0.7D, -0.5D, 0.7D)); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -index ee31704ffb88ab68702657554d386e8ebfa05d03..4bec5c1d504b9456dafe1b76bdbb523d0a324abe 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -@@ -47,6 +47,12 @@ public class EntityMinecartTNT extends EntityMinecartAbstract { - public void tick() { - super.tick(); - if (this.b > 0) { -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - --this.b; - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } else if (this.b == 0) { diff --git a/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch deleted file mode 100644 index c038efb7ba76..000000000000 --- a/Spigot-Server-Patches/0018-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 14:32:43 -0600 -Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang - stats - - -diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java -index a5171d28b960b12c2743ea68a36d747bc967697d..a0f53c9eff04a40780b3ba568dbfc5bbe9bd8504 100644 ---- a/src/main/java/net/minecraft/server/EULA.java -+++ b/src/main/java/net/minecraft/server/EULA.java -@@ -72,7 +72,7 @@ public class EULA { - Properties properties = new Properties(); - - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 511d6094403d17522212fcdda6903a13517c44fa..9ba05ab7ec97896349f4b754f2993cda9ab1bbfd 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1342,7 +1342,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // CraftBukkit - cb > vanilla! -+ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index cb470baa3533e4502c13982ef4e03041fac91ce5..c66be5b9f304878f9179faba433f2e844bcee72c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -226,7 +226,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - - public final class CraftServer implements Server { -- private final String serverName = "CraftBukkit"; -+ private final String serverName = "Paper"; // Paper - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bb8ddfae48526d9b6fdc64eecb6f655f6b7665de..8507f9a81b6068eb2f50e6390e3b4afe6d04fbbb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -206,12 +206,25 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { - System.err.println("*** Error, this build is outdated ***"); -- System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***"); -+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper - System.err.println("*** Server will start in 20 seconds ***"); - Thread.sleep(TimeUnit.SECONDS.toMillis(20)); - } - } - -+ // Paper start - Log Java and OS versioning to help with debugging plugin issues -+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); -+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); -+ if (runtimeMX != null && osMX != null) { -+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; -+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; -+ -+ System.out.println("System Info: " + javaInfo + " " + osInfo); -+ } else { -+ System.out.println("Unable to read system info"); -+ } -+ // Paper end -+ - System.out.println("Loading libraries, please wait..."); - net.minecraft.server.Main.main(options); - } catch (Throwable t) { -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index b4eeeb0d001e692180874bd26385a0e786a8b752..1b3a14784cac8e855633fae6172ad5479ebe9877 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -19,7 +19,7 @@ public class WatchdogThread extends Thread - - private WatchdogThread(long timeoutTime, boolean restart) - { -- super( "Spigot Watchdog Thread" ); -+ super( "Paper Watchdog Thread" ); - this.timeoutTime = timeoutTime; - this.restart = restart; - } -@@ -65,14 +65,14 @@ public class WatchdogThread extends Thread - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); -+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); - log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); - log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); - log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); -- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); -+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); - log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); -- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); -+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); - // - if ( net.minecraft.world.level.World.lastPhysicsProblem != null ) - { -@@ -82,7 +82,7 @@ public class WatchdogThread extends Thread - } - // - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); -+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch b/Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch deleted file mode 100644 index 8be3bf335e4e..000000000000 --- a/Spigot-Server-Patches/0019-Implement-Paper-VersionChecker.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 27 May 2019 03:40:05 -0500 -Subject: [PATCH] Implement Paper VersionChecker - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c8b911e5d013525ffc5d2911ee0e421dd916cb00 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -0,0 +1,117 @@ -+package com.destroystokyo.paper; -+ -+import com.destroystokyo.paper.util.VersionFetcher; -+import com.google.common.base.Charsets; -+import com.google.common.io.Resources; -+import com.google.gson.*; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.io.*; -+import java.net.HttpURLConnection; -+import java.net.URL; -+ -+public class PaperVersionFetcher implements VersionFetcher { -+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end -+ private static final String GITHUB_BRANCH_NAME = "master"; -+ private static @Nullable String mcVer; -+ -+ @Override -+ public long getCacheTime() { -+ return 720000; -+ } -+ -+ @Nonnull -+ @Override -+ public Component getVersionMessage(@Nonnull String serverVersion) { -+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ } -+ -+ private static @Nullable String getMinecraftVersion() { -+ if (mcVer == null) { -+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); -+ if (matcher.find()) { -+ String result = matcher.group(); -+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' -+ } else { -+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); -+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); -+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); -+ } -+ } -+ -+ return mcVer; -+ } -+ -+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { -+ int distance; -+ try { -+ int jenkinsBuild = Integer.parseInt(versionInfo); -+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); -+ } catch (NumberFormatException ignored) { -+ versionInfo = versionInfo.replace("\"", ""); -+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); -+ } -+ -+ switch (distance) { -+ case -1: -+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); -+ case 0: -+ return Component.text("You are running the latest version", NamedTextColor.GREEN); -+ case -2: -+ return Component.text("Unknown version", NamedTextColor.YELLOW); -+ default: -+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); -+ } -+ } -+ -+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { -+ if (siteApiVersion == null) { return -1; } -+ try { -+ try (BufferedReader reader = Resources.asCharSource( -+ new URL("https://papermc.io/api/v1/paper/" + siteApiVersion + "/latest"), -+ Charsets.UTF_8 -+ ).openBufferedStream()) { -+ JsonObject json = new Gson().fromJson(reader, JsonObject.class); -+ int latest = json.get("build").getAsInt(); -+ return latest - jenkinsBuild; -+ } catch (JsonSyntaxException ex) { -+ ex.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+ -+ // Contributed by Techcable in GH-65 -+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { -+ try { -+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); -+ connection.connect(); -+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit -+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { -+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); -+ String status = obj.get("status").getAsString(); -+ switch (status) { -+ case "identical": -+ return 0; -+ case "behind": -+ return obj.get("behind_by").getAsInt(); -+ default: -+ return -1; -+ } -+ } catch (JsonSyntaxException | NumberFormatException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8f737f63f280c00c1276bd1dc3ecf60448732ca8..8aa9e7796ea39c09a965750d06c3d358250f33b8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -370,6 +370,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public String getTimingsServerName() { - return com.destroystokyo.paper.PaperConfig.timingsServerName; - } -+ -+ @Override -+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.PaperVersionFetcher(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch b/Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch deleted file mode 100644 index 8ce6b7fea567..000000000000 --- a/Spigot-Server-Patches/0020-Add-version-history-to-version-command.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 1 Mar 2018 19:37:52 -0600 -Subject: [PATCH] Add version history to version command - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -index c8b911e5d013525ffc5d2911ee0e421dd916cb00..dc0ea65ab87255fad0d54dfb509300098a0b4864 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -5,7 +5,9 @@ import com.google.common.base.Charsets; - import com.google.common.io.Resources; - import com.google.gson.*; - import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; - import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextDecoration; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -@@ -27,7 +29,10 @@ public class PaperVersionFetcher implements VersionFetcher { - @Override - public Component getVersionMessage(@Nonnull String serverVersion) { - String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component history = getHistory(); -+ -+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; - } - - private static @Nullable String getMinecraftVersion() { -@@ -114,4 +119,19 @@ public class PaperVersionFetcher implements VersionFetcher { - return -1; - } - } -+ -+ @Nullable -+ private Component getHistory() { -+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); -+ if (data == null) { -+ return null; -+ } -+ -+ final String oldVersion = data.getOldVersion(); -+ if (oldVersion == null) { -+ return null; -+ } -+ -+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aac3f66cb23d260729c2a48d8710a9de2346aa22 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -@@ -0,0 +1,145 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.MoreObjects; -+import com.google.gson.Gson; -+import com.google.gson.JsonSyntaxException; -+import java.io.BufferedReader; -+import java.io.BufferedWriter; -+import java.io.IOException; -+import java.nio.charset.StandardCharsets; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.nio.file.StandardOpenOption; -+import java.util.Objects; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import org.bukkit.Bukkit; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+ -+public enum VersionHistoryManager { -+ INSTANCE; -+ -+ private final Gson gson = new Gson(); -+ -+ private final Logger logger = Bukkit.getLogger(); -+ -+ private VersionData currentData = null; -+ -+ VersionHistoryManager() { -+ final Path path = Paths.get("version_history.json"); -+ -+ if (Files.exists(path)) { -+ // Basic file santiy checks -+ if (!Files.isRegularFile(path)) { -+ if (Files.isDirectory(path)) { -+ logger.severe(path + " is a directory, cannot be used for version history"); -+ } else { -+ logger.severe(path + " is not a regular file, cannot be used for version history"); -+ } -+ // We can't continue -+ return; -+ } -+ -+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { -+ currentData = gson.fromJson(reader, VersionData.class); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); -+ return; -+ } catch (final JsonSyntaxException e) { -+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); -+ return; -+ } -+ -+ final String version = Bukkit.getVersion(); -+ if (version == null) { -+ logger.severe("Failed to retrieve current version"); -+ return; -+ } -+ -+ if (!version.equals(currentData.getCurrentVersion())) { -+ // The version appears to have changed -+ currentData.setOldVersion(currentData.getCurrentVersion()); -+ currentData.setCurrentVersion(version); -+ writeFile(path); -+ } -+ } else { -+ // File doesn't exist, start fresh -+ currentData = new VersionData(); -+ // oldVersion is null -+ currentData.setCurrentVersion(Bukkit.getVersion()); -+ writeFile(path); -+ } -+ } -+ -+ private void writeFile(@Nonnull final Path path) { -+ try (final BufferedWriter writer = Files.newBufferedWriter( -+ path, -+ StandardCharsets.UTF_8, -+ StandardOpenOption.WRITE, -+ StandardOpenOption.CREATE, -+ StandardOpenOption.TRUNCATE_EXISTING -+ )) { -+ gson.toJson(currentData, writer); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to write to version history file", e); -+ } -+ } -+ -+ @Nullable -+ public VersionData getVersionData() { -+ return currentData; -+ } -+ -+ public static class VersionData { -+ private String oldVersion; -+ -+ private String currentVersion; -+ -+ @Nullable -+ public String getOldVersion() { -+ return oldVersion; -+ } -+ -+ public void setOldVersion(@Nullable String oldVersion) { -+ this.oldVersion = oldVersion; -+ } -+ -+ @Nullable -+ public String getCurrentVersion() { -+ return currentVersion; -+ } -+ -+ public void setCurrentVersion(@Nullable String currentVersion) { -+ this.currentVersion = currentVersion; -+ } -+ -+ @Override -+ public String toString() { -+ return MoreObjects.toStringHelper(this) -+ .add("oldVersion", oldVersion) -+ .add("currentVersion", currentVersion) -+ .toString(); -+ } -+ -+ @Override -+ public boolean equals(@Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ final VersionData versionData = (VersionData) o; -+ return Objects.equals(oldVersion, versionData.oldVersion) && -+ Objects.equals(currentVersion, versionData.currentVersion); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(oldVersion, currentVersion); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 59942eb6bb6e8e1e9a988bce0d09757e575018b9..faf4d00bf288359db806913c4d2964324e8706b7 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -196,6 +196,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - return false; - } - com.destroystokyo.paper.PaperConfig.registerCommands(); -+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch b/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch deleted file mode 100644 index aaedffd84375..000000000000 --- a/Spigot-Server-Patches/0021-Player-affects-spawning-API.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Tue, 1 Mar 2016 14:47:52 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 20e4ff812960a54872f2fea8fe6baf7bb1ef077d..cae9da158f54438d2a397665c7ce964f6f755469 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1354,6 +1354,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return MathHelper.c(f * f + f1 * f1 + f2 * f2); - } - -+ public double getDistanceSquared(double x, double y, double z) { return h(x, y, z); } // Paper - OBFHELPER - public double h(double d0, double d1, double d2) { - double d3 = this.locX() - d0; - double d4 = this.locY() - d1; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index f93af56f68d5fd27eca38d333ca429ce22fc397b..0631cd531647239858b2a7298f58cc770720f69a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -756,7 +756,7 @@ public abstract class EntityInsentient extends EntityLiving { - if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { - this.die(); - } else if (!this.isPersistent() && !this.isSpecialPersistence()) { -- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D); -+ EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper - - if (entityhuman != null) { - double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 6e78192a5898df017d96acba845a288011d24e35..dfcfdb31ca9531913d705aaaf85fb67399cfdc8c 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -29,6 +29,12 @@ public final class IEntitySelector { - return !entity.isSpectator(); - }; - -+ // Paper start -+ public static final Predicate affectsSpawning = (entity) -> { -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ }; -+ // Paper end -+ - public static Predicate a(double d0, double d1, double d2, double d3) { - double d4 = d3 * d3; - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -index 0b3b430766fba602e74727f78173567ca10fabc6..e1fcb1be102822e87eaf7757fbd64a516b2f58ac 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -@@ -122,7 +122,7 @@ public class EntitySilverfish extends EntityMonster { - if (c(entitytypes, generatoraccess, enummobspawn, blockposition, random)) { - EntityHuman entityhuman = generatoraccess.a((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0D, true); - -- return entityhuman == null; -+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 1017ee73b8617ce2b6734469fa49aaff7563c2b1..f42e16589476c1bd10b13214dda5ac7bb3e52131 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -164,6 +164,9 @@ public abstract class EntityHuman extends EntityLiving { - private final ItemCooldown bM; - @Nullable - public EntityFishingHook hookedFish; -+ // Paper start -+ public boolean affectsSpawning = true; -+ // Paper end - - // CraftBukkit start - public boolean fauxSleeping; -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 4ece69851e7b05016f52c291ce911eb791cf3a23..6d5d4c3df65995b9a13b66d070ba08d553cc98a2 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -92,8 +92,9 @@ public interface IEntityAccess { - } - } - -- @Nullable -- default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { -+ default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper -+ @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER -+ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper - double d4 = -1.0D; - EntityHuman entityhuman = null; - Iterator iterator = this.getPlayers().iterator(); -@@ -126,6 +127,27 @@ public interface IEntityAccess { - return this.a(d0, d1, d2, d3, predicate); - } - -+ // Paper end -+ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { -+ Iterator iterator = this.getPlayers().iterator(); -+ double d4; -+ do { -+ EntityHuman entityhuman; -+ do { -+ if (!iterator.hasNext()) { -+ return false; -+ } -+ -+ entityhuman = (EntityHuman) iterator.next(); -+ } while (!IEntitySelector.affectsSpawning.test(entityhuman)); -+ -+ d4 = entityhuman.getDistanceSquared(d0, d1, d2); -+ } while (d3 >= 0.0D && d4 >= d3 * d3); -+ -+ return true; -+ } -+ // Paper end -+ - default boolean isPlayerNearby(double d0, double d1, double d2, double d3) { - Iterator iterator = this.getPlayers().iterator(); - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 33cba4e475edc0573b901f70c61d3659fd63ad62..8d8b03074df1635946f81bec0feae18d2f3e20aa 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -66,7 +66,7 @@ public abstract class MobSpawnerAbstract { - private boolean h() { - BlockPosition blockposition = this.b(); - -- return this.a().isPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); -+ return this.a().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - } - - public void c() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6ab14bccb1fcd108931bf7ec331e60f652e0b42d..cc471418b37a745ecea1af964e81bc0362cf7d94 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1770,8 +1770,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - @Override - public String getLocale() { - return getHandle().locale; -+ -+ } -+ -+ // Paper start -+ public void setAffectsSpawning(boolean affects) { -+ this.getHandle().affectsSpawning = affects; - } - -+ @Override -+ public boolean getAffectsSpawning() { -+ return this.getHandle().affectsSpawning; -+ } -+ // Paper end -+ - @Override - public void updateCommands() { - if (getHandle().playerConnection == null) return; diff --git a/Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch b/Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch deleted file mode 100644 index 2aeae2d5b4a8..000000000000 --- a/Spigot-Server-Patches/0022-Remove-invalid-mob-spawner-tile-entities.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 15:08:03 -0600 -Subject: [PATCH] Remove invalid mob spawner tile entities - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index ac576d268b23148089d404cb22d8c2f9d1a79d6e..a2d80c2c8e4f080f60746548f75631c5946ba8e2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -40,9 +40,11 @@ import net.minecraft.world.level.TickListChunk; - import net.minecraft.world.level.TickListEmpty; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockMobSpawner; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.levelgen.ChunkProviderDebug; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -648,6 +650,10 @@ public class Chunk implements IChunkAccess { - } - - // CraftBukkit start -+ // Paper start - Remove invalid mob spawner tile entities -+ } else if (tileentity instanceof TileEntityMobSpawner && !(getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getBlock() instanceof BlockMobSpawner)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - } else { - System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() - + " (" + getType(blockposition) + ") where there was no entity tile!"); diff --git a/Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch b/Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch deleted file mode 100644 index a556c9c8da63..000000000000 --- a/Spigot-Server-Patches/0023-Optimize-TileEntity-Ticking.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 8 Mar 2015 22:55:25 -0600 -Subject: [PATCH] Optimize TileEntity Ticking - - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index d4ebcf8f66197299256bd6b65710a1488c90ea41..c9164dfdb27ddf3709129c8aec54903a1df121ff 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -109,7 +109,7 @@ public class TimingsExport extends Thread { - pair("end", System.currentTimeMillis() / 1000), - pair("online-mode", Bukkit.getServer().getOnlineMode()), - pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().e(), pack -> { - // Don't feel like obf helper'ing these, non fatal if its temp missed. - return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); - })) -@@ -148,8 +148,8 @@ public class TimingsExport extends Thread { - ); - - parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -- return pair(world.getWorldData().getName(), createObject( -+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorld().getName(), createObject( - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index 60e7dc1910ae9214d84d65b011cfec278b6b32ae..b229faad99120c67b089f7680d800fbe594fe7da 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShapeCollision; - public class BlockChest extends BlockChestAbstract implements IBlockWaterlogged { - - public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING; -- public static final BlockStateEnum c = BlockProperties.aF; -- public static final BlockStateBoolean d = BlockProperties.C; -+ public static final BlockStateEnum c = BlockProperties.aF; public static final BlockStateEnum CHEST_TYPE_PROPERTY = c; // Paper - OBFHELPER -+ public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER - protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); - protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); - protected static final VoxelShape g = Block.a(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index eed95b370d1d624ffc6b7a35357b7028ec58c584..51167d776c710decb0107bebcb35bdf43103772b 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -33,7 +34,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.entity.HumanEntity; - // CraftBukkit end - --public class TileEntityChest extends TileEntityLootable implements ITickable { -+public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable - - private NonNullList items; - protected float a; -@@ -111,14 +112,20 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - return nbttagcompound; - } - -- @Override - public void tick() { - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - - ++this.j; -- this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); -+ } -+ -+ public void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ -+ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set - this.b = this.a; - float f = 0.1F; - -@@ -132,8 +139,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - if (this.viewingCount > 0 && this.a == 0.0F) { - this.playOpenSound(SoundEffects.BLOCK_CHEST_OPEN); - } -+ } - -- if (this.viewingCount == 0 && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F) { -+ public void doCloseLogic() { -+ if (this.viewingCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check -+ /* // Paper - disable animation stuff - float f1 = this.a; - - if (this.viewingCount > 0) { -@@ -149,8 +159,11 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ */ -+ MCUtil.scheduleTask(10, () -> { - this.playOpenSound(SoundEffects.BLOCK_CHEST_CLOSE); -- } -+ }, "Chest Sounds"); -+ //} // Paper end - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -189,6 +202,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - } - - public void playOpenSound(SoundEffect soundeffect) { -+ if (!this.getBlock().contains(BlockChest.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 - BlockPropertyChestType blockpropertychesttype = (BlockPropertyChestType) this.getBlock().get(BlockChest.c); - - if (blockpropertychesttype != BlockPropertyChestType.LEFT) { -@@ -227,6 +241,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - - ++this.viewingCount; - if (this.world == null) return; // CraftBukkit -+ doOpenLogic(); // Paper - - // CraftBukkit start - Call redstone event - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { -@@ -249,6 +264,7 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - --this.viewingCount; - - // CraftBukkit start - Call redstone event -+ doCloseLogic(); // Paper - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { - int newPower = Math.max(0, Math.min(15, this.viewingCount)); - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -index 930f1bd091d9754f7ca5d9e36cdf49b2be03eb23..2bc4213c70be47ca8bbc24898cc92e43f4228821 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -@@ -1,11 +1,12 @@ - package net.minecraft.world.level.block.entity; - -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.block.Blocks; - --public class TileEntityEnderChest extends TileEntity implements ITickable { -+public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickable - - public float a; - public float b; -@@ -16,18 +17,28 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - super(TileEntityTypes.ENDER_CHEST); - } - -- @Override - public void tick() { - if (++this.g % 20 * 4 == 0) { - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - } - - this.b = this.a; -+ /* // Paper - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - float f = 0.1F; - double d0; -+ // Paper start -+ */ -+ } -+ -+ private void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ // Paper end - - if (this.c > 0 && this.a == 0.0F) { - double d1 = (double) i + 0.5D; -@@ -35,8 +46,17 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - d0 = (double) k + 0.5D; - this.world.playSound((EntityHuman) null, d1, (double) j + 0.5D, d0, SoundEffects.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); - } -+ // Paper start -+ } - -- if (this.c == 0 && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ private void doCloseLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ -+ if (this.c == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ // Paper end - float f1 = this.a; - - if (this.c > 0) { -@@ -52,11 +72,14 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ // Paper start -+ */ - d0 = (double) i + 0.5D; - double d2 = (double) k + 0.5D; - -+ MCUtil.scheduleTask(10, () -> { - this.world.playSound((EntityHuman) null, d0, (double) j + 0.5D, d2, SoundEffects.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -- } -+ }, "Chest Sounds"); - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -84,11 +107,13 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - public void d() { - ++this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doOpenLogic(); // Paper - } - - public void f() { - --this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doCloseLogic(); // Paper - } - - public boolean a(EntityHuman entityhuman) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index e4b59a85ee9b435b2e86d4c7d78b7224773f6967..ba046cffdd8331c7e0427f19fa54d0c7a99077d9 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -84,6 +84,7 @@ public abstract class IBlockDataHolder { - return Collections.unmodifiableCollection(this.b.keySet()); - } - -+ public > boolean contains(IBlockState iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER - public > boolean b(IBlockState iblockstate) { - return this.b.containsKey(iblockstate); - } diff --git a/Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch b/Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch deleted file mode 100644 index 8aea8a8dfae8..000000000000 --- a/Spigot-Server-Patches/0024-Further-improve-server-tick-loop.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:09:29 -0600 -Subject: [PATCH] Further improve server tick loop - -Improves how the catchup buffer is handled, allowing it to roll both ways -increasing the effeciency of the thread sleep so it only will sleep once. - -Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions - -Previous implementation did not calculate TPS correctly. -Switch to a realistic rolling average and factor in std deviation as an extra reporting variable - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9ba05ab7ec97896349f4b754f2993cda9ab1bbfd..add4f149fd31d1420d825b646b3e088808e5896b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -253,7 +253,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; - public CommandDispatcher vanillaCommandDispatcher; -@@ -262,7 +262,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 5000L && this.nextTick - this.lastOverloadTime >= 30000L) { // CraftBukkit - long j = i / 50L; - - if (server.getWarnOnOverload()) // CraftBukkit -- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); -+ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); - this.nextTick += j * 50L; - this.lastOverloadTime = this.nextTick; - } - -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) - { -- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; -- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) -- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) -- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) -+ final long diff = curTime - tickSection; -+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); -+ tps1.add(currentTps, diff); -+ tps5.add(currentTps, diff); -+ tps15.add(currentTps, diff); -+ // Backwards compat with bad plugins -+ recentTps[0] = tps1.getAverage(); -+ recentTps[1] = tps5.getAverage(); -+ recentTps[2] = tps15.getAverage(); -+ // Paper end - tickSection = curTime; - } - // Spigot end - -- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit -+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time -+ lastTick = curTime; - this.nextTick += 50L; - GameProfilerTick gameprofilertick = GameProfilerTick.a("Server"); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c66be5b9f304878f9179faba433f2e844bcee72c..eeaf100f73bb10e0a49400795f568438982f7cfa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2121,6 +2121,17 @@ public final class CraftServer implements Server { - return CraftMagicNumbers.INSTANCE; - } - -+ // Paper - Add getTPS API - Further improve tick loop -+ @Override -+ public double[] getTPS() { -+ return new double[] { -+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() -+ }; -+ } -+ // Paper end -+ - // Spigot start - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { -diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -index f5b6dec1cbe7501ce2ee9125920e810bc94670cc..e62890433ffbe0b4e48942fe6c38b599a19e58fd 100644 ---- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java -+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -@@ -24,22 +24,30 @@ public class TicksPerSecondCommand extends Command - return true; - } - -- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); -- for ( double tps : MinecraftServer.getServer().recentTps ) -- { -- sb.append( format( tps ) ); -- sb.append( ", " ); -+ // Paper start - Further improve tick handling -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int i = 0; i < tps.length; i++) { -+ tpsAvg[i] = format( tps[i] ); -+ } -+ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); -+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { -+ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ if (!hasShownMemoryWarning) { -+ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); -+ hasShownMemoryWarning = true; -+ } - } -- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); -- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " -- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ // Paper end - - return true; - } - -- private String format(double tps) -+ private boolean hasShownMemoryWarning; // Paper -+ private static String format(double tps) // Paper - Made static - { - return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() -- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise - } - } diff --git a/Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch b/Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch deleted file mode 100644 index ae353e8f8a6d..000000000000 --- a/Spigot-Server-Patches/0025-Only-refresh-abilities-if-needed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:12:03 -0600 -Subject: [PATCH] Only refresh abilities if needed - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index cc471418b37a745ecea1af964e81bc0362cf7d94..fb792de46ff80a6bad77a47954861cddfd17f2d9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1439,12 +1439,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.isFlying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { - throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); - } - - getHandle().abilities.isFlying = value; -- getHandle().updateAbilities(); -+ if (needsUpdate) getHandle().updateAbilities(); // Paper - Only refresh abilities if needed - } - - @Override diff --git a/Spigot-Server-Patches/0026-Entity-Origin-API.patch b/Spigot-Server-Patches/0026-Entity-Origin-API.patch deleted file mode 100644 index 60fd7b5fbedf..000000000000 --- a/Spigot-Server-Patches/0026-Entity-Origin-API.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 23:45:08 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 4f6f6f51f9807bafa88482c0fe776c8b163107d7..ce6572df63c4e7341708aee60330fb214a3fe416 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -190,6 +190,7 @@ public class NBTTagList extends NBTList { - return new int[0]; - } - -+ public final double getDoubleAt(int i) { return this.h(i); } // Paper - OBFHELPER - public double h(int i) { - if (i >= 0 && i < this.list.size()) { - NBTBase nbtbase = (NBTBase) this.list.get(i); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 4170743875d2fb16987e513713b2d141918219a5..701b00e65c4d5eb66e974f8d622eecef0f744f82 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1246,6 +1246,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ // Paper start - Set origin location when the entity is being added to the world -+ if (entity.origin == null) { -+ entity.origin = entity.getBukkitEntity().getLocation(); -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cae9da158f54438d2a397665c7ce964f6f755469..83006297e59971f4c358eacc3da586417982540c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -247,6 +247,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -+ public org.bukkit.Location origin; // Paper - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -1625,6 +1626,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.bukkitEntity.storeBukkitValues(nbttagcompound); - } - // CraftBukkit end -+ // Paper start - Save the entity's origin location -+ if (this.origin != null) { -+ nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); -+ } -+ // Paper end - return nbttagcompound; - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT"); -@@ -1747,6 +1753,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - Restore the entity's origin location -+ NBTTagList originTag = nbttagcompound.getList("Paper.Origin", 6); -+ if (!originTag.isEmpty()) { -+ origin = new org.bukkit.Location(world.getWorld(), originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); -+ } -+ // Paper end -+ - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded"); -@@ -1808,6 +1821,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - protected abstract void saveData(NBTTagCompound nbttagcompound); - -+ protected final NBTTagList createList(double... adouble) { return a(adouble); } // Paper - OBFHELPER - protected NBTTagList a(double... adouble) { - NBTTagList nbttaglist = new NBTTagList(); - double[] adouble1 = adouble; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 901522f24b8bc58861e46eda400dbab92bb6401d..3f10e41b18e09186635fd6f7c653b04db7b39d8e 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -293,6 +293,14 @@ public class EntityFallingBlock extends Entity { - this.block = Blocks.SAND.getBlockData(); - } - -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - public void a(boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 4f4b2b8d58223fa22d6a7af5c94cfb36399b9641..535e7d7297d81026b8586d5049b72fa65519b464 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -120,6 +120,14 @@ public class EntityTNTPrimed extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.setFuseTicks(nbttagcompound.getShort("Fuse")); -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 3cf81734c8580f4d88ea97b6ac737a370b413c84..220bad90bbb9a90c3f23562bf0fb109fce379682 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1062,4 +1062,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public Location getOrigin() { -+ Location origin = getHandle().origin; -+ return origin == null ? null : origin.clone(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch b/Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch deleted file mode 100644 index 7abd9f5960c6..000000000000 --- a/Spigot-Server-Patches/0027-Prevent-tile-entity-and-entity-crashes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:52:34 -0600 -Subject: [PATCH] Prevent tile entity and entity crashes - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 62735e7908f86e31f7a89ce2071ddebe176c0385..87e37c38825ad20fc11f41ea2a4512753266d2b4 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -737,11 +737,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - gameprofilerfiller.exit(); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking block entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block entity being ticked"); -- -- tileentity.a(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ throwable.printStackTrace(); -+ tilesThisCycle--; -+ this.tileEntityListTick.remove(tileTickPosition--); -+ continue; -+ // Paper end - // Spigot start - } finally { - tileentity.tickTimer.stopTiming(); -@@ -806,11 +808,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - consumer.accept(entity); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -- -- entity.appendEntityCrashDetails(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ throwable.printStackTrace(); -+ entity.dead = true; -+ return; -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 9ebd91e1309938f81583eb3d4dd97fd39bcc930a..58789a6e285c31947508deae37caefe7e182278c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -208,7 +208,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return IRegistry.BLOCK_ENTITY_TYPE.getKey(this.getTileType()) + " // " + this.getClass().getCanonicalName(); - }); - if (this.world != null) { -- CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.getBlock()); -+ // Paper start - Prevent TileEntity and Entity crashes -+ IBlockData block = this.getBlock(); -+ if (block != null) { -+ CrashReportSystemDetails.a(crashreportsystemdetails, this.position, block); -+ } -+ // Paper end - CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.world.getType(this.position)); - } - } diff --git a/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch b/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch deleted file mode 100644 index 69c16929401e..000000000000 --- a/Spigot-Server-Patches/0028-Configurable-top-of-nether-void-damage.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 1 Mar 2016 23:58:50 -0600 -Subject: [PATCH] Configurable top of nether void damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d16ae924bcbe31c964f7fb448757c748e5c4418c..4bba6977a0287837b8927718c040ac61463f0469 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -134,4 +134,19 @@ public class PaperWorldConfig { - if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); - if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); - } -+ -+ public int netherVoidTopDamageHeight; -+ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } -+ private void netherVoidTopDamageHeight() { -+ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); -+ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); -+ -+ if (PaperConfig.version < 18) { -+ boolean legacy = getBoolean("nether-ceiling-void-damage", false); -+ if (legacy) { -+ netherVoidTopDamageHeight = 128; -+ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index dce47ec1fc186d12ffa30bfd3d71870aecb95d40..cf92de7c138ef9cbbc1263bee29b9d0017b45827 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -500,9 +500,16 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance *= 0.5F; - } - -+ // Paper start - Configurable nether ceiling damage -+ -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - if (!this.world.isClientSide) { - this.setFlag(0, this.fireTicks > 0); -@@ -595,6 +602,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.setFireTicks(0); - } - -+ // Paper start -+ protected void performVoidDamage() { -+ if (this.locY() < -64.0D || (this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER -+ && world.paperConfig.doNetherTopVoidDamage() -+ && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { -+ this.doVoidDamage(); -+ } -+ } -+ // Paper end -+ -+ protected final void doVoidDamage() { this.an(); } // Paper - OBFHELPER - protected void an() { - this.die(); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 37785b27c3d9ffd010f09f53b2ca09941f609872..1f94cc096d95129d85a6278b1e369729df93d27d 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -330,9 +330,15 @@ public abstract class EntityMinecartAbstract extends Entity { - this.setDamage(this.getDamage() - 1.0F); - } - -+ // Paper start - Configurable nether ceiling damage -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - // this.doPortalTick(); // CraftBukkit - handled in postTick - if (this.world.isClientSide) { diff --git a/Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch b/Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch deleted file mode 100644 index 386f7f1615a1..000000000000 --- a/Spigot-Server-Patches/0029-Check-online-mode-before-converting-and-renaming-pla.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:03:55 -0600 -Subject: [PATCH] Check online mode before converting and renaming player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index c3a1b5943b0dad8701d566c45b9b474dac7e5c8a..191c9e9a00b9871038f60d54bc22620322f6bdbd 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -56,7 +56,7 @@ public class WorldNBTStorage { - File file = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat"); - // Spigot Start - boolean usingWrongFile = false; -- if ( !file.exists() ) -+ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first - { - file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); - if ( file.exists() ) diff --git a/Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch b/Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch deleted file mode 100644 index 4352384dba5b..000000000000 --- a/Spigot-Server-Patches/0030-Always-tick-falling-blocks.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 00:32:25 -0600 -Subject: [PATCH] Always tick falling blocks - - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 69c5d4e51ebf747d931fadc819973e36f001f5bc..58d22363124a9343188d8c19476e5a92f2f0b80b 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -91,6 +91,7 @@ public class ActivationRange - || entity instanceof EntityFireball - || entity instanceof EntityLightning - || entity instanceof EntityTNTPrimed -+ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks - || entity instanceof EntityEnderCrystal - || entity instanceof EntityFireworks - || entity instanceof EntityThrownTrident ) diff --git a/Spigot-Server-Patches/0031-Configurable-end-credits.patch b/Spigot-Server-Patches/0031-Configurable-end-credits.patch deleted file mode 100644 index 202de912027c..000000000000 --- a/Spigot-Server-Patches/0031-Configurable-end-credits.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctorDark -Date: Wed, 16 Mar 2016 02:21:39 -0500 -Subject: [PATCH] Configurable end credits - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4bba6977a0287837b8927718c040ac61463f0469..e6e18f309dc09ea9416ea37dcc697ddc2b571a96 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -149,4 +149,10 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean disableEndCredits; -+ private void disableEndCredits() { -+ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -+ log("End credits disabled: " + disableEndCredits); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5ef8b66cf266488df75ce7399596f75273b90761..808bb68b3c5115b1219a65d0dd253bd60d543652 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -191,7 +191,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -- private boolean cd; -+ private boolean cd; private void setHasSeenCredits(boolean has) { this.cd = has; } // Paper - OBFHELPER - private final RecipeBookServer recipeBook = new RecipeBookServer(); - private Vec3D cf; - private int cg; -@@ -896,6 +896,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.decouple(); - this.getWorldServer().removePlayer(this); - if (!this.viewingCredits) { -+ if (world.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits - this.viewingCredits = true; - this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.e, this.cd ? 0.0F : 1.0F)); - this.cd = true; diff --git a/Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch b/Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch deleted file mode 100644 index 85ee81828685..000000000000 --- a/Spigot-Server-Patches/0032-Fix-lag-from-explosions-processing-dead-entities.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Iceee -Date: Wed, 2 Mar 2016 01:39:52 -0600 -Subject: [PATCH] Fix lag from explosions processing dead entities - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 9c1ad56e4362cd86e7ffe2aef7fd9ec301cf9002..7786a06ba09aacaa70c346e85a9eeed9f2ffec6e 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -182,7 +182,7 @@ public class Explosion { - int i1 = MathHelper.floor(this.posY + (double) f2 + 1.0D); - int j1 = MathHelper.floor(this.posZ - (double) f2 - 1.0D); - int k1 = MathHelper.floor(this.posZ + (double) f2 + 1.0D); -- List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); -+ List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities - Vec3D vec3d = new Vec3D(this.posX, this.posY, this.posZ); - - for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/Spigot-Server-Patches/0033-Optimize-explosions.patch b/Spigot-Server-Patches/0033-Optimize-explosions.patch deleted file mode 100644 index 78ab387974cb..000000000000 --- a/Spigot-Server-Patches/0033-Optimize-explosions.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 11:59:48 -0600 -Subject: [PATCH] Optimize explosions - -The process of determining an entity's exposure from explosions can be -expensive when there are hundreds or more entities in range. - -This patch adds a per-tick cache that is used for storing and retrieving -an entity's exposure during an explosion. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e6e18f309dc09ea9416ea37dcc697ddc2b571a96..4881b03d470646843bad1bc343eb6a6ab9072d8e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -155,4 +155,10 @@ public class PaperWorldConfig { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); - log("End credits disabled: " + disableEndCredits); - } -+ -+ public boolean optimizeExplosions; -+ private void optimizeExplosions() { -+ optimizeExplosions = getBoolean("optimize-explosions", false); -+ log("Optimize explosions: " + optimizeExplosions); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index add4f149fd31d1420d825b646b3e088808e5896b..06071e15851d5d27f1c9a0d60a764a6214e0ba0f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1326,6 +1326,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant>> 32)); -+ temp = Double.doubleToLongBits(posY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(posZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ return result; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 87e37c38825ad20fc11f41ea2a4512753266d2b4..06455fb3916e347c075c6aa84977dca7e25760c2 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -136,6 +136,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; -+ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - - public CraftWorld getWorld() { - return this.world; diff --git a/Spigot-Server-Patches/0034-Disable-explosion-knockback.patch b/Spigot-Server-Patches/0034-Disable-explosion-knockback.patch deleted file mode 100644 index 10bd640ecfbc..000000000000 --- a/Spigot-Server-Patches/0034-Disable-explosion-knockback.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:48:03 -0600 -Subject: [PATCH] Disable explosion knockback - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4881b03d470646843bad1bc343eb6a6ab9072d8e..2222c1bb5f8625eee4d88946e4bfdfa2fe598977 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -161,4 +161,9 @@ public class PaperWorldConfig { - optimizeExplosions = getBoolean("optimize-explosions", false); - log("Optimize explosions: " + optimizeExplosions); - } -+ -+ public boolean disableExplosionKnockback; -+ private void disableExplosionKnockback(){ -+ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 98f5f1dcd0abf9272533bf3801bab316c9f0a12c..3598db4144141a8701a2879be13a81a8ee48018c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1283,6 +1283,7 @@ public abstract class EntityLiving extends Entity { - } - } - -+ boolean knockbackCancelled = world.paperConfig.disableExplosionKnockback && damagesource.isExplosion() && this instanceof EntityHuman; // Paper - Disable explosion knockback - if (flag1) { - if (flag) { - this.world.broadcastEntityEffect(this, (byte) 29); -@@ -1301,6 +1302,7 @@ public abstract class EntityLiving extends Entity { - b0 = 2; - } - -+ if (!knockbackCancelled) // Paper - Disable explosion knockback - this.world.broadcastEntityEffect(this, b0); - } - -@@ -1324,6 +1326,7 @@ public abstract class EntityLiving extends Entity { - } - } - -+ if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { - SoundEffect soundeffect = this.getSoundDeath(); -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 6a7af2c0c3c294b10c6ddbf98babb0f30d7d5f56..618cf4e0d71b4b04085807314e79a02785f8a498 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -217,14 +217,14 @@ public class Explosion { - double d14 = d13; - - if (entity instanceof EntityLiving) { -- d14 = EnchantmentProtection.a((EntityLiving) entity, d13); -+ d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback - } - - entity.setMot(entity.getMot().add(d8 * d14, d9 * d14, d10 * d14)); - if (entity instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) entity; - -- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying)) { -+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying) && !world.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback - this.n.put(entityhuman, new Vec3D(d8 * d13, d9 * d13, d10 * d13)); - } - } diff --git a/Spigot-Server-Patches/0035-Disable-thunder.patch b/Spigot-Server-Patches/0035-Disable-thunder.patch deleted file mode 100644 index 9887bf87d883..000000000000 --- a/Spigot-Server-Patches/0035-Disable-thunder.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:52:43 -0600 -Subject: [PATCH] Disable thunder - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2222c1bb5f8625eee4d88946e4bfdfa2fe598977..083e421f8496b5336af473b108498ed28b984774 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -166,4 +166,9 @@ public class PaperWorldConfig { - private void disableExplosionKnockback(){ - disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); - } -+ -+ public boolean disableThunder; -+ private void disableThunder() { -+ disableThunder = getBoolean("disable-thunder", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 701b00e65c4d5eb66e974f8d622eecef0f744f82..6e8e9067a43d0fb88683be733fb3d138f35d6cf0 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -586,7 +586,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - gameprofilerfiller.enter("thunder"); - BlockPosition blockposition; - -- if (flag && this.W() && this.random.nextInt(100000) == 0) { -+ if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); diff --git a/Spigot-Server-Patches/0036-Disable-ice-and-snow.patch b/Spigot-Server-Patches/0036-Disable-ice-and-snow.patch deleted file mode 100644 index 911b86d0329a..000000000000 --- a/Spigot-Server-Patches/0036-Disable-ice-and-snow.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:57:24 -0600 -Subject: [PATCH] Disable ice and snow - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 083e421f8496b5336af473b108498ed28b984774..2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -171,4 +171,9 @@ public class PaperWorldConfig { - private void disableThunder() { - disableThunder = getBoolean("disable-thunder", false); - } -+ -+ public boolean disableIceAndSnow; -+ private void disableIceAndSnow(){ -+ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 6e8e9067a43d0fb88683be733fb3d138f35d6cf0..474e91b1a0a3fc2c5abb238f058e50ad787c22d9 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -610,7 +610,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (this.random.nextInt(16) == 0) { -+ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow - blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); - BlockPosition blockposition1 = blockposition.down(); - BiomeBase biomebase = this.getBiome(blockposition); diff --git a/Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch b/Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch deleted file mode 100644 index 0ced9bb837ef..000000000000 --- a/Spigot-Server-Patches/0037-Configurable-mob-spawner-tick-rate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 15:03:53 -0600 -Subject: [PATCH] Configurable mob spawner tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f7a5a4a5a7b29750cfd777e0bc5d19a14e93fa2..4de86b09c6bc3c1974ce61b550ccb73d37f6f170 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -176,4 +176,9 @@ public class PaperWorldConfig { - private void disableIceAndSnow(){ - disableIceAndSnow = getBoolean("disable-ice-and-snow", false); - } -+ -+ public int mobSpawnerTickRate; -+ private void mobSpawnerTickRate() { -+ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 8d8b03074df1635946f81bec0feae18d2f3e20aa..76c98d576d3e567ec4482b30219f5a9107cb9703 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -41,6 +41,7 @@ public abstract class MobSpawnerAbstract { - public int maxNearbyEntities = 6; - public int requiredPlayerRange = 16; - public int spawnRange = 4; -+ private int tickDelay = 0; // Paper - - public MobSpawnerAbstract() {} - -@@ -70,6 +71,10 @@ public abstract class MobSpawnerAbstract { - } - - public void c() { -+ // Paper start - Configurable mob spawner tick rate -+ if (spawnDelay > 0 && --tickDelay > 0) return; -+ tickDelay = this.a().paperConfig.mobSpawnerTickRate; -+ // Paper end - if (!this.h()) { - this.f = this.e; - } else { -@@ -84,18 +89,18 @@ public abstract class MobSpawnerAbstract { - world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); - world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - } - - this.f = this.e; - this.e = (this.e + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; - } else { -- if (this.spawnDelay == -1) { -+ if (this.spawnDelay < -tickDelay) { // Paper - this.i(); - } - - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - return; - } - diff --git a/Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch b/Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch deleted file mode 100644 index c6d021541762..000000000000 --- a/Spigot-Server-Patches/0038-Send-absolute-position-the-first-time-an-entity-is-s.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Wed, 2 Mar 2016 23:13:07 -0600 -Subject: [PATCH] Send absolute position the first time an entity is seen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 9ad74b380a92e3a563e1a891e81401d8b4707bcf..beb0beb716869978be6bc5a78ce3b6cf785c5aee 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -4,6 +4,7 @@ import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Pair; - import java.util.Collection; - import java.util.Collections; -+import java.util.HashSet; - import java.util.Iterator; - import java.util.List; - import java.util.Set; -@@ -52,7 +53,7 @@ public class EntityTrackerEntry { - private final Entity tracker; - private final int d; - private final boolean e; -- private final Consumer> f; -+ private final Consumer> f; private Consumer> getPacketConsumer() { return f; } // Paper - OBFHELPER - private long xLoc; - private long yLoc; - private long zLoc; -@@ -67,8 +68,23 @@ public class EntityTrackerEntry { - private boolean r; - // CraftBukkit start - private final Set trackedPlayers; -+ // Paper start -+ private java.util.Map trackedPlayerMap = null; -+ -+ /** -+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets -+ */ -+ public void sendPlayerPacket(EntityPlayer player, Packet packet) { -+ player.playerConnection.sendPacket(packet); -+ } -+ -+ public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { -+ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); -+ trackedPlayerMap = trackedPlayers; -+ } - - public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { -+ // Paper end - this.trackedPlayers = trackedPlayers; - // CraftBukkit end - this.m = Vec3D.ORIGIN; -@@ -189,7 +205,25 @@ public class EntityTrackerEntry { - } - - if (packet1 != null) { -- this.f.accept(packet1); -+ // paper start -+ if (trackedPlayerMap == null || packet1 instanceof PacketPlayOutEntityTeleport) { -+ this.f.accept((packet1)); -+ } else { -+ PacketPlayOutEntityTeleport teleportPacket = null; -+ -+ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { -+ if (viewer.getValue()) { -+ viewer.setValue(false); -+ if (teleportPacket == null) { -+ teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); -+ } -+ sendPlayerPacket(viewer.getKey(), teleportPacket); -+ } else { -+ sendPlayerPacket(viewer.getKey(), packet1); -+ } -+ } -+ } -+ // Paper end - } - - this.c(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 62245fa420390dc0a70ba9a95505dc46cd8aa64a..788a45d5426f0752509442aec2d28b1f32f63cb1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1303,10 +1303,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -- public final Set trackedPlayers = Sets.newHashSet(); -+ // Paper start -+ // Replace trackedPlayers Set with a Map. The value is true until the player receives -+ // their first update (which is forced to have absolute coordinates), false afterward. -+ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); -+ public Set trackedPlayers = trackedPlayerMap.keySet(); - - public EntityTracker(Entity entity, int i, int j, boolean flag) { -- this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayers); // CraftBukkit -+ this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper - this.tracker = entity; - this.trackingDistance = i; - this.e = SectionPosition.a(entity); -@@ -1388,7 +1392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); - // CraftBukkit end - -- if (flag1 && this.trackedPlayers.add(entityplayer)) { -+ if (flag1 && this.trackedPlayerMap.putIfAbsent(entityplayer, true) == null) { // Paper - this.trackerEntry.b(entityplayer); - } - } else if (this.trackedPlayers.remove(entityplayer)) { diff --git a/Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch b/Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch deleted file mode 100644 index a2c0b8f5b8ad..000000000000 --- a/Spigot-Server-Patches/0039-Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 23:30:53 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index c6914c8d2a3d1057c98537a3538097d3ac6149e0..f9b1ab0e19ff398a16b1452e86f1a165a4b54219 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -42,6 +42,11 @@ import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.craftbukkit.potion.CraftPotionUtil; - import org.bukkit.potion.PotionEffect; - // CraftBukkit end -+// Paper start -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.entity.Player; -+import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+// Paper end - - public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable { - -@@ -268,14 +273,31 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - } - - private void applyEffect(List list, MobEffectList effects, int i, int b0) { -+ // Paper - BeaconEffectEvent -+ applyEffect(list, effects, i, b0, true); -+ } -+ -+ private void applyEffect(List list, MobEffectList effects, int i, int b0, boolean isPrimary) { -+ // Paper - BeaconEffectEvent - { - Iterator iterator = list.iterator(); - - EntityHuman entityhuman; - -+ // Paper start - BeaconEffectEvent -+ org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffect(effects, i, b0, true, true)); -+ // Paper end -+ - while (iterator.hasNext()) { - entityhuman = (EntityHuman) iterator.next(); -- entityhuman.addEffect(new MobEffect(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ -+ // Paper start - BeaconEffectEvent -+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); -+ if (CraftEventFactory.callEvent(event).isCancelled()) continue; -+ PotionEffect eventEffect = event.getEffect(); -+ entityhuman.addEffect(new MobEffect(MobEffectList.fromId(eventEffect.getType().getId()), eventEffect.getDuration(), eventEffect.getAmplifier(), true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ // Paper end - } - } - } -@@ -298,10 +320,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - int i = getLevel(); - List list = getHumansInRange(); - -- applyEffect(list, this.primaryEffect, i, b0); -+ applyEffect(list, this.primaryEffect, i, b0, true); // Paper - BeaconEffectEvent - - if (hasSecondaryEffect()) { -- applyEffect(list, this.secondaryEffect, i, 0); -+ applyEffect(list, this.secondaryEffect, i, 0, false); // Paper - BeaconEffectEvent - } - } - diff --git a/Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch b/Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch deleted file mode 100644 index 75bd09e68524..000000000000 --- a/Spigot-Server-Patches/0040-Configurable-container-update-tick-rate.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 23:34:44 -0600 -Subject: [PATCH] Configurable container update tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4de86b09c6bc3c1974ce61b550ccb73d37f6f170..5a4c3a8c511f22c8c3240c9c7cd83a65119c1054 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -181,4 +181,9 @@ public class PaperWorldConfig { - private void mobSpawnerTickRate() { - mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); - } -+ -+ public int containerUpdateTickRate; -+ private void containerUpdateTickRate() { -+ containerUpdateTickRate = getInt("container-update-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 808bb68b3c5115b1219a65d0dd253bd60d543652..cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -210,6 +210,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean e; - public int ping; - public boolean viewingCredits; -+ private int containerUpdateDelay; // Paper - - // CraftBukkit start - public String displayName; -@@ -534,7 +535,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - --this.noDamageTicks; - } - -- this.activeContainer.c(); -+ // Paper start - Configurable container update tick rate -+ if (--containerUpdateDelay <= 0) { -+ this.activeContainer.c(); -+ containerUpdateDelay = world.paperConfig.containerUpdateTickRate; -+ } -+ // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { - this.closeInventory(); - this.activeContainer = this.defaultContainer; diff --git a/Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch b/Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch deleted file mode 100644 index bffebdb478e4..000000000000 --- a/Spigot-Server-Patches/0041-Use-UserCache-for-player-heads.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 2 Mar 2016 23:42:37 -0600 -Subject: [PATCH] Use UserCache for player heads - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 1a686e603feede34236dc43136ade71cfdc88214..42de897596ada4044df683dc5e8d5d750ee9c207 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -166,7 +166,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - if (name == null) { - setProfile(null); - } else { -- setProfile(new GameProfile(null, name)); -+ // Paper start - Use Online Players Skull -+ GameProfile newProfile = null; -+ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ if (player != null) newProfile = player.getProfile(); -+ if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); -+ // Paper end - } - - return true; diff --git a/Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch b/Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch deleted file mode 100644 index 54851e5ccf95..000000000000 --- a/Spigot-Server-Patches/0042-Disable-spigot-tick-limiters.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Mar 2016 23:45:17 -0600 -Subject: [PATCH] Disable spigot tick limiters - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 06455fb3916e347c075c6aa84977dca7e25760c2..26d9388badb0328735abf0319a42bd633c90dc4b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -707,9 +707,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tileEntityListTick.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -+ for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; - TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition); - // Spigot start diff --git a/Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch b/Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index 616ed8869e6a..000000000000 --- a/Spigot-Server-Patches/0043-Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Thu, 3 Mar 2016 00:09:38 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -This is a duplicate API from spigot, so use our duplicate subclass and -improve setPosition to use raw - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 15418868c2b92498139e66d913ee1c35b3abf0cf..cfd0af520dd3dcf364a3ffd03a74e3b9ee6045af 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -213,7 +213,7 @@ public abstract class PlayerList { - - // Spigot start - spawn location event - Player bukkitPlayer = entityplayer.getBukkitEntity(); -- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); -+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event - cserver.getPluginManager().callEvent(ev); - - Location loc = ev.getSpawnLocation(); -@@ -221,7 +221,10 @@ public abstract class PlayerList { - - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); -- entityplayer.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); -+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) -+ entityplayer.setPositionRaw(loc.getX(), loc.getY(), loc.getZ()); -+ entityplayer.setYawPitch(loc.getYaw(), loc.getPitch()); -+ // Paper end - // Spigot end - - // CraftBukkit - Moved message to after join -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cf92de7c138ef9cbbc1263bee29b9d0017b45827..10cbf66f06b31c9a4cae2359b3fbb9988abb9278 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -398,7 +398,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return d1 * d1 + d2 * d2 + d3 * d3 < d0 * d0; - } - -- protected void setYawPitch(float f, float f1) { -+ public void setYawPitch(float f, float f1) { // Paper - protected -> public - // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 - if (Float.isNaN(f)) { - f = 0; diff --git a/Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch b/Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch deleted file mode 100644 index 9c34c4ef30af..000000000000 --- a/Spigot-Server-Patches/0044-Configurable-Disabling-Cat-Chest-Detection.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:13:45 -0600 -Subject: [PATCH] Configurable Disabling Cat Chest Detection - -Offers a gameplay feature to stop cats from blocking chests - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5a4c3a8c511f22c8c3240c9c7cd83a65119c1054..70e074cdf2087e638af8e0f3878d0ef8eb7305cc 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -186,4 +186,9 @@ public class PaperWorldConfig { - private void containerUpdateTickRate() { - containerUpdateTickRate = getInt("container-update-tick-rate", 1); - } -+ -+ public boolean disableChestCatDetection; -+ private void disableChestCatDetection() { -+ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index b229faad99120c67b089f7680d800fbe594fe7da..b2c29cff5883868cb56a4e376ab946ac929abc94 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -312,6 +312,11 @@ public class BlockChest extends BlockChestAbstract implements I - } - - private static boolean b(GeneratorAccess generatoraccess, BlockPosition blockposition) { -+ // Paper start - Option to disable chest cat detection -+ if (((World) generatoraccess).paperConfig.disableChestCatDetection) { -+ return false; -+ } -+ // Paper end - List list = generatoraccess.a(EntityCat.class, new AxisAlignedBB((double) blockposition.getX(), (double) (blockposition.getY() + 1), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 2), (double) (blockposition.getZ() + 1))); - - if (!list.isEmpty()) { diff --git a/Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch b/Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch deleted file mode 100644 index f254df99675d..000000000000 --- a/Spigot-Server-Patches/0045-Ensure-commands-are-not-ran-async.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:17:12 -0600 -Subject: [PATCH] Ensure commands are not ran async - -Plugins calling Player.chat("/foo") or Server.dispatchCommand() could -trigger the server to execute a command while on another thread. - -These commands would then process EXPECTING to be on the main thread, leaving to -very hard to trace concurrency issues. - -This change will synchronize the command execution back to the main thread, causing a -big slowdown in execution but throwing an exception at same time to raise awareness -that it is happening so that plugin authors can fix their code to stop executing commands async. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index a39f58e0c60b5e3ccc3b725f1f4167d52b230e11..6a8567c355202560ee523c6dc68cac1ac3e562fd 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1853,6 +1853,29 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (!async && s.startsWith("/")) { -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { -+ final String fCommandLine = s; -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ Waitable wait = new Waitable() { -+ @Override -+ protected Object evaluate() { -+ chat(fCommandLine, false); -+ return null; -+ } -+ }; -+ minecraftServer.processQueue.add(wait); -+ try { -+ wait.get(); -+ return; -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing chat command", e.getCause()); -+ } -+ } -+ // Paper End - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f84fe5929cb7bcedff5fc587163380172bc1e8be..8e9547fc745e8244ca1f439770571ca1175ff632 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -762,6 +762,29 @@ public final class CraftServer implements Server { - Validate.notNull(commandLine, "CommandLine cannot be null"); - org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot - -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { -+ final CommandSender fSender = sender; -+ final String fCommandLine = commandLine; -+ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); -+ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { -+ @Override -+ protected Boolean evaluate() { -+ return dispatchCommand(fSender, fCommandLine); -+ } -+ }; -+ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing dispatch command", e.getCause()); -+ } -+ } -+ // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index ddef523ea8762c927f37f7d16d581e43367e8c6b..70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread { - public void run() { - try { - org.spigotmc.AsyncCatcher.enabled = false; // Spigot -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); - } finally { - try { -diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java -index aeed7697254af17ffefe8e578353ad216e15f9f3..9f7d2ef932ab41cef5d3d0736d20a7c7e4a2c888 100644 ---- a/src/main/java/org/spigotmc/AsyncCatcher.java -+++ b/src/main/java/org/spigotmc/AsyncCatcher.java -@@ -6,6 +6,7 @@ public class AsyncCatcher - { - - public static boolean enabled = true; -+ public static boolean shuttingDown = false; // Paper - - public static void catchOp(String reason) - { -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index d76e01d73da7413f192132134caf201d7780e3f1..a45155cdd7d7a302c119f75bfe2b428ae5e8ab47 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -43,6 +43,7 @@ public class RestartCommand extends Command - private static void restart(final String restartScript) - { - AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - try - { - String[] split = restartScript.split( " " ); diff --git a/Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch b/Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch deleted file mode 100644 index 48622f89ba36..000000000000 --- a/Spigot-Server-Patches/0046-All-chunks-are-slime-spawn-chunks-toggle.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Thu, 3 Mar 2016 01:19:22 -0600 -Subject: [PATCH] All chunks are slime spawn chunks toggle - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 70e074cdf2087e638af8e0f3878d0ef8eb7305cc..416a6760883cb40367535c7c5acd779742bb8af5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -191,4 +191,9 @@ public class PaperWorldConfig { - private void disableChestCatDetection() { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } -+ -+ public boolean allChunksAreSlimeChunks; -+ private void allChunksAreSlimeChunks() { -+ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 292789d76da400d15d0742e2e0979f4ac6ec4b75..01d5b0db9a34d88172e8c7c84c4e1d0b2562217c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -325,7 +325,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(blockposition); -- boolean flag = SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot -+ boolean flag = generatoraccess.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper - - if (random.nextInt(10) == 0 && flag && blockposition.getY() < 40) { - return a(entitytypes, generatoraccess, enummobspawn, blockposition, random); diff --git a/Spigot-Server-Patches/0047-Expose-server-CommandMap.patch b/Spigot-Server-Patches/0047-Expose-server-CommandMap.patch deleted file mode 100644 index 65a77037bc0d..000000000000 --- a/Spigot-Server-Patches/0047-Expose-server-CommandMap.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:15:57 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3b29f94dcfb98ba7cdd61c7b398dbc8fc56f5aef..9142a4813414d125ebff32e1521659da525e7337 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1760,6 +1760,7 @@ public final class CraftServer implements Server { - return helpMap; - } - -+ @Override // Paper - add override - public SimpleCommandMap getCommandMap() { - return commandMap; - } diff --git a/Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch b/Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch deleted file mode 100644 index 75179086ebbd..000000000000 --- a/Spigot-Server-Patches/0048-Be-a-bit-more-informative-in-maxHealth-exception.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 3 Mar 2016 02:18:39 -0600 -Subject: [PATCH] Be a bit more informative in maxHealth exception - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 422e5578a0b9ae0ddc98e4c43d63fcb5e535e5d2..9f7334ae769438cdd77508000e7721f57b30e225 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -111,7 +111,10 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHealth(double health) { - health = (float) health; - if ((health < 0) || (health > getMaxHealth())) { -- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); -+ // Paper - Be more informative -+ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health -+ + ". (attribute base value: " + this.getHandle().getAttributeInstance(GenericAttributes.MAX_HEALTH).getBaseValue() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - - getHandle().setHealth((float) health); diff --git a/Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch b/Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index 2c15cce7ce71..000000000000 --- a/Spigot-Server-Patches/0049-Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 02:32:10 -0600 -Subject: [PATCH] Player Tab List and Title APIs - - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5f1c5dd7902f6cff5acae05e8c6bf58a1ba5bdf1..df459918c14589155a574730205cb35d463b8079 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -171,6 +171,11 @@ public class PacketDataSerializer extends ByteBuf { - public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { - return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); - } -+ -+ @Deprecated -+ public PacketDataSerializer writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { -+ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); -+ } - // Paper end - - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index e96fa348a37a39c381b6659f612232933686c2a7..a002125e454f8a86924e9010e0b20a95742fa04b 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -364,6 +364,7 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { - } - - } -+ // Paper start -+ public net.md_5.bungee.api.chat.BaseComponent[] components; -+ -+ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) { -+ this.a = action; -+ this.components = components; -+ this.c = fadeIn; -+ this.d = stay; -+ this.e = fadeOut; -+ } -+ // Paper end - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -@@ -55,6 +66,8 @@ public class PacketPlayOutTitle implements Packet { - // Paper start - if (this.adventure$text != null) { - packetdataserializer.writeComponent(this.adventure$text); -+ } else if (this.components != null) { -+ packetdataserializer.writeComponent(this.components); - } else - // Paper end - packetdataserializer.a(this.b); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 62f8d96f996ece87b7ab8d5d05d1dc214d10dbfa..9837f7364f3efd0aa22d33058bec369c41cd03ef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; - import com.google.common.io.BaseEncoding; -@@ -238,6 +239,96 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -+ // Paper start -+ @Override -+ public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { -+ if (header != null) { -+ String headerJson = net.md_5.bungee.chat.ComponentSerializer.toString(header); -+ playerListHeader = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(headerJson); -+ } else { -+ playerListHeader = null; -+ } -+ -+ if (footer != null) { -+ String footerJson = net.md_5.bungee.chat.ComponentSerializer.toString(footer); -+ playerListFooter = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(footerJson); -+ } else { -+ playerListFooter = null; -+ } -+ -+ updatePlayerListHeaderFooter(); -+ } -+ -+ @Override -+ public void setPlayerListHeaderFooter(BaseComponent header, BaseComponent footer) { -+ this.setPlayerListHeaderFooter(header == null ? null : new BaseComponent[]{header}, -+ footer == null ? null : new BaseComponent[]{footer}); -+ } -+ -+ -+ @Override -+ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, (BaseComponent[]) null, fadeInTicks, stayTicks, fadeOutTicks)); -+ } -+ -+ @Override -+ public void setSubtitle(BaseComponent[] subtitle) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, subtitle, 0, 0, 0)); -+ } -+ -+ @Override -+ public void setSubtitle(BaseComponent subtitle) { -+ setSubtitle(new BaseComponent[]{subtitle}); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent[] title) { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, title, 0, 0, 0)); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent title) { -+ showTitle(new BaseComponent[]{title}); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent[] title, BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); -+ setSubtitle(subtitle); -+ showTitle(title); -+ } -+ -+ @Override -+ public void showTitle(BaseComponent title, BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { -+ setTitleTimes(fadeInTicks, stayTicks, fadeOutTicks); -+ setSubtitle(subtitle); -+ showTitle(title); -+ } -+ -+ @Override -+ public void sendTitle(Title title) { -+ Preconditions.checkNotNull(title, "Title is null"); -+ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); -+ setSubtitle(title.getSubtitle() == null ? new BaseComponent[0] : title.getSubtitle()); -+ showTitle(title.getTitle()); -+ } -+ -+ @Override -+ public void updateTitle(Title title) { -+ Preconditions.checkNotNull(title, "Title is null"); -+ setTitleTimes(title.getFadeIn(), title.getStay(), title.getFadeOut()); -+ if (title.getSubtitle() != null) { -+ setSubtitle(title.getSubtitle()); -+ } -+ showTitle(title.getTitle()); -+ } -+ -+ @Override -+ public void hideTitle() { -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, (BaseComponent[]) null, 0, 0, 0)); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper diff --git a/Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch b/Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch deleted file mode 100644 index 3d814228e9a2..000000000000 --- a/Spigot-Server-Patches/0050-Ensure-inv-drag-is-in-bounds.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:33:53 -0600 -Subject: [PATCH] Ensure inv drag is in bounds - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 2410214a300407ef20ea14244db5db2ebede2759..e9733fd9dac89d31dbad391cb22a8c84216045db 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -239,7 +239,7 @@ public abstract class Container { - this.d(); - } - } else if (this.h == 1) { -- Slot slot = (Slot) this.slots.get(i); -+ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds - - itemstack1 = playerinventory.getCarried(); - if (slot != null && a(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.dragType == 2 || itemstack1.getCount() > this.i.size()) && this.b(slot)) { diff --git a/Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch b/Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch deleted file mode 100644 index 05bc8dac6dc0..000000000000 --- a/Spigot-Server-Patches/0051-Change-implementation-of-tile-entity-removal-list.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:39:54 -0600 -Subject: [PATCH] Change implementation of (tile)entity removal list - -use sets for faster removal - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 26d9388badb0328735abf0319a42bd633c90dc4b..33469b719d679c65d4bcb8366008e6e107eb3a0b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -89,7 +89,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final List tileEntityList = Lists.newArrayList(); - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); -- protected final List tileEntityListUnload = Lists.newArrayList(); -+ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); - public final Thread serverThread; - private final boolean debugWorld; - private int d; diff --git a/Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch b/Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch deleted file mode 100644 index 7c478fce6a8d..000000000000 --- a/Spigot-Server-Patches/0052-Add-configurable-portal-search-radius.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:46:17 -0600 -Subject: [PATCH] Add configurable portal search radius - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 416a6760883cb40367535c7c5acd779742bb8af5..670efbe53241a0ae32d618c83da601ccc1f26e37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -196,4 +196,13 @@ public class PaperWorldConfig { - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); - } -+ -+ public int portalSearchRadius; -+ public int portalCreateRadius; -+ public boolean portalSearchVanillaDimensionScaling; -+ private void portalSearchRadius() { -+ portalSearchRadius = getInt("portal-search-radius", 128); -+ portalCreateRadius = getInt("portal-create-radius", 16); -+ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 10cbf66f06b31c9a4cae2359b3fbb9988abb9278..40eb6bae8ca4e2b57d4f91547808eb00ac1fd455 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2613,7 +2613,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - double d4 = DimensionManager.a(this.world.getDimensionManager(), worldserver.getDimensionManager()); - BlockPosition blockposition = new BlockPosition(MathHelper.a(this.locX() * d4, d0, d2), this.locY(), MathHelper.a(this.locZ() * d4, d1, d3)); - // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); -+ // Paper start -+ int portalSearchRadius = worldserver.paperConfig.portalSearchRadius; -+ if (world.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER -+ portalSearchRadius = (int) (portalSearchRadius / worldserver.getDimensionManager().getCoordinateScale()); -+ } -+ // Paper end -+ CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver.paperConfig.portalCreateRadius); // Paper start - configurable portal radius - if (event == null) { - return null; - } -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -index 7b8e8a7dae47ecc42a57e3f9444caa2ee5b1ef3b..77dfa7eaf178baa55041a829c9dec4851efeedfc 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -@@ -31,7 +31,7 @@ public class PortalTravelAgent { - - public Optional findPortal(BlockPosition blockposition, boolean flag) { - // CraftBukkit start -- return findPortal(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortal(blockposition, flag ? world.paperConfig.portalCreateRadius : world.paperConfig.portalSearchRadius); // Paper - search Radius - } - - public Optional findPortal(BlockPosition blockposition, int i) { diff --git a/Spigot-Server-Patches/0053-Add-velocity-warnings.patch b/Spigot-Server-Patches/0053-Add-velocity-warnings.patch deleted file mode 100644 index eba37e215baa..000000000000 --- a/Spigot-Server-Patches/0053-Add-velocity-warnings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:48:12 -0600 -Subject: [PATCH] Add velocity warnings - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 96d4049f8a42f00dbbc092b391ae11c1326a5501..f6a1d52239216984da4a9c87312c6ed085213935 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -262,6 +262,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { - ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 220bad90bbb9a90c3f23562bf0fb109fce379682..a58626b1a0160983a738a45c8a1d411eb347e6a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -424,10 +424,41 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public void setVelocity(Vector velocity) { - Preconditions.checkArgument(velocity != null, "velocity"); - velocity.checkFinite(); -+ // Paper start - Warn server owners when plugins try to set super high velocities -+ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { -+ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); -+ } -+ // Paper end -+ - entity.setMot(CraftVector.toNMS(velocity)); - entity.velocityChanged = true; - } - -+ // Paper start -+ /** -+ * Checks if the given velocity is not necessarily safe in all situations. -+ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be -+ * a detriment to performance on the server. -+ * -+ * It is not to be used as a hard rule of any sort. -+ * Paper only uses it to warn server owners in watchdog crashes. -+ * -+ * @param vel incoming velocity to check -+ * @return if the velocity has the potential to be a performance detriment -+ */ -+ private static boolean isUnsafeVelocity(Vector vel) { -+ final double x = vel.getX(); -+ final double y = vel.getY(); -+ final double z = vel.getZ(); -+ -+ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { -+ return true; -+ } -+ -+ return false; -+ } -+ // Paper end -+ - @Override - public double getHeight() { - return getHandle().getHeight(); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 1b3a14784cac8e855633fae6172ad5479ebe9877..69e5054886b5858664fed333aca8c25a76e5cb11 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -80,7 +80,19 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); - log.log( Level.SEVERE, "near " + net.minecraft.world.level.World.lastPhysicsProblem ); - } -- // -+ // Paper start - Warn in watchdog if an excessive velocity was ever set -+ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) -+ { -+ log.log( Level.SEVERE, "------------------------------" ); -+ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); -+ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); -+ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); -+ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) -+ { -+ log.log( Level.SEVERE, "\t\t" + stack ); -+ } -+ } -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch b/Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch deleted file mode 100644 index 789bab195fca..000000000000 --- a/Spigot-Server-Patches/0054-Configurable-inter-world-teleportation-safety.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Thu, 3 Mar 2016 02:50:31 -0600 -Subject: [PATCH] Configurable inter-world teleportation safety - -People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation -safety check. - -To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest -or door block. While they are in this block, they accept a teleport request from a player within a different world. Once -the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a -player's skybase. - -Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png -The wanted destination was on top of the emerald block however the player ended on top of the diamond block. -This only is the case if the player is teleporting between worlds. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 670efbe53241a0ae32d618c83da601ccc1f26e37..abbbe1786eb68af02f9d39650aad730ac44aac8a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -205,4 +205,9 @@ public class PaperWorldConfig { - portalCreateRadius = getInt("portal-create-radius", 16); - portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); - } -+ -+ public boolean disableTeleportationSuffocationCheck; -+ private void disableTeleportationSuffocationCheck() { -+ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1ad5863dc12b2288a38efed71b7fa4b84296d96d..f2228933719a2325a518be15237fedf56c994d1f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -863,7 +863,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (fromWorld == toWorld) { - entity.playerConnection.teleport(to); - } else { -- server.getHandle().moveToWorld(entity, toWorld, true, to, true); -+ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper - } - return true; - } diff --git a/Spigot-Server-Patches/0055-Add-exception-reporting-event.patch b/Spigot-Server-Patches/0055-Add-exception-reporting-event.patch deleted file mode 100644 index b032c0319942..000000000000 --- a/Spigot-Server-Patches/0055-Add-exception-reporting-event.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 03:15:41 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; -+ -+/** -+ * Reporting wrapper to catch exceptions not natively -+ */ -+public class ServerSchedulerReportingWrapper implements Runnable { -+ -+ private final CraftTask internalTask; -+ -+ public ServerSchedulerReportingWrapper(CraftTask internalTask) { -+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ internalTask.run(); -+ } catch (RuntimeException e) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) -+ ); -+ throw e; -+ } catch (Throwable t) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) -+ ); //Do not rethrow, since it is not permitted with Runnable#run -+ } -+ } -+ -+ public CraftTask getInternalTask() { -+ return internalTask; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 788a45d5426f0752509442aec2d28b1f32f63cb1..2511fbe7aa5ff1ace71b513d2938975e388295c6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -815,6 +815,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return true; - } catch (Exception exception) { - PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 107979178e8be5ee6cf885d42f992fabf3bd00b0..8a343a857dc4661ba256e39cf391dd2c7a1cc970 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.io.Files; -@@ -363,6 +364,7 @@ public class NameReferencingFileConverter { - root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file5)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - if (root != null) { -@@ -376,6 +378,7 @@ public class NameReferencingFileConverter { - NBTCompressedStreamTools.a(root, new java.io.FileOutputStream(file2)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 928ca3189af1ddaba797628a087cd6c6a9016f5c..eaa97eb11d893266253fb108249ced1e0e96a4dc 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.entity.ai.village; - -+import com.destroystokyo.paper.exception.ServerInternalException; -+ - import java.util.Iterator; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -119,6 +121,7 @@ public class VillageSiege implements MobSpawner { - entityzombie.prepare(worldserver, worldserver.getDamageScaler(entityzombie.getChunkCoordinates()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null); - } catch (Exception exception) { - VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); -+ ServerInternalException.reportInternalException(exception); // Paper - return; - } - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 2d02b2fc502a0f7e541f7943ed647ff7177acee8..fd0595fd584046326eccacdf0a6afe40c5e84eed 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -301,6 +301,7 @@ public final class SpawnerCreature { - } - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return null; - } - } -@@ -407,6 +408,7 @@ public final class SpawnerCreature { - entity = biomesettingsmobs_c.c.a((World) worldaccess.getMinecraftWorld()); - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - continue; - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 33469b719d679c65d4bcb8366008e6e107eb3a0b..01cb0c8dd9875986e0c08371e876f0dba3f0cf5a 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1,5 +1,10 @@ - package net.minecraft.world.level; - -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerInternalException; -+import com.google.common.base.MoreObjects; - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; - import java.io.IOException; -@@ -737,8 +742,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.exit(); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ String msg = "TileEntity threw exception at " + tileentity.getWorld().getWorld().getName() + ":" + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); -+ // Paper end - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - continue; -@@ -808,8 +816,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - consumer.accept(entity); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.dead = true; - return; - // Paper end -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index a2d80c2c8e4f080f60746548f75631c5946ba8e2..4b3de29b1a6e9d75b28962073c62bbe8d666165f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -@@ -655,10 +656,15 @@ public class Chunk implements IChunkAccess { - this.tileEntities.remove(blockposition); - // Paper end - } else { -- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -- + " (" + getType(blockposition) + ") where there was no entity tile!"); -- System.out.println("Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -- new Exception().printStackTrace(); -+ // Paper start -+ ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," -+ + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -+ + " (" + getType(blockposition) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -+ e.printStackTrace(); -+ ServerInternalException.reportInternalException(e); -+ // Paper end - // CraftBukkit end - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index d1b761055c508a4b80436b50a832e00d0449d8cb..1638f7902290e1bb233f11e5d0bbf83a9e863939 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,6 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper - return false; - } - } -@@ -337,6 +338,7 @@ public class RegionFile implements AutoCloseable { - filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable1; - } finally { - if (filechannel != null) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 3910daeaa177639fa8055301304634c2014dc20f..d61960d80599dc5e7b70cc990e4b0b174eb6e34e 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -150,6 +150,7 @@ public class WorldPersistentData { - } - } catch (Throwable throwable6) { - throwable = throwable6; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable6; - } finally { - if (fileinputstream != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger; - import java.util.concurrent.atomic.AtomicReference; - import java.util.function.Consumer; - import java.util.logging.Level; -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; - import org.apache.commons.lang.Validate; - import org.bukkit.plugin.IllegalPluginAccessException; - import org.bukkit.plugin.Plugin; -@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler { - msg, - throwable); - } -+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); - // Paper end - } finally { - currentTask = null; -@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } diff --git a/Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch deleted file mode 100644 index e8a68b30bbde..000000000000 --- a/Spigot-Server-Patches/0056-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 8 Mar 2016 18:28:43 -0800 -Subject: [PATCH] Don't nest if we don't need to when cerealising text - components - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index edae451a54bfcd6b54e89c1619fb112a7763eb3b..f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -40,7 +40,14 @@ public class PacketPlayOutChat implements Packet { - // Paper end - // Spigot start - if (components != null) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below -+ // Paper start - don't nest if we don't need to so that we can preserve formatting -+ if (this.components.length == 1) { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ } else { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ } -+ // Paper end - } else { - packetdataserializer.a(this.a); - } diff --git a/Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch b/Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch deleted file mode 100644 index 6f434c23a47e..000000000000 --- a/Spigot-Server-Patches/0057-Disable-Scoreboards-for-non-players-by-default.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 8 Mar 2016 23:25:45 -0500 -Subject: [PATCH] Disable Scoreboards for non players by default - -Entities collision is checking for scoreboards setting. -This is very heavy to do map lookups for every collision to check -this setting. - -So avoid looking up scoreboards and short circuit to the "not on a team" -logic which is most likely to be true. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index abbbe1786eb68af02f9d39650aad730ac44aac8a..3ac2ac3db9b1c271b3c21930bb13716669ff64d3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -210,4 +210,9 @@ public class PaperWorldConfig { - private void disableTeleportationSuffocationCheck() { - disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); - } -+ -+ public boolean nonPlayerEntitiesOnScoreboards = false; -+ private void nonPlayerEntitiesOnScoreboards() { -+ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 40eb6bae8ca4e2b57d4f91547808eb00ac1fd455..b7df4d8eb3ccb9e8dc85898352f41c5c20abcb34 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2284,6 +2284,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - @Nullable - public ScoreboardTeamBase getScoreboardTeam() { -+ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.getName()); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 3598db4144141a8701a2879be13a81a8ee48018c..318c96ee92fc8c6f5926aeadaa597d32ad590974 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -741,6 +741,7 @@ public abstract class EntityLiving extends Entity { - if (nbttagcompound.hasKeyOfType("Team", 8)) { - String s = nbttagcompound.getString("Team"); - ScoreboardTeam scoreboardteam = this.world.getScoreboard().getTeam(s); -+ if (!world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { scoreboardteam = null; } // Paper - boolean flag = scoreboardteam != null && this.world.getScoreboard().addPlayerToTeam(this.getUniqueIDString(), scoreboardteam); - - if (!flag) { diff --git a/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index a2f353ae1248..000000000000 --- a/Spigot-Server-Patches/0058-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:43:39 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 9f7334ae769438cdd77508000e7721f57b30e225..a81afaf47214dcb4452642a7e8f295eb94ca6501 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -689,4 +689,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - getHandle().persistentInvisibility = invisible; - getHandle().setFlag(5, invisible); - } -+ -+ // Paper start -+ @Override -+ public int getArrowsStuck() { -+ return getHandle().getArrowCount(); -+ } -+ -+ @Override -+ public void setArrowsStuck(int arrows) { -+ getHandle().setArrowCount(arrows); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0059-Complete-resource-pack-API.patch b/Spigot-Server-Patches/0059-Complete-resource-pack-API.patch deleted file mode 100644 index e8e4ac7f9d2a..000000000000 --- a/Spigot-Server-Patches/0059-Complete-resource-pack-API.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 23:17:52 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 6a8567c355202560ee523c6dc68cac1ac3e562fd..69dc4431a430461ce242de5c1a1c3023367c99b7 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1604,7 +1604,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { - PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); -- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); -+ // Paper start -+ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; -+ player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index f2228933719a2325a518be15237fedf56c994d1f..ed5680e6e0fcfbaf948bdede98d206cff2b26467 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -138,6 +138,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private double health = 20; - private boolean scaledHealth = false; - private double healthScale = 20; -+ // Paper start -+ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; -+ private String resourcePackHash; -+ // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { - super(server, entity); -@@ -1874,6 +1878,32 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public boolean getAffectsSpawning() { - return this.getHandle().affectsSpawning; - } -+ -+ @Override -+ public void setResourcePack(String url, String hash) { -+ Validate.notNull(url, "Resource pack URL cannot be null"); -+ Validate.notNull(hash, "Hash cannot be null"); -+ this.getHandle().setResourcePack(url, hash); -+ } -+ -+ @Override -+ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { -+ return this.resourcePackStatus; -+ } -+ -+ @Override -+ public String getResourcePackHash() { -+ return this.resourcePackHash; -+ } -+ -+ @Override -+ public boolean hasResourcePack() { -+ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; -+ } -+ -+ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { -+ this.resourcePackStatus = status; -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch b/Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch deleted file mode 100644 index 03f01b158376..000000000000 --- a/Spigot-Server-Patches/0060-Chunk-Save-Reattempt.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Mar 2013 23:46:10 -0500 -Subject: [PATCH] Chunk Save Reattempt - -We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 1638f7902290e1bb233f11e5d0bbf83a9e863939..4bf3e0cb4602d33a2e00c502b1dd212032b22a8f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -265,7 +265,7 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this - return false; - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index de125077656f249d5cf9b76f07981b55e690e015..8310dd6bfc04b8ac0a51545baa3a264e6cb42eac 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -11,6 +11,7 @@ import java.io.IOException; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - -@@ -92,6 +93,7 @@ public final class RegionFileCache implements AutoCloseable { - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { - RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; - -@@ -115,6 +117,18 @@ public final class RegionFileCache implements AutoCloseable { - - } - -+ // Paper start -+ return; -+ } catch (Exception ex) { -+ laste = ex; -+ } -+ } -+ -+ if (laste != null) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); -+ MinecraftServer.LOGGER.error("Failed to save chunk", laste); -+ } -+ // Paper end - } - - public void close() throws IOException { diff --git a/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch b/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch deleted file mode 100644 index c908679a7733..000000000000 --- a/Spigot-Server-Patches/0061-Default-loading-permissions.yml-before-plugins.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:17:38 -0400 -Subject: [PATCH] Default loading permissions.yml before plugins - -Under previous behavior, plugins were not able to check if a player had a permission -if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. - -This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. - -This gives plugins expected permission checks. - -It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins -modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. - -A config option has been added for those who depend on the previous behavior, but I don't expect that. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 429b74474ced04d8dd8f038b8590b8dfe178bf4d..716f285e67019b8a62922d09c15883c99f9421aa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -222,4 +222,9 @@ public class PaperConfig { - private static void useDisplayNameInQuit() { - useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); - } -+ -+ public static boolean loadPermsBeforePlugins = true; -+ private static void loadPermsBeforePlugins() { -+ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2833861b337cdb28ae12d21c6abee84dbcac314a..6df1ef2640cc6c014051bdb4d71d7cd80e978aec 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -399,6 +399,7 @@ public final class CraftServer implements Server { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); - helpMap.initializeGeneralTopics(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - } - - Plugin[] plugins = pluginManager.getPlugins(); -@@ -418,7 +419,7 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); - } diff --git a/Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch b/Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch deleted file mode 100644 index 1789e141f9f3..000000000000 --- a/Spigot-Server-Patches/0062-Allow-Reloading-of-Custom-Permissions.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:30:17 -0400 -Subject: [PATCH] Allow Reloading of Custom Permissions - -https://github.com/PaperMC/Paper/issues/49 - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b75c5571c3f1d7c45ca2dd29ff285cb5a0d27071..9e2b3ef9296cd6bbba99f1b1e3181fff4e537760 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2252,5 +2252,23 @@ public final class CraftServer implements Server { - } - return this.adventure$audiences; - } -+ -+ @Override -+ public void reloadPermissions() { -+ pluginManager.clearPermissions(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ for (Permission perm : plugin.getDescription().getPermissions()) { -+ try { -+ pluginManager.addPermission(perm); -+ } catch (IllegalArgumentException ex) { -+ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); -+ } -+ } -+ } -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ DefaultPermissions.registerCorePermissions(); -+ CraftDefaultPermissions.registerCorePermissions(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch b/Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch deleted file mode 100644 index fcfe939c2960..000000000000 --- a/Spigot-Server-Patches/0063-Remove-Metadata-on-reload.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:50:14 -0400 -Subject: [PATCH] Remove Metadata on reload - -Metadata is not meant to persist reload as things break badly with non primitive types -This will remove metadata on reload so it does not crash everything if a plugin uses it. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e5f6dfa4061b98ccb5f3b0cd93ef416a2c20ee78..83ab502d80bbb97204a6f0e4474d1a3b96218448 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -873,8 +873,18 @@ public final class CraftServer implements Server { - world.paperConfig.init(); // Paper - } - -+ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ -+ // Paper start -+ for (Plugin plugin : pluginClone) { -+ entityMetadata.removeAll(plugin); -+ worldMetadata.removeAll(plugin); -+ playerMetadata.removeAll(plugin); -+ } -+ // Paper end -+ - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch b/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch deleted file mode 100644 index e87ee15fe261..000000000000 --- a/Spigot-Server-Patches/0064-Handle-Item-Meta-Inconsistencies.patch +++ /dev/null @@ -1,331 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 May 2015 23:00:19 -0400 -Subject: [PATCH] Handle Item Meta Inconsistencies - -First, Enchantment order would blow away seeing 2 items as the same, -however the Client forces enchantment list in a certain order, as well -as does the /enchant command. Anvils can insert it into forced order, -causing 2 same items to be considered different. - -This change makes unhandled NBT Tags and Enchantments use a sorted tree map, -so they will always be in a consistent order. - -Additionally, the old enchantment API was never updated when ItemMeta -was added, resulting in 2 different ways to modify an items enchantments. - -For consistency, the old API methods now forward to use the -ItemMeta API equivalents, and should deprecate the old API's. - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 4010152dccc93019f2e7f284d80b92bae0d91c34..d7c5065457d910f3e5481fda046d368d5f66f67b 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -9,6 +9,8 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; - import java.text.DecimalFormat; - import java.text.DecimalFormatSymbols; -+import java.util.Collections; -+import java.util.Comparator; - import java.util.Locale; - import java.util.Objects; - import java.util.Optional; -@@ -120,6 +122,23 @@ public final class ItemStack { - private ShapeDetectorBlock n; - private boolean o; - -+ // Paper start -+ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); -+ private void processEnchantOrder(NBTTagCompound tag) { -+ if (tag == null || !tag.hasKeyOfType("Enchantments", 9)) { -+ return; -+ } -+ NBTTagList list = tag.getList("Enchantments", 10); -+ if (list.size() < 2) { -+ return; -+ } -+ try { -+ //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper -+ } catch (Exception ignored) {} -+ } -+ // Paper end -+ - public ItemStack(IMaterial imaterial) { - this(imaterial, 1); - } -@@ -162,6 +181,7 @@ public final class ItemStack { - if (nbttagcompound.hasKeyOfType("tag", 10)) { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); -+ processEnchantOrder(this.tag); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -680,6 +700,7 @@ public final class ItemStack { - // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; -+ processEnchantOrder(this.tag); // Paper - if (this.getItem().usesDurability()) { - this.setDamage(this.getDamage()); - } -@@ -770,6 +791,7 @@ public final class ItemStack { - nbttagcompound.setString("id", String.valueOf(IRegistry.ENCHANTMENT.getKey(enchantment))); - nbttagcompound.setShort("lvl", (short) ((byte) i)); - nbttaglist.add(nbttagcompound); -+ processEnchantOrder(nbttagcompound); // Paper - } - - public boolean hasEnchantments() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 275b943a59ef28c831a068987e111e84ebba3bb7..7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -178,28 +178,11 @@ public final class CraftItemStack extends ItemStack { - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); - -- if (!makeTag(handle)) { -- return; -- } -- NBTTagList list = getEnchantmentList(handle); -- if (list == null) { -- list = new NBTTagList(); -- handle.getTag().set(ENCHANTMENTS.NBT, list); -- } -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound tag = (NBTTagCompound) list.get(i); -- String id = tag.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- return; -- } -- } -- NBTTagCompound tag = new NBTTagCompound(); -- tag.setString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- list.add(tag); -+ // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); -+ itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); -+ // Paper end - } - - static boolean makeTag(net.minecraft.world.item.ItemStack item) { -@@ -216,66 +199,33 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta - } - - @Override - public int getEnchantmentLevel(Enchantment ench) { -- Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { -- return 0; -- } -- return EnchantmentManager.getEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta - } - - @Override - public int removeEnchantment(Enchantment ench) { - Validate.notNull(ench, "Cannot remove null enchantment"); - -- NBTTagList list = getEnchantmentList(handle), listCopy; -- if (list == null) { -- return 0; -- } -- int index = Integer.MIN_VALUE; -- int level = Integer.MIN_VALUE; -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound enchantment = (NBTTagCompound) list.get(i); -- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- index = i; -- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); -- break; -- } -- } -- -- if (index == Integer.MIN_VALUE) { -- return 0; -- } -- if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); -- } -- return level; -- } -- -- // This is workaround for not having an index removal -- listCopy = new NBTTagList(); -- for (int i = 0; i < size; i++) { -- if (i != index) { -- listCopy.add(list.get(i)); -- } -+ // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); -+ int level = itemMeta.getEnchantLevel(ench); -+ if (level > 0) { -+ itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); - } -- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); -+ // Paper end - - return level; - } - - @Override - public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta - } - - static Map getEnchantments(net.minecraft.world.item.ItemStack item) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 7a11b2ddfa4244459253c918315aaab78ef2eb4a..57a6e66866ea82caccbbbfd55948a081f50f6bbe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.ImmutableMultimap; - import com.google.common.collect.LinkedHashMultimap; -+import com.google.common.collect.ImmutableSortedMap; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Multimap; - import com.google.common.collect.SetMultimap; -@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.Comparator; // Paper - import java.util.EnumSet; - import java.util.HashMap; - import java.util.Iterator; -@@ -32,6 +34,7 @@ import java.util.Map; - import java.util.NoSuchElementException; - import java.util.Objects; - import java.util.Set; -+import java.util.TreeMap; // Paper - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; -@@ -271,7 +274,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private List lore; // null and empty are two different states internally - private Integer customModelData; - private NBTTagCompound blockData; -- private Map enchantments; -+ private EnchantmentMap enchantments; // Paper - private Multimap attributeModifiers; - private int repairCost; - private int hideFlag; -@@ -282,7 +285,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - - private NBTTagCompound internalTag; -- private final Map unhandledTags = new HashMap(); -+ private final Map unhandledTags = new TreeMap<>(); // Paper - private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - - private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only -@@ -303,7 +306,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.blockData = meta.blockData; - - if (meta.enchantments != null) { // Spigot -- this.enchantments = new LinkedHashMap(meta.enchantments); -+ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper - } - - if (meta.hasAttributeModifiers()) { -@@ -386,13 +389,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { // Paper - if (!tag.hasKey(key.NBT)) { - return null; - } - - NBTTagList ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - - for (int i = 0; i < ench.size(); i++) { - String id = ((NBTTagCompound) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); -@@ -545,13 +548,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(Map map, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper - Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - if (ench == null) { - return null; - } - -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - for (Map.Entry entry : ench.entrySet()) { - // Doctor older enchants - String enchantKey = entry.getKey().toString(); -@@ -827,14 +830,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Override - public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper - } - - @Override - public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { - Validate.notNull(ench, "Enchantment cannot be null"); - if (enchantments == null) { -- enchantments = new LinkedHashMap(4); -+ enchantments = new EnchantmentMap(); // Paper - } - - if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -1215,7 +1218,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.customModelData = this.customModelData; - clone.blockData = this.blockData; - if (this.enchantments != null) { -- clone.enchantments = new LinkedHashMap(this.enchantments); -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } - if (this.hasAttributeModifiers()) { - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -1447,4 +1450,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; - } - } -+ -+ // Paper start -+ private static class EnchantmentMap extends TreeMap { -+ private EnchantmentMap(Map enchantments) { -+ this(); -+ putAll(enchantments); -+ } -+ -+ private EnchantmentMap() { -+ super(Comparator.comparing(o -> o.getKey().toString())); -+ } -+ -+ public EnchantmentMap clone() { -+ return (EnchantmentMap) super.clone(); -+ } -+ } -+ // Paper end -+ - } diff --git a/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch deleted file mode 100644 index 0cc21d37c30b..000000000000 --- a/Spigot-Server-Patches/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 15:12:22 -0400 -Subject: [PATCH] Configurable Non Player Arrow Despawn Rate - -Can set a much shorter despawn rate for arrows that players can not pick up. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3ac2ac3db9b1c271b3c21930bb13716669ff64d3..3c78d3234054ce2dc46ef77decb6adb0cbd10620 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -215,4 +215,19 @@ public class PaperWorldConfig { - private void nonPlayerEntitiesOnScoreboards() { - nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); - } -+ -+ public int nonPlayerArrowDespawnRate = -1; -+ public int creativeArrowDespawnRate = -1; -+ private void nonPlayerArrowDespawnRate() { -+ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); -+ if (nonPlayerArrowDespawnRate == -1) { -+ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); -+ if (creativeArrowDespawnRate == -1) { -+ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); -+ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index a05ee898bd360f49ea2807d06f93e27ada11ef63..9bd4a283a99f86c9a26f73e0bad0c3414d66ad55 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -283,7 +283,7 @@ public abstract class EntityArrow extends IProjectile { - - protected void h() { - ++this.despawnCounter; -- if (this.despawnCounter >= ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)) { // Spigot -+ if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? - this.die(); - } - diff --git a/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch b/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch deleted file mode 100644 index e8f87bb7d581..000000000000 --- a/Spigot-Server-Patches/0066-Add-World-Util-Methods.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 20:16:03 -0400 -Subject: [PATCH] Add World Util Methods - -Methods that can be used for other patches to help improve logic. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index eddfbd25953e8ef410f1617a1edecbc7d07696c0..b04a6cd626fceed26aec6121e20fb1b6dd1c716d 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -197,7 +197,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - -- public Chunk getChunkIfLoaded(int x, int z) { -+ @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b0ad55f35285cc1bc339859a8deae65e930082b8..067f5e46ad2f28ab119db77b19c4897bed9b3d80 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -297,11 +297,27 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ public final Fluid getFluidIfLoaded(BlockPosition blockposition) { - IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); - - return chunk == null ? null : chunk.getFluid(blockposition); - } -+ -+ public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline -+ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; -+ } -+ -+ public Chunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ } -+ public final Chunk getChunkIfLoaded(BlockPosition blockposition) { -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ -+ // reduces need to do isLoaded before getType -+ public final IBlockData getTypeIfLoadedAndInBounds(BlockPosition blockposition) { -+ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; -+ } - // Paper end - - @Override -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 2bb03f1cb9671a7754a68059219f783d4508eeb9..f16c76df5d7b184d57f4cc397f069eac9cc430cb 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -31,6 +31,7 @@ public class WorldBorder { - - public WorldBorder() {} - -+ public final boolean isInBounds(BlockPosition blockposition) { return this.a(blockposition); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition) { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } diff --git a/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch b/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch deleted file mode 100644 index defeebd3fcf0..000000000000 --- a/Spigot-Server-Patches/0067-Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:07:20 -0400 -Subject: [PATCH] Custom replacement for eaten items - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 318c96ee92fc8c6f5926aeadaa597d32ad590974..9b12e15a6c377ae90193596a35114dd452cf6e0c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3205,9 +3205,10 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -+ PlayerItemConsumeEvent event = null; // Paper - if (this instanceof EntityPlayer) { - org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.activeItem); -- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); -+ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -@@ -3221,6 +3222,13 @@ public abstract class EntityLiving extends Entity { - } else { - itemstack = this.activeItem.a(this.world, this); - } -+ -+ // Paper start - save the default replacement item and change it if necessary -+ final ItemStack defaultReplacement = itemstack; -+ if (event != null && event.getReplacement() != null) { -+ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); -+ } -+ // Paper end - // CraftBukkit end - - if (itemstack != this.activeItem) { -@@ -3228,6 +3236,11 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -+ // Paper start - if the replacement is anything but the default, update the client inventory -+ if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ ((EntityPlayer) this).getBukkitEntity().updateInventory(); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch deleted file mode 100644 index 7560b346792c..000000000000 --- a/Spigot-Server-Patches/0068-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 27 Sep 2015 01:18:02 -0400 -Subject: [PATCH] handle NaN health/absorb values and repair bad data - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 082a3efb8c03e6a0a35411107f3cf3776dee14bf..c7b40800343edb2c2a68786afb828c9dc3e3627f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -702,7 +702,13 @@ public abstract class EntityLiving extends Entity { - - @Override - public void loadData(NBTTagCompound nbttagcompound) { -- this.setAbsorptionHearts(nbttagcompound.getFloat("AbsorptionAmount")); -+ // Paper start - jvm keeps optimizing the setter -+ float absorptionAmount = nbttagcompound.getFloat("AbsorptionAmount"); -+ if (Float.isNaN(absorptionAmount)) { -+ absorptionAmount = 0; -+ } -+ this.setAbsorptionHearts(absorptionAmount); -+ // Paper end - if (nbttagcompound.hasKeyOfType("Attributes", 9) && this.world != null && !this.world.isClientSide) { - this.getAttributeMap().a(nbttagcompound.getList("Attributes", 10)); - } -@@ -1151,6 +1157,10 @@ public abstract class EntityLiving extends Entity { - } - - public void setHealth(float f) { -+ // Paper start -+ if (Float.isNaN(f)) { f = getMaxHealth(); if (this.valid) { -+ System.err.println("[NAN-HEALTH] " + getName() + " had NaN health set"); -+ } } // Paper end - // CraftBukkit start - Handle scaled health - if (this instanceof EntityPlayer) { - org.bukkit.craftbukkit.entity.CraftPlayer player = ((EntityPlayer) this).getBukkitEntity(); -@@ -3045,7 +3055,7 @@ public abstract class EntityLiving extends Entity { - } - - public void setAbsorptionHearts(float f) { -- if (f < 0.0F) { -+ if (f < 0.0F || Float.isNaN(f)) { // Paper - f = 0.0F; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ed5680e6e0fcfbaf948bdede98d206cff2b26467..ab7e731cb04a75b829f0cd24d7b94f7ddad166e8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1680,6 +1680,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setRealHealth(double health) { -+ if (Double.isNaN(health)) {return;} // Paper - this.health = health; - } - diff --git a/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch b/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch deleted file mode 100644 index 1579a0057c58..000000000000 --- a/Spigot-Server-Patches/0069-Use-a-Shared-Random-for-Entities.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Mar 2016 00:33:47 -0400 -Subject: [PATCH] Use a Shared Random for Entities - -Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b7df4d8eb3ccb9e8dc85898352f41c5c20abcb34..6cbb797cb0de4b26d8ddd7f0bf567f49bd36f9c0 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -143,6 +143,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } - -+ // Paper start -+ public static Random SHARED_RANDOM = new Random() { -+ private boolean locked = false; -+ @Override -+ public synchronized void setSeed(long seed) { -+ if (locked) { -+ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); -+ } else { -+ super.setSeed(seed); -+ locked = true; -+ } -+ } -+ }; -+ // Paper end -+ - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -@@ -272,7 +287,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.am = 1.0F; - this.an = 1.0F; -- this.random = new Random(); -+ this.random = SHARED_RANDOM; // Paper - this.fireTicks = -this.getMaxFireTicks(); - this.M = new Object2DoubleArrayMap(2); - this.justCreated = true; diff --git a/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch deleted file mode 100644 index a0c1e7b12180..000000000000 --- a/Spigot-Server-Patches/0070-Configurable-spawn-chances-for-skeleton-horses.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 22 Mar 2016 12:04:28 -0500 -Subject: [PATCH] Configurable spawn chances for skeleton horses - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c78d3234054ce2dc46ef77decb6adb0cbd10620..cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -230,4 +230,12 @@ public class PaperWorldConfig { - log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); - log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); - } -+ -+ public double skeleHorseSpawnChance; -+ private void skeleHorseSpawnChance() { -+ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); -+ if (skeleHorseSpawnChance < 0) { -+ skeleHorseSpawnChance = 0.01D; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 045183ab75bac68b1da5e0899a15fa34cd9e956f..a5ee8bf7904444ff6fd82260a66a81c9af479f9e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -590,7 +590,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); -- boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D; -+ boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper - - if (flag1) { - EntityHorseSkeleton entityhorseskeleton = (EntityHorseSkeleton) EntityTypes.SKELETON_HORSE.a((World) this); diff --git a/Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch deleted file mode 100644 index 9f9e1ddd608d..000000000000 --- a/Spigot-Server-Patches/0071-Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:07:55 -0600 -Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for - inlining - -Hot methods, so reduce # of instructions for the method. - -Move is valid location test to the BlockPosition class so that it can access local variables. - -Replace all calls to the new place to the unnecessary forward. - -Optimize getType and getBlockData to manually inline and optimize the calls - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 25fdd55a7548cfaa45a541ad77f22f33c33e7471..4b56683336fdab06804efdc8ca1f7c130b77291f 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -22,6 +22,15 @@ public class BaseBlockPosition implements Comparable { - private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER - private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - -+ // Paper start -+ public boolean isValidLocation() { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; -+ } -+ public boolean isInvalidYLocation() { -+ return b < 0 || b >= 256; -+ } -+ // Paper end -+ - public BaseBlockPosition(int i, int j, int k) { - this.a = i; - this.b = j; -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a570998e4ef6c3ff83403881bf1d24c8cbcfcf67..a22be13b097052b2a88707c9436b88c84298e46b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -239,7 +239,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public static boolean isValidLocation(BlockPosition blockposition) { -- return !isOutsideWorld(blockposition) && D(blockposition); -+ return blockposition.isValidLocation(); // Paper - use better/optimized check - } - - public static boolean l(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 4b3de29b1a6e9d75b28962073c62bbe8d666165f..fdc491f978560c394eec22116572585f9bbdec9f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -348,12 +348,27 @@ public class Chunk implements IChunkAccess { - return this.sections; - } - -- @Override -+ // Paper start - Optimize getBlockData to reduce instructions -+ public final IBlockData getBlockData(BlockPosition pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getX(); -- int j = blockposition.getY(); -- int k = blockposition.getZ(); -+ return this.getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ -+ public IBlockData getType(final int x, final int y, final int z) { -+ return getBlockData(x, y, z); -+ } -+ public final IBlockData getBlockData(final int x, final int y, final int z) { -+ // Method body / logic copied from below -+ final int i = y >> 4; -+ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { -+ return Blocks.AIR.getBlockData(); -+ } -+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) -+ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); -+ } - -+ public IBlockData getBlockData_unused(int i, int j, int k) { -+ // Paper end - if (this.world.isDebugWorld()) { - IBlockData iblockdata = null; - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 395d21afaabcbd99f9ce0551d647f5db9507a518..89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -23,7 +23,7 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public class ChunkEmpty extends Chunk { - -- private static final BiomeBase[] b = (BiomeBase[]) SystemUtils.a((Object) (new BiomeBase[BiomeStorage.a]), (abiomebase) -> { -+ private static final BiomeBase[] b = SystemUtils.a((new BiomeBase[BiomeStorage.a]), (abiomebase) -> { // Paper - decompile error - Arrays.fill(abiomebase, BiomeRegistry.a); - }); - -@@ -31,6 +31,11 @@ public class ChunkEmpty extends Chunk { - super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); - } - -+ // Paper start -+ @Override public IBlockData getType(int x, int y, int z) { -+ return Blocks.VOID_AIR.getBlockData(); -+ } -+ // Paper end - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.VOID_AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index a4e2eb1a753e8fcb48982d78fe80e505bce5c476..eea4a30428293eaf7afbe303a37adec60b44c2b4 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -13,10 +13,10 @@ public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); - private final int yPos; -- private short nonEmptyBlockCount; -+ short nonEmptyBlockCount; // Paper - package-private - private short tickingBlockCount; - private short e; -- private final DataPaletteBlock blockIds; -+ final DataPaletteBlock blockIds; // Paper - package-private - - public ChunkSection(int i) { - this(i, (short) 0, (short) 0, (short) 0); -@@ -30,8 +30,8 @@ public class ChunkSection { - this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - } - -- public IBlockData getType(int i, int j, int k) { -- return (IBlockData) this.blockIds.a(i, j, k); -+ public final IBlockData getType(int i, int j, int k) { // Paper -+ return this.blockIds.a(j << 8 | k << 4 | i); // Paper - inline - } - - public Fluid b(int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index e397b871b846c3a90bc75d0e1cf0683b6a3d0ca9..8928157b01bb4f0dfe043732777b33708c23cda7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -133,7 +133,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T a(int i, int j, int k) { -- return this.a(b(i, j, k)); -+ return this.a(j << 8 | k << 4 | i); // Paper - inline - } - - protected T a(int i) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index 2cd04abd72f1135446182ad6294003e526f99a4b..e570dc58efa56bd0aa5ada5575b4054ee38d505e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 7572ca53a5cca8ca5085d18c24048b85dda4daa9..9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -113,16 +113,18 @@ public class ProtoChunk implements IChunkAccess { - - @Override - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getY(); -- -- if (World.b(i)) { -+ return getType(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ // Paper start -+ public IBlockData getType(final int x, final int y, final int z) { -+ if (y < 0 || y >= 256) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- ChunkSection chunksection = this.getSections()[i >> 4]; -- -- return ChunkSection.a(chunksection) ? Blocks.AIR.getBlockData() : chunksection.getType(blockposition.getX() & 15, i & 15, blockposition.getZ() & 15); -+ ChunkSection chunksection = this.getSections()[y >> 4]; -+ return chunksection == Chunk.EMPTY_CHUNK_SECTION || chunksection.c() ? Blocks.AIR.getBlockData() : chunksection.getType(x & 15, y & 15, z & 15); - } - } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index c059d3d055c35b492680556e8605966e2caaf7fd..9351e6ba541d440c485b6e4a3209170c5756e31e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -42,6 +42,11 @@ public class ProtoChunkExtension extends ProtoChunk { - public IBlockData getType(BlockPosition blockposition) { - return this.a.getType(blockposition); - } -+ // Paper start -+ public final IBlockData getType(final int x, final int y, final int z) { -+ return this.a.getBlockData(x, y, z); -+ } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch deleted file mode 100644 index 357ba81b5365..000000000000 --- a/Spigot-Server-Patches/0072-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 19:55:45 -0400 -Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener - -Saves on some object allocation and processing when no plugin listens to this - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 06071e15851d5d27f1c9a0d60a764a6214e0ba0f..33139f9dc6a9c6030f565b01c9b6fd411cafa710 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1292,6 +1292,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a5ee8bf7904444ff6fd82260a66a81c9af479f9e..c5baf9c448761f24c4fd49d7c4bade7dee43edf4 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -196,6 +196,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private int tickPosition; - public final Convertable.ConversionSession convertable; - public final UUID uuid; -+ public boolean hasPhysicsEvent = true; // Paper - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a22be13b097052b2a88707c9436b88c84298e46b..9236e480d21340d4295caa16dae34363e182f483 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -458,7 +458,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - iblockdata1.b(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); - this.getServer().getPluginManager().callEvent(event); - -@@ -560,7 +560,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - // CraftBukkit start - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ())); - this.getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPlant.java b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -index 33a5c5a4dc1478ab211dbb2e09df87570b06644f..97dfe5c5e3ea1d9691de87ffbf4b1a29a83a65b4 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.IWorldReader; -@@ -23,7 +24,7 @@ public class BlockPlant extends Block { - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start - if (!iblockdata.canPlace(generatoraccess, blockposition)) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { -+ if (!(generatoraccess instanceof WorldServer && ((WorldServer) generatoraccess).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { // Paper - return Blocks.AIR.getBlockData(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -index ca22187625f7ac6c43b663fd4d66cbf0c943c655..1a5d29ecc9edc52bac14ed5d05ef5376fd5b8a9c 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; -@@ -83,7 +84,7 @@ public class BlockTallPlant extends BlockPlant { - - protected static void b(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { - // CraftBukkit start -- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { -+ if (((WorldServer)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { // Paper - return; - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index e910aa110a6e..000000000000 --- a/Spigot-Server-Patches/0073-Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:32:58 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index c5baf9c448761f24c4fd49d7c4bade7dee43edf4..b40089319329a0843c4d74ebd6189fc4089e319a 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1214,7 +1214,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity instanceof EntityInsentient) { - this.navigators.remove(((EntityInsentient) entity).getNavigation()); - } -- -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - -@@ -1252,6 +1252,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - } diff --git a/Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch b/Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch deleted file mode 100644 index aec9c86c646d..000000000000 --- a/Spigot-Server-Patches/0074-Configurable-Chunk-Inhabited-Time.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:46:14 -0400 -Subject: [PATCH] Configurable Chunk Inhabited Time - -Vanilla stores how long a chunk has been active on a server, and dynamically scales some -aspects of vanilla gameplay to this factor. - -For people who want all chunks to be treated equally, you can chose a fixed value. - -This allows to fine-tune vanilla gameplay. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd64fb9d0c6d123e1c86cb33f12cd9cefc9f80d0..74ba5dbb83c13ce1721619b755036a7864a1fb90 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -238,4 +238,14 @@ public class PaperWorldConfig { - skeleHorseSpawnChance = 0.01D; // Vanilla value - } - } -+ -+ public int fixedInhabitedTime; -+ private void fixedInhabitedTime() { -+ if (PaperConfig.version < 16) { -+ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); -+ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); -+ set("use-chunk-inhabited-timer", null); -+ } -+ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index fdc491f978560c394eec22116572585f9bbdec9f..b6898cd6e6117fef65198db32b98a64c806811d4 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -1022,7 +1022,7 @@ public class Chunk implements IChunkAccess { - - @Override - public long getInhabitedTime() { -- return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper - } - - @Override diff --git a/Spigot-Server-Patches/0075-EntityPathfindEvent.patch b/Spigot-Server-Patches/0075-EntityPathfindEvent.patch deleted file mode 100644 index 84caa9a7de8a..000000000000 --- a/Spigot-Server-Patches/0075-EntityPathfindEvent.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:22:26 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -index 942e03578836524ba746bc37699677eb06cc7803..703d06b2b29f1500301d82df78dc377141085145 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -@@ -75,7 +75,7 @@ public class Navigation extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - private int u() { -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 8848a7552a0ef3944560a71f71620c6bd0f08c10..58225877ce4f2533c19d34e143ae374dc289bce5 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -10,6 +10,7 @@ import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -28,7 +29,7 @@ import net.minecraft.world.phys.Vec3D; - - public abstract class NavigationAbstract { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable - protected PathEntity c; -@@ -115,16 +116,26 @@ public abstract class NavigationAbstract { - - @Nullable - public PathEntity a(BlockPosition blockposition, int i) { -- return this.a(ImmutableSet.of(blockposition), 8, false, i); -+ // Paper start - add target parameter -+ return this.a(blockposition, null, i); -+ } -+ @Nullable public PathEntity a(BlockPosition blockposition, Entity target, int i) { -+ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); -+ // Paper end - } - - @Nullable - public PathEntity a(Entity entity, int i) { -- return this.a(ImmutableSet.of(entity.getChunkCoordinates()), 16, true, i); -+ return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - - @Nullable -+ // Paper start - Add target - protected PathEntity a(Set set, int i, boolean flag, int j) { -+ return this.a(set, null, i, flag, j); -+ } -+ @Nullable protected PathEntity a(Set set, Entity target, int i, boolean flag, int j) { -+ // Paper end - if (set.isEmpty()) { - return null; - } else if (this.a.locY() < 0.0D) { -@@ -134,6 +145,23 @@ public abstract class NavigationAbstract { - } else if (this.c != null && !this.c.c() && set.contains(this.p)) { - return this.c; - } else { -+ // Paper start - Pathfind event -+ boolean copiedSet = false; -+ for (BlockPosition possibleTarget : set) { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { -+ if (!copiedSet) { -+ copiedSet = true; -+ set = new java.util.HashSet<>(set); -+ } -+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy -+ set.remove(possibleTarget); -+ if (set.isEmpty()) { -+ return null; -+ } -+ } -+ } -+ // Paper end - this.b.getMethodProfiler().enter("pathfind"); - float f = (float) this.a.b(GenericAttributes.FOLLOW_RANGE); - BlockPosition blockposition = flag ? this.a.getChunkCoordinates().up() : this.a.getChunkCoordinates(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -index 2e1efe7a048f64d494260d10a4ae5dba86af5e6c..f5664b8c0762f775f3cd106d156eb74b48bcedc2 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -@@ -37,7 +37,7 @@ public class NavigationFlying extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - @Override diff --git a/Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch b/Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch deleted file mode 100644 index d60c778ceae3..000000000000 --- a/Spigot-Server-Patches/0076-Sanitise-RegionFileCache-and-make-configurable.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Antony Riley -Date: Tue, 29 Mar 2016 08:22:55 +0300 -Subject: [PATCH] Sanitise RegionFileCache and make configurable. - -RegionFileCache prior to this patch would close every single open region -file upon reaching a size of 256. -This patch modifies that behaviour so it closes the the least recently -used RegionFile. -The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). -The maximum size of the RegionFileCache is also made configurable. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 716f285e67019b8a62922d09c15883c99f9421aa..439dcc6effdc91830d2b7ede9063982998b37120 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -227,4 +227,9 @@ public class PaperConfig { - private static void loadPermsBeforePlugins() { - loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); - } -+ -+ public static int regionFileCacheSize = 256; -+ private static void regionFileCacheSize() { -+ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 8310dd6bfc04b8ac0a51545baa3a264e6cb42eac..75b10a3755392870d8f5b51239a09a0e7fd75a42 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -33,7 +33,7 @@ public final class RegionFileCache implements AutoCloseable { - if (regionfile != null) { - return regionfile; - } else { -- if (this.cache.size() >= 256) { -+ if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable - ((RegionFile) this.cache.removeLast()).close(); - } - diff --git a/Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch b/Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch deleted file mode 100644 index 6086fc3ad753..000000000000 --- a/Spigot-Server-Patches/0077-Do-not-load-chunks-for-Pathfinding.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 31 Mar 2016 19:17:58 -0400 -Subject: [PATCH] Do not load chunks for Pathfinding - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 58225877ce4f2533c19d34e143ae374dc289bce5..d71a6e5991629ce59c8529d7cc8064960e385236 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -48,7 +48,7 @@ public abstract class NavigationAbstract { - private BlockPosition p; - private int q; - private float r; -- private final Pathfinder s; -+ private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER - private boolean t; - - public NavigationAbstract(EntityInsentient entityinsentient, World world) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 39cd22a820fdc4c75aefb625b45b0c8c6ce1f199..5784be69098805e4d550a0923ac8daa5aada73f9 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -20,7 +20,7 @@ public class Pathfinder { - - private final PathPoint[] a = new PathPoint[32]; - private final int b; -- private final PathfinderAbstract c; -+ private final PathfinderAbstract c; public PathfinderAbstract getPathfinder() { return this.c; } // Paper - OBFHELPER - private final Path d = new Path(); - - public Pathfinder(PathfinderAbstract pathfinderabstract, int i) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index ed9c1dfbc84b9573784e6531186b3cd9513ddf75..d14f2800237c2a80912bf6f2d418a9ba9031070d 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -479,7 +479,12 @@ public class PathfinderNormal extends PathfinderAbstract { - for (int j1 = -1; j1 <= 1; ++j1) { - if (l != 0 || j1 != 0) { - blockposition_mutableblockposition.d(i + l, j + i1, k + j1); -- IBlockData iblockdata = iblockaccess.getType(blockposition_mutableblockposition); -+ // Paper start -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (iblockdata == null) { -+ pathtype = PathType.BLOCKED; -+ } else { -+ // Paper end - - if (iblockdata.a(Blocks.CACTUS)) { - return PathType.DANGER_CACTUS; -@@ -496,6 +501,7 @@ public class PathfinderNormal extends PathfinderAbstract { - if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { - return PathType.WATER_BORDER; - } -+ } // Paper - } - } - } -@@ -505,7 +511,8 @@ public class PathfinderNormal extends PathfinderAbstract { - } - - protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { -- IBlockData iblockdata = iblockaccess.getType(blockposition); -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return PathType.BLOCKED; // Paper - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - diff --git a/Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch b/Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 5401f07df11d..000000000000 --- a/Spigot-Server-Patches/0078-Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:09:16 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -index 9f3f8568ef9484ba226deaa6429f819c325b7a26..ce63f3e5ac4d1a4311c0ebeb7574d999d45987d9 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -@@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec3D; - - public class PacketPlayInUseEntity implements Packet { - -- private int a; -+ private int a; public int getEntityId() { return this.a; } // Paper - add accessor - private PacketPlayInUseEntity.EnumEntityUseAction action; - private Vec3D c; - private EnumHand d; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 69dc4431a430461ce242de5c1a1c3023367c99b7..7cb946ff73de5171debe34b37a784b6ed4e09150 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2199,6 +2199,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } - } -+ // Paper start - fire event -+ else { -+ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packetplayinuseentity.getEntityId(), -+ packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, -+ packetplayinuseentity.c() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch b/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch deleted file mode 100644 index 063b7e7b454f..000000000000 --- a/Spigot-Server-Patches/0079-Fix-reducedDebugInfo-not-initialized-on-client.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 20:37:03 -0400 -Subject: [PATCH] Fix reducedDebugInfo not initialized on client - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cfd0af520dd3dcf364a3ffd03a74e3b9ee6045af..152aa38788a21638aab7cfe2dc187671f1143bde 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -246,6 +246,7 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); - playerconnection.sendPacket(new PacketPlayOutRecipeUpdate(this.server.getCraftingManager().b())); - playerconnection.sendPacket(new PacketPlayOutTags(this.server.getTagRegistry())); -+ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver1.getGameRules().getBoolean(GameRules.REDUCED_DEBUG_INFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.d(entityplayer); - entityplayer.getStatisticManager().c(); - entityplayer.getRecipeBook().a(entityplayer); diff --git a/Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch b/Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch deleted file mode 100644 index 78ce2d00019c..000000000000 --- a/Spigot-Server-Patches/0080-Configurable-Grass-Spread-Tick-Rate.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 16:28:17 -0400 -Subject: [PATCH] Configurable Grass Spread Tick Rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 74ba5dbb83c13ce1721619b755036a7864a1fb90..db2dddd12f54e6d15916c4cee623676541de37fb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -248,4 +248,10 @@ public class PaperWorldConfig { - } - fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); - } -+ -+ public int grassUpdateRate = 1; -+ private void grassUpdateRate() { -+ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); -+ log("Grass Spread Tick Rate: " + grassUpdateRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -index a98392f06e66959ec1b75df8d2ecf3b5267980af..712596420af83e6e1b9d147ae2fd8d8a1f36e1b9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -41,6 +42,7 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { - - @Override - public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (this instanceof BlockGrass && worldserver.paperConfig.grassUpdateRate != 1 && (worldserver.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % worldserver.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!b(iblockdata, (IWorldReader) worldserver, blockposition)) { - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { diff --git a/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch deleted file mode 100644 index d3f898437e66..000000000000 --- a/Spigot-Server-Patches/0081-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 17:48:50 -0400 -Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 70db5312ac556ea53247efdbc7759910ba0c9a95..7611481db980a230d42b3cec1d81fae2622ca634 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -518,6 +518,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void b(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - - public void applyPhysics(BlockPosition blockposition, Block block) { -+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.a(blockposition.west(), block, blockposition); - this.a(blockposition.east(), block, blockposition); - this.a(blockposition.down(), block, blockposition); diff --git a/Spigot-Server-Patches/0082-Optimize-DataBits.patch b/Spigot-Server-Patches/0082-Optimize-DataBits.patch deleted file mode 100644 index 61a9ac3f61d5..000000000000 --- a/Spigot-Server-Patches/0082-Optimize-DataBits.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Optimize DataBits - -Remove Debug checks as these are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor - -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 0c0576c8730069fb5364d8383dec8ab7e698658d..c4f3b680512fb15cea01ad12d0a00c6e60bf34b7 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -13,8 +13,8 @@ public class DataBits { - private final long d; - private final int e; - private final int f; -- private final int g; -- private final int h; -+ private final int g;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls -+ private final int h;private final long h_unsigned; // Paper - private final int i; - - public DataBits(int i, int j) { -@@ -29,8 +29,8 @@ public class DataBits { - this.f = (char) (64 / i); - int k = 3 * (this.f - 1); - -- this.g = DataBits.a[k + 0]; -- this.h = DataBits.a[k + 1]; -+ this.g = DataBits.a[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.g); // Paper -+ this.h = DataBits.a[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.h); // Paper - this.i = DataBits.a[k + 2]; - int l = (j + this.f - 1) / this.f; - -@@ -47,15 +47,15 @@ public class DataBits { - } - - private int b(int i) { -- long j = Integer.toUnsignedLong(this.g); -- long k = Integer.toUnsignedLong(this.h); -+ //long j = Integer.toUnsignedLong(this.g); // Paper -+ //long k = Integer.toUnsignedLong(this.h); // Paper - -- return (int) ((long) i * j + k >> 32 >> this.i); -+ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.i); // Paper - } - -- public int a(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final int a(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -65,9 +65,9 @@ public class DataBits { - return j1; - } - -- public void b(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final void b(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -75,8 +75,8 @@ public class DataBits { - this.b[k] = l & ~(this.d << i1) | ((long) j & this.d) << i1; - } - -- public int a(int i) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -+ public final int a(int i) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper - int j = this.b(i); - long k = this.b[j]; - int l = (i - j * this.f) * this.c; diff --git a/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch deleted file mode 100644 index 7b7292001f68..000000000000 --- a/Spigot-Server-Patches/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 6 Apr 2016 01:04:23 -0500 -Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names - -This change is basically a bandaid to fix CB's complete and utter lack -of support for vanilla scoreboard name modifications. - -In the future, finding a way to merge the vanilla expectations in with -bukkit's concept of a display name would be preferable. There was a PR -for this on CB at one point but I can't find it. We may need to do this -ourselves at some point in the future. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419cfc1a7bdd 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -254,4 +254,9 @@ public class PaperWorldConfig { - grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); - log("Grass Spread Tick Rate: " + grassUpdateRate); - } -+ -+ public boolean useVanillaScoreboardColoring; -+ private void useVanillaScoreboardColoring() { -+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 84dcca67ccd2e52881b4a97de0f061b396ab5f35..b9bdf74e02f414ac0cf265f37b8a7883cab4fdd0 100644 ---- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -17,7 +17,11 @@ import net.minecraft.network.chat.ChatMessageType; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.scores.ScoreboardTeam; -+import net.minecraft.world.scores.ScoreboardTeamBase; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.util.LazyPlayerSet; - import org.bukkit.craftbukkit.util.Waitable; -@@ -179,10 +183,22 @@ public final class ChatProcessor { - } - - private static String legacyDisplayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ final EntityPlayer ep = player.getHandle(); -+ IChatBaseComponent name = ep.getDisplayName(); -+ final ScoreboardTeamBase team = ep.getScoreboardTeam(); -+ if (team != null) { -+ name = team.getFormattedName(name); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; -+ } - return player.getDisplayName(); - } - - private static Component displayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ return PaperAdventure.asAdventure(ScoreboardTeam.a(player.getHandle().getScoreboardTeam(), player.getHandle().getDisplayName())); -+ } - return player.displayName(); - } - diff --git a/Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch b/Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch deleted file mode 100644 index ec42a6a21a3e..000000000000 --- a/Spigot-Server-Patches/0084-Workaround-for-setting-passengers-on-players.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 10 Apr 2016 03:23:32 -0500 -Subject: [PATCH] Workaround for setting passengers on players - -SPIGOT-1915 & GH-114 - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ab7e731cb04a75b829f0cd24d7b94f7ddad166e8..4bb57229c045956bab631982e12c0fc420db450e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -872,6 +872,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return true; - } - -+ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 -+ @Override -+ public boolean setPassenger(org.bukkit.entity.Entity passenger) { -+ boolean wasSet = super.setPassenger(passenger); -+ if (wasSet) { -+ this.getHandle().playerConnection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutMount(this.getHandle())); -+ } -+ return wasSet; -+ } -+ // Paper end -+ - @Override - public void setSneaking(boolean sneak) { - getHandle().setSneaking(sneak); diff --git a/Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch b/Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch deleted file mode 100644 index 8cdf18237877..000000000000 --- a/Spigot-Server-Patches/0085-Remove-unused-World-Tile-Entity-List.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:25:28 -0400 -Subject: [PATCH] Remove unused World Tile Entity List - -Massive hit to performance and it is completely unnecessary. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 24a45e5ac9b17feb528e9a047d1ad1761569ebfa..75424a5dd6db57dded3b6d895e6b5b102e91c77e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1721,7 +1721,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); -- bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityList.size())); -+ bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityListTick.size())); // Paper - remove unused list - bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTickList().a())); - bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getFluidTickList().a())); - bufferedwriter.write("distance_manager: " + playerchunkmap.e().c() + "\n"); -@@ -1860,7 +1860,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("y").a("z").a("type").a(writer); -- Iterator iterator = this.tileEntityList.iterator(); -+ Iterator iterator = this.tileEntityListTick.iterator(); // Paper - remove unused list - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8da8141c2320c0c1a9b95826a9be2dbe22e11c14..cad86b0273c05767f78bcb3bdfaa9ea01e26af4e 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -91,7 +91,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public static final ResourceKey THE_NETHER = ResourceKey.a(IRegistry.L, new MinecraftKey("the_nether")); - public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); - private static final EnumDirection[] a = EnumDirection.values(); -- public final List tileEntityList = Lists.newArrayList(); -+ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); - protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); -@@ -683,9 +683,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }, tileentity::getPosition}); - } - -- boolean flag = this.tileEntityList.add(tileentity); -+ boolean flag = true; // Paper - remove unused list - -- if (flag && tileentity instanceof ITickable) { -+ if (flag && tileentity instanceof ITickable && !this.tileEntityListTick.contains(tileentity)) { // Paper - this.tileEntityListTick.add(tileentity); - } - -@@ -721,7 +721,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - this.tileEntityListTick.removeAll(this.tileEntityListUnload); -- this.tileEntityList.removeAll(this.tileEntityListUnload); -+ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } - -@@ -781,7 +781,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - if (this.isLoaded(tileentity.getPosition())) { - this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); - } -@@ -811,7 +811,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); - // CraftBukkit start - // From above, don't screw this up - SPIGOT-1746 -- if (!this.tileEntityList.contains(tileentity1)) { -+ if (true) { // Paper - remove unused list - this.a(tileentity1); - } - // CraftBukkit end -@@ -957,7 +957,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } else { - if (tileentity != null) { - this.tileEntityListPending.remove(tileentity); -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tileEntityListTick.remove(tileentity); - } - diff --git a/Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch b/Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch deleted file mode 100644 index 26489896abbb..000000000000 --- a/Spigot-Server-Patches/0086-Don-t-tick-Skulls-unused-code.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:30:10 -0400 -Subject: [PATCH] Don't tick Skulls - unused code - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 87a5f352c8a6336c65008d6e21a771fd6332773c..22217f24b4a87f10b6d5a3e37d23a1164af84ace 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -33,7 +33,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.world.entity.player.EntityHuman; - // Spigot end - --public class TileEntitySkull extends TileEntity implements ITickable { -+public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable - - @Nullable - private static UserCache userCache; -@@ -136,7 +136,7 @@ public class TileEntitySkull extends TileEntity implements ITickable { - - } - -- @Override -+ // Paper - remove override - public void tick() { - IBlockData iblockdata = this.getBlock(); - diff --git a/Spigot-Server-Patches/0087-Configurable-Player-Collision.patch b/Spigot-Server-Patches/0087-Configurable-Player-Collision.patch deleted file mode 100644 index 450c44ab69d0..000000000000 --- a/Spigot-Server-Patches/0087-Configurable-Player-Collision.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 02:10:49 -0400 -Subject: [PATCH] Configurable Player Collision - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 439dcc6effdc91830d2b7ede9063982998b37120..504efea7b6f50a0d17f4f353781953dfb18bdeca 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -232,4 +232,9 @@ public class PaperConfig { - private static void regionFileCacheSize() { - regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); - } -+ -+ public static boolean enablePlayerCollisions = true; -+ private static void enablePlayerCollisions() { -+ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -index bc40f2cbe1645fd60c4cee106b90f17cd043d32d..c1bb5c325286119891e8d68ce8f7328c99edb486 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -@@ -112,7 +112,7 @@ public class PacketPlayOutScoreboardTeam implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(ScoreboardTeam::getName).collect(java.util.stream.Collectors.toList()); -+ for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { -+ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); -+ ScoreboardTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); -+ collideTeam.setCanSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all -+ } -+ // Paper end -+ - this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); - this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); - this.serverConnection.acceptConnections(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 152aa38788a21638aab7cfe2dc187671f1143bde..f9e9e51b0b0dcbf2a8424c7c14bd2cbb0d899e82 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -86,6 +86,7 @@ import net.minecraft.world.level.storage.SavedFile; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldNBTStorage; - import net.minecraft.world.phys.Vec3D; -+import net.minecraft.world.scores.Scoreboard; - import net.minecraft.world.scores.ScoreboardObjective; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; -@@ -145,6 +146,7 @@ public abstract class PlayerList { - // CraftBukkit start - private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); -+ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer minecraftserver, IRegistryCustom.Dimension iregistrycustom_dimension, WorldNBTStorage worldnbtstorage, int i) { - this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); -@@ -376,6 +378,13 @@ public abstract class PlayerList { - } - - entityplayer.syncInventory(); -+ // Paper start - Add to collideRule team if needed -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getScoreboardTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeam); -+ } -+ // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getDisplayName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getName(), entityplayer.locX(), entityplayer.locY(), entityplayer.locZ()); - } -@@ -496,6 +505,16 @@ public abstract class PlayerList { - entityplayer.playerTick(); // SPIGOT-924 - // CraftBukkit end - -+ // Paper start - Remove from collideRule team if needed -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreBoard = this.server.getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); -+ if (entityplayer.getScoreboardTeam() == team && team != null) { -+ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); -+ } -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); -@@ -1144,6 +1163,13 @@ public abstract class PlayerList { - } - // CraftBukkit end - -+ // Paper start - Remove collideRule team if it exists -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); -+ } -+ // Paper end - } - - // CraftBukkit start diff --git a/Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index 9696f8be1176..000000000000 --- a/Spigot-Server-Patches/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 13 Apr 2016 20:21:38 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 9b24afa4f4fe41d2261b16aaecec2144ac7d049f..5047a742d2e6a9749aa7d37e761d023a3425944b 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -29,7 +29,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - // CraftBukkit end - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; -- private final NetworkManager c; -+ private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -88,8 +88,34 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.c.close(chatmessage); - } else { - this.c.setPacketListener(new LoginListener(this.b, this.c)); -+ // Paper start - handshake event -+ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; -+ boolean handledByEvent = false; -+ // Try and handle the handshake through the event -+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? -+ java.net.InetSocketAddress socketAddress = (java.net.InetSocketAddress) this.getNetworkManager().socketAddress; -+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, socketAddress.getAddress().getHostAddress(), !proxyLogicEnabled); -+ if (event.callEvent()) { -+ // If we've failed somehow, let the client know so and go no further. -+ if (event.isFailed()) { -+ chatmessage = new ChatMessage(event.getFailMessage()); -+ this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.getNetworkManager().close(chatmessage); -+ return; -+ } -+ -+ if (event.getServerHostname() != null) packethandshakinginsetprotocol.hostname = event.getServerHostname(); -+ if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress.getPort()); -+ this.getNetworkManager().spoofedUUID = event.getUniqueId(); -+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); -+ handledByEvent = true; // Hooray, we did it! -+ } -+ } -+ // Don't try and handle default logic if it's been handled by the event. -+ if (!handledByEvent && proxyLogicEnabled) { -+ // Paper end - // Spigot Start -- if (org.spigotmc.SpigotConfig.bungee) { -+ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { - packethandshakinginsetprotocol.hostname = split[0]; diff --git a/Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch b/Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch deleted file mode 100644 index 05f34610328e..000000000000 --- a/Spigot-Server-Patches/0089-Configurable-RCON-IP-address.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Apr 2016 00:39:33 -0400 -Subject: [PATCH] Configurable RCON IP address - -For servers with multiple IP's, ability to bind to a specific interface. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 0ecff9f5e2ba444b196d80da341ff851dd5ce26f..b7cf02301c02ed0a6b696384e656426762ae2105 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -67,6 +67,8 @@ public class DedicatedServerProperties extends PropertyManager.EditableProperty whiteList; - public final GeneratorSettings generatorSettings; - -+ public final String rconIp; // Paper - Add rcon ip -+ - // CraftBukkit start - public DedicatedServerProperties(Properties properties, IRegistryCustom iregistrycustom, OptionSet optionset) { - super(properties, optionset); -@@ -118,6 +120,10 @@ public class DedicatedServerProperties extends PropertyManager> { - }; - } - -- @Nullable -- private String c(String s) { -+ @Nullable String getSettingIfExists(final String path) { return this.c(path); } // Paper - OBFHELPER -+ @Nullable private String c(String s) { // Paper - OBFHELPER - return (String) getOverride(s, this.properties.getProperty(s)); // CraftBukkit - } - -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -index 797a450a08da1b799e32fae2a71a7a50bb90d127..3b3e21d1d86629d6c5e06108e53d1c5e807074d8 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -@@ -62,7 +62,7 @@ public class RemoteControlListener extends RemoteConnectionThread { - @Nullable - public static RemoteControlListener a(IMinecraftServer iminecraftserver) { - DedicatedServerProperties dedicatedserverproperties = iminecraftserver.getDedicatedServerProperties(); -- String s = iminecraftserver.h_(); -+ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip - - if (s.isEmpty()) { - s = "0.0.0.0"; diff --git a/Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch deleted file mode 100644 index c379b25ebad2..000000000000 --- a/Spigot-Server-Patches/0090-Prevent-Fire-from-loading-chunks-wrongly-spread.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 17 Apr 2016 17:27:09 -0400 -Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread - -This causes the nether to spam unload/reload chunks, plus overall -bad behavior. - -This also stops fire from spreading to illegal locations. - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index ee5400fd3e493e1f0518a9e47ddbc997e7a0fb92..c22fad0038fdb0769e23db782e3341206fbd80f9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -135,7 +135,7 @@ public class BlockFire extends BlockFireAbstract { - BlockStateBoolean blockstateboolean = (BlockStateBoolean) BlockFire.h.get(enumdirection); - - if (blockstateboolean != null) { -- iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getType(blockposition.shift(enumdirection)))); -+ iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))); // Paper - prevent chunk loads - } - } - -@@ -215,6 +215,7 @@ public class BlockFire extends BlockFireAbstract { - } - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, l, j1, i1); -+ if (blockposition_mutableblockposition.isInvalidYLocation() || !worldserver.isLoaded(blockposition_mutableblockposition)) continue; // Paper - int l1 = this.a((IWorldReader) worldserver, (BlockPosition) blockposition_mutableblockposition); - - if (l1 > 0) { -@@ -260,10 +261,16 @@ public class BlockFire extends BlockFireAbstract { - } - - private void trySpread(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition -- int k = this.getBurnChance(world.getType(blockposition)); -+ // Paper start -+ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ return; -+ } -+ int k = this.getBurnChance(iblockdata); -+ // Paper end - - if (random.nextInt(i) < k) { -- IBlockData iblockdata = world.getType(blockposition); -+ //IBlockData iblockdata = world.getType(blockposition); // Paper - - // CraftBukkit start - org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -309,7 +316,7 @@ public class BlockFire extends BlockFireAbstract { - for (int j = 0; j < i; ++j) { - EnumDirection enumdirection = aenumdirection[j]; - -- if (this.e(iblockaccess.getType(blockposition.shift(enumdirection)))) { -+ if (this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))) { // Paper - prevent chunk loads - return true; - } - } -@@ -327,7 +334,12 @@ public class BlockFire extends BlockFireAbstract { - - for (int k = 0; k < j; ++k) { - EnumDirection enumdirection = aenumdirection[k]; -- IBlockData iblockdata = iworldreader.getType(blockposition.shift(enumdirection)); -+ // Paper start -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition.shift(enumdirection)); -+ if (iblockdata == null) { -+ continue; -+ } -+ // Paper end - - i = Math.max(this.getFlameChance(iblockdata), i); - } -@@ -338,7 +350,7 @@ public class BlockFire extends BlockFireAbstract { - - @Override - protected boolean e(IBlockData iblockdata) { -- return this.getFlameChance(iblockdata) > 0; -+ return iblockdata != null && this.getFlameChance(iblockdata) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now - } - - @Override diff --git a/Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch b/Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 56e55d42db03..000000000000 --- a/Spigot-Server-Patches/0091-Implement-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Tue, 19 Apr 2016 14:09:31 -0500 -Subject: [PATCH] Implement PlayerLocaleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index cda0e7f8f9a9d66ac4e5a3f52609a4271bf0c4b5..3f1f8f7fe9452f66b18a08ef480d50ef78ad3351 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1695,7 +1695,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return s; - } - -- public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start -@@ -1703,9 +1703,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); - this.server.server.getPluginManager().callEvent(event); - } -- if (!this.locale.equals(packetplayinsettings.locale)) { -+ if (this.locale == null || !this.locale.equals(packetplayinsettings.locale)) { // Paper - check for null - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.locale); - this.server.server.getPluginManager().callEvent(event); -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packetplayinsettings.locale).callEvent(); // Paper - } - this.locale = packetplayinsettings.locale; - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 4bb57229c045956bab631982e12c0fc420db450e..5698ef90bfeceec37eaf7f23361246ef125b3cd1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1877,8 +1877,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getLocale() { -- return getHandle().locale; -- -+ // Paper start - Locale change event -+ final String locale = getHandle().locale; -+ return locale != null ? locale : "en_us"; -+ // Paper end - } - - // Paper start diff --git a/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index 99e9b4058cd6..000000000000 --- a/Spigot-Server-Patches/0092-EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 22 Apr 2016 01:43:11 -0500 -Subject: [PATCH] EntityRegainHealthEvent isFastRegen API - -Don't even get me started - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index acbd10432b09172f7541b2f4081d1aa9812194ac..ecb07130be80b484e0f2241a368db967775148e8 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1130,10 +1130,16 @@ public abstract class EntityLiving extends Entity { - } - - public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { -+ // Paper start - Forward -+ heal(f, regainReason, false); -+ } -+ -+ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { -+ // Paper end - float f1 = this.getHealth(); - - if (f1 > 0.0F) { -- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); -+ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper - // Suppress during worldgen - if (this.valid) { - this.world.getServer().getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/food/FoodMetaData.java b/src/main/java/net/minecraft/world/food/FoodMetaData.java -index 7ed321acba6d46159f7d67b8d10a0a3e06ac88a9..e455b25b0809af15f6fde957121d0110da7eb08f 100644 ---- a/src/main/java/net/minecraft/world/food/FoodMetaData.java -+++ b/src/main/java/net/minecraft/world/food/FoodMetaData.java -@@ -87,7 +87,7 @@ public class FoodMetaData { - if (this.foodTickTimer >= this.saturatedRegenRate) { // CraftBukkit - float f = Math.min(this.saturationLevel, 6.0F); - -- entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason -+ entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen - // this.a(f); CraftBukkit - EntityExhaustionEvent - entityhuman.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent - this.foodTickTimer = 0; diff --git a/Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch b/Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch deleted file mode 100644 index c48a22b74f2a..000000000000 --- a/Spigot-Server-Patches/0093-Add-ability-to-configure-frosted_ice-properties.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 21 Apr 2016 23:51:55 -0700 -Subject: [PATCH] Add ability to configure frosted_ice properties - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1942f5224aaebb18adb591d6f70a419cfc1a7bdd..5baccb8d50c135ab20c38ffd0690f585514ce5af 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -259,4 +259,14 @@ public class PaperWorldConfig { - private void useVanillaScoreboardColoring() { - useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); - } -+ -+ public boolean frostedIceEnabled = true; -+ public int frostedIceDelayMin = 20; -+ public int frostedIceDelayMax = 40; -+ private void frostedIce() { -+ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); -+ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); -+ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); -+ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index 7239a30bd4a5dc4ed09802eea8f7126485ebb635..e32e94868386ff06ff29254e6cc3bee9b446a293 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -30,6 +30,7 @@ public class BlockIceFrost extends BlockIce { - - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (!worldserver.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.a(worldserver, blockposition, 4)) && worldserver.getLightLevel(blockposition) > 11 - (Integer) iblockdata.get(BlockIceFrost.a) - iblockdata.b((IBlockAccess) worldserver, blockposition) && this.e(iblockdata, (World) worldserver, blockposition)) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - EnumDirection[] aenumdirection = EnumDirection.values(); -@@ -42,12 +43,12 @@ public class BlockIceFrost extends BlockIce { - IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { -- worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - - } else { -- worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - diff --git a/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch deleted file mode 100644 index f215104b52c6..000000000000 --- a/Spigot-Server-Patches/0094-remove-null-possibility-for-getServer-singleton.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Apr 2016 00:57:27 -0400 -Subject: [PATCH] remove null possibility for getServer singleton - -to stop IDE complaining about potential NPE - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 026ddfba26439a00685f3962084aa6194086c9b7..f990f242a8d812a93b454b065a17fd4e8170355a 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -180,6 +180,7 @@ import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -+ private static MinecraftServer SERVER; // Paper - public static final Logger LOGGER = LogManager.getLogger(); - public static final File b = new File("usercache.json"); - public static final WorldSettings c = new WorldSettings("Demo World", EnumGamemode.SURVIVAL, false, EnumDifficulty.NORMAL, false, new GameRules(), DataPackConfiguration.a); -@@ -286,6 +287,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 29 Apr 2016 20:02:00 -0400 -Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes - -Maps used a modified version of rendering to support plugin controlled -imaging on maps. The Craft Map Renderer is much slower than Vanilla, -causing maps in item frames to cause a noticeable hit on server performance. - -This updates the map system to not use the Craft system if we detect that no -custom renderers are in use, defaulting to the much simpler Vanilla system. - -Additionally, numerous issues to player position tracking on maps has been fixed. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 2412c2fa22abe171254f7fe49d319bcd6cc533ff..c4bbc4e97ee1871ed6e4364c1fe9204b0dd2fdae 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1170,6 +1170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - { - if ( iter.next().trackee == entity ) - { -+ map.decorations.remove(entity.getDisplayName().getString()); // Paper - iter.remove(); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index f42e16589476c1bd10b13214dda5ac7bb3e52131..e3e3426a00128b56d523bb43a59b814b915ad0ff 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -86,6 +86,7 @@ import net.minecraft.world.item.ItemElytra; - import net.minecraft.world.item.ItemProjectileWeapon; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.ItemSword; -+import net.minecraft.world.item.ItemWorldMap; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.item.enchantment.EnchantmentManager; -@@ -104,6 +105,7 @@ import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.entity.TileEntityStructure; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock; -+import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.Scoreboard; -@@ -689,6 +691,12 @@ public abstract class EntityHuman extends EntityLiving { - return null; - } - // CraftBukkit end -+ // Paper start - remove player from map on drop -+ if (itemstack.getItem() == Items.FILLED_MAP) { -+ WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.world); -+ worldmap.updateSeenPlayers(this, itemstack); -+ } -+ // Paper end - - return entityitem; - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 3f057f0bd23bc1c693c8f04ee8acd6626c620008..d470af1814af332595c1c0beb1cdc552e186a6bb 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -57,6 +57,7 @@ public class WorldMap extends PersistentBase { - private final Map m = Maps.newHashMap(); - public final Map decorations = Maps.newLinkedHashMap(); - private final Map n = Maps.newHashMap(); -+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - - // CraftBukkit start - public final CraftMapView mapView; -@@ -69,6 +70,7 @@ public class WorldMap extends PersistentBase { - // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper - // CraftBukkit end - } - -@@ -136,6 +138,7 @@ public class WorldMap extends PersistentBase { - this.m.put(mapiconbanner.f(), mapiconbanner); - this.a(mapiconbanner.c(), (GeneratorAccess) null, mapiconbanner.f(), (double) mapiconbanner.a().getX(), (double) mapiconbanner.a().getZ(), 180.0D, mapiconbanner.d()); - } -+ this.vanillaRender.buffer = colors; // Paper - - NBTTagList nbttaglist1 = nbttagcompound.getList("frames", 10); - -@@ -216,6 +219,7 @@ public class WorldMap extends PersistentBase { - this.b(); - } - -+ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { this.a(entityhuman, itemstack); } // Paper - OBFHELPER - public void a(EntityHuman entityhuman, ItemStack itemstack) { - if (!this.humans.containsKey(entityhuman)) { - WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); -@@ -451,6 +455,21 @@ public class WorldMap extends PersistentBase { - - public class WorldMapHumanTracker { - -+ // Paper start -+ private void addSeenPlayers(java.util.Collection icons) { -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) trackee.getBukkitEntity(); -+ WorldMap.this.decorations.forEach((name, mapIcon) -> { -+ // If this cursor is for a player check visibility with vanish system -+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot -+ if (other == null || player.canSee(other)) { -+ icons.add(mapIcon); -+ } -+ }); -+ } -+ private boolean shouldUseVanillaMap() { -+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; -+ } -+ // Paper end - public final EntityHuman trackee; - private boolean d = true; - private int e; -@@ -467,9 +486,12 @@ public class WorldMap extends PersistentBase { - @Nullable - public Packet a(ItemStack itemstack) { - // CraftBukkit start -- org.bukkit.craftbukkit.map.RenderData render = WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()); // CraftBukkit -+ if (!this.d && this.i % 5 != 0) { this.i++; return null; } // Paper - this won't end up sending, so don't render it! -+ boolean vanillaMaps = shouldUseVanillaMap(); // Paper -+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()) : WorldMap.this.vanillaRender; // CraftBukkit // Paper - - java.util.Collection icons = new java.util.ArrayList(); -+ if (vanillaMaps) addSeenPlayers(icons); // Paper - - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - -diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -index 256a131781721c86dd6cdbc329335964570cbe8c..5768cd512ec166f1e8d1f4a28792015347297c3f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -+++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -@@ -5,7 +5,7 @@ import org.bukkit.map.MapCursor; - - public class RenderData { - -- public final byte[] buffer; -+ public byte[] buffer; // Paper - public final ArrayList cursors; - - public RenderData() { diff --git a/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch b/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch deleted file mode 100644 index 7d27f20665f2..000000000000 --- a/Spigot-Server-Patches/0096-LootTable-API-Replenishable-Lootables-Feature.patch +++ /dev/null @@ -1,736 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 21:19:14 -0400 -Subject: [PATCH] LootTable API & Replenishable Lootables Feature - -Provides an API to control the loot table for an object. -Also provides a feature that any Lootable Inventory (Chests in Structures) -can automatically replenish after a given time. - -This feature is good for long term worlds so that newer players -do not suffer with "Every chest has been looted" - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -269,4 +269,26 @@ public class PaperWorldConfig { - this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); - log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); - } -+ -+ public boolean autoReplenishLootables; -+ public boolean restrictPlayerReloot; -+ public boolean changeLootTableSeedOnFill; -+ public int maxLootableRefills; -+ public int lootableRegenMin; -+ public int lootableRegenMax; -+ private void enhancedLootables() { -+ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); -+ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); -+ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); -+ maxLootableRefills = getInt("lootables.max-refills", -1); -+ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); -+ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); -+ if (autoReplenishLootables) { -+ log("Lootables: Replenishing every " + -+ PaperConfig.timeSummary(lootableRegenMin) + " to " + -+ PaperConfig.timeSummary(lootableRegenMax) + -+ (restrictPlayerReloot ? " (restricting reloot)" : "") -+ ); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5dfc3c8008d64ad4ed71b4904c897f5005491349 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -@@ -0,0 +1,33 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Chunk; -+import org.bukkit.block.Block; -+ -+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { -+ -+ TileEntityLootable getTileEntity(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getTileEntity().getWorld(); -+ } -+ -+ default Block getBlock() { -+ final BlockPosition position = getTileEntity().getPosition(); -+ final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; -+ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getTileEntity().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..019a06fa2b43cacd3bbd4d58aba71b3728f37581 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -@@ -0,0 +1,28 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.entity.Entity; -+ -+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { -+ -+ net.minecraft.world.entity.Entity getHandle(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ default Entity getEntity() { -+ return getHandle().getBukkitEntity(); -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getHandle().getWorld(); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getHandle().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..59e8aea749bbba079e3304d9a5854280db2692e9 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -@@ -0,0 +1,71 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.loot.Lootable; -+ -+import java.util.UUID; -+ -+public interface PaperLootableInventory extends LootableInventory, Lootable { -+ -+ PaperLootableInventoryData getLootableData(); -+ LootableInventory getAPILootableInventory(); -+ -+ World getNMSWorld(); -+ -+ default org.bukkit.World getBukkitWorld() { -+ return getNMSWorld().getWorld(); -+ } -+ -+ @Override -+ default boolean isRefillEnabled() { -+ return getNMSWorld().paperConfig.autoReplenishLootables; -+ } -+ -+ @Override -+ default boolean hasBeenFilled() { -+ return getLastFilled() != -1; -+ } -+ -+ @Override -+ default boolean hasPlayerLooted(UUID player) { -+ return getLootableData().hasPlayerLooted(player); -+ } -+ -+ @Override -+ default Long getLastLooted(UUID player) { -+ return getLootableData().getLastLooted(player); -+ } -+ -+ @Override -+ default boolean setHasPlayerLooted(UUID player, boolean looted) { -+ final boolean hasLooted = hasPlayerLooted(player); -+ if (hasLooted != looted) { -+ getLootableData().setPlayerLootedState(player, looted); -+ } -+ return hasLooted; -+ } -+ -+ @Override -+ default boolean hasPendingRefill() { -+ long nextRefill = getLootableData().getNextRefill(); -+ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getLastFilled() { -+ return getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getNextRefill() { -+ return getLootableData().getNextRefill(); -+ } -+ -+ @Override -+ default long setNextRefill(long refillAt) { -+ if (refillAt < -1) { -+ refillAt = -1; -+ } -+ return getLootableData().setNextRefill(refillAt); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..904332454ede006f4ee33337d46b11674d78bef7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -@@ -0,0 +1,181 @@ -+package com.destroystokyo.paper.loottable; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.world.entity.player.EntityHuman; -+import org.bukkit.entity.Player; -+import org.bukkit.loot.LootTable; -+ -+import javax.annotation.Nullable; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Random; -+import java.util.UUID; -+ -+public class PaperLootableInventoryData { -+ -+ private static final Random RANDOM = new Random(); -+ -+ private long lastFill = -1; -+ private long nextRefill = -1; -+ private int numRefills = 0; -+ private Map lootedPlayers; -+ private final PaperLootableInventory lootable; -+ -+ public PaperLootableInventoryData(PaperLootableInventory lootable) { -+ this.lootable = lootable; -+ } -+ -+ long getLastFill() { -+ return this.lastFill; -+ } -+ -+ long getNextRefill() { -+ return this.nextRefill; -+ } -+ -+ long setNextRefill(long nextRefill) { -+ long prev = this.nextRefill; -+ this.nextRefill = nextRefill; -+ return prev; -+ } -+ -+ public boolean shouldReplenish(@Nullable EntityHuman player) { -+ LootTable table = this.lootable.getLootTable(); -+ -+ // No Loot Table associated -+ if (table == null) { -+ return false; -+ } -+ -+ // ALWAYS process the first fill or if the feature is disabled -+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { -+ return true; -+ } -+ -+ // Only process refills when a player is set -+ if (player == null) { -+ return false; -+ } -+ -+ // Chest is not scheduled for refill -+ if (this.nextRefill == -1) { -+ return false; -+ } -+ -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ -+ // Check if max refills has been hit -+ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { -+ return false; -+ } -+ -+ // Refill has not been reached -+ if (this.nextRefill > System.currentTimeMillis()) { -+ return false; -+ } -+ -+ -+ final Player bukkitPlayer = (Player) player.getBukkitEntity(); -+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); -+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { -+ event.setCancelled(true); -+ } -+ return event.callEvent(); -+ } -+ public void processRefill(@Nullable EntityHuman player) { -+ this.lastFill = System.currentTimeMillis(); -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ if (paperConfig.autoReplenishLootables) { -+ int min = paperConfig.lootableRegenMin; -+ int max = paperConfig.lootableRegenMax; -+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; -+ this.numRefills++; -+ if (paperConfig.changeLootTableSeedOnFill) { -+ this.lootable.setSeed(0); -+ } -+ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific -+ this.setPlayerLootedState(player.getUniqueID(), true); -+ } -+ } else { -+ this.lootable.clearLootTable(); -+ } -+ } -+ -+ -+ public void loadNbt(NBTTagCompound base) { -+ if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = base.getCompound("Paper.LootableData"); -+ if (comp.hasKey("lastFill")) { -+ this.lastFill = comp.getLong("lastFill"); -+ } -+ if (comp.hasKey("nextRefill")) { -+ this.nextRefill = comp.getLong("nextRefill"); -+ } -+ -+ if (comp.hasKey("numRefills")) { -+ this.numRefills = comp.getInt("numRefills"); -+ } -+ if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list -+ NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound -+ final int size = list.size(); -+ if (size > 0) { -+ this.lootedPlayers = new HashMap<>(list.size()); -+ } -+ for (int i = 0; i < size; i++) { -+ final NBTTagCompound cmp = list.getCompound(i); -+ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); -+ } -+ } -+ } -+ public void saveNbt(NBTTagCompound base) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.nextRefill != -1) { -+ comp.setLong("nextRefill", this.nextRefill); -+ } -+ if (this.lastFill != -1) { -+ comp.setLong("lastFill", this.lastFill); -+ } -+ if (this.numRefills != 0) { -+ comp.setInt("numRefills", this.numRefills); -+ } -+ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { -+ NBTTagList list = new NBTTagList(); -+ for (Map.Entry entry : this.lootedPlayers.entrySet()) { -+ NBTTagCompound cmp = new NBTTagCompound(); -+ cmp.setUUID("UUID", entry.getKey()); -+ cmp.setLong("Time", entry.getValue()); -+ list.add(cmp); -+ } -+ comp.set("lootedPlayers", list); -+ } -+ -+ if (!comp.isEmpty()) { -+ base.set("Paper.LootableData", comp); -+ } -+ } -+ -+ void setPlayerLootedState(UUID player, boolean looted) { -+ if (looted && this.lootedPlayers == null) { -+ this.lootedPlayers = new HashMap<>(); -+ } -+ if (looted) { -+ if (!this.lootedPlayers.containsKey(player)) { -+ this.lootedPlayers.put(player, System.currentTimeMillis()); -+ } -+ } else if (this.lootedPlayers != null) { -+ this.lootedPlayers.remove(player); -+ } -+ } -+ -+ boolean hasPlayerLooted(UUID player) { -+ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); -+ } -+ -+ Long getLastLooted(UUID player) { -+ return lootedPlayers != null ? lootedPlayers.get(player) : null; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c682bd7700d8103533026d46cfc63a7abde5a5f4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.vehicle.EntityMinecartContainer; -+import net.minecraft.world.level.World; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { -+ -+ private EntityMinecartContainer entity; -+ -+ public PaperMinecartLootableInventory(EntityMinecartContainer entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ entity.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return entity.lootTableSeed; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return entity.lootableData; -+ } -+ -+ @Override -+ public Entity getHandle() { -+ return entity; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) entity.getBukkitEntity(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return entity.world; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9dae34370d014a291f025f83b55e18bff4619a23 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -@@ -0,0 +1,65 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { -+ private TileEntityLootable tileEntityLootable; -+ -+ public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { -+ this.tileEntityLootable = tileEntityLootable; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ tileEntityLootable.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return tileEntityLootable.lootTableSeed; -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return tileEntityLootable.lootableData; -+ } -+ -+ @Override -+ public TileEntityLootable getTileEntity() { -+ return tileEntityLootable; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ World world = tileEntityLootable.getWorld(); -+ if (world == null) { -+ return null; -+ } -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return tileEntityLootable.getWorld(); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 6cbb797cb0de4b26d8ddd7f0bf567f49bd36f9c0..2b1b46bda48c0b137fe914c47a387e6e72a1be40 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -158,6 +158,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }; - // Paper end - -+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -index c4b970c37b1792ac0022936f2df4740183621a0d..0166d11cb540a536390f486e1069d6119d8d23d6 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -@@ -46,6 +46,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - public long lootTableSeed; - - // CraftBukkit start -+ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper - public List transaction = new java.util.ArrayList(); - private int maxStack = MAX_STACK; - -@@ -203,12 +204,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable != null) { - nbttagcompound.setString("LootTable", this.lootTable.toString()); - if (this.lootTableSeed != 0L) { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } -- } else { -+ } if (true) { // Paper - Always save the items, Table may stick around - ContainerUtil.a(nbttagcompound, this.items); - } - -@@ -217,11 +219,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ this.lootableData.loadNbt(nbttagcompound); // Paper - this.items = NonNullList.a(this.getSize(), ItemStack.b); - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- } else { -+ } if (true) { // Paper - always load the items, table may still remain - ContainerUtil.b(nbttagcompound, this.items); - } - -@@ -252,14 +255,15 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 62e6833a90d7adae3c7df33e3bc73b4288e0370b..1508e267a38555820e2d31f3075adca185fbd4b6 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -27,6 +27,7 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Nullable - public MinecraftKey lootTable; - public long lootTableSeed; -+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper - - protected TileEntityLootable(TileEntityTypes tileentitytypes) { - super(tileentitytypes); -@@ -42,16 +43,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { - } - - protected boolean b(NBTTagCompound nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); -+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- return true; -+ return false; // Paper - always load the items, table may still remain - } else { - return false; - } - } - - protected boolean c(NBTTagCompound nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable == null) { - return false; - } else { -@@ -60,19 +64,20 @@ public abstract class TileEntityLootable extends TileEntityContainer { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } - -- return true; -+ return false; // Paper - always save the items, table may still remain - } - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 524f27830752f424493c3ae8d793b871f6495594..dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockState - } - - // gets the wrapped TileEntity -- protected T getTileEntity() { -+ public T getTileEntity() { // Paper - protected -> public - return tileEntity; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 486fa8937d644f59a770db163482259525a7e465..54eb170fd533b0e91572601268fcbc167ed9bb5c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; - import org.bukkit.inventory.Inventory; -+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper - --public class CraftChest extends CraftLootable implements Chest { -+public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper - - public CraftChest(final Block block) { - super(block, TileEntityChest.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index f0a7e61a26c4668a9aa823d641f29bdecd42dd1f..3512054ede5fd1dd7605444e827e30a0be47f935 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -@@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.loot.LootTable; - import org.bukkit.loot.Lootable; - --public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { -+public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper - - public CraftLootable(Block block, Class tileEntityClass) { - super(block, tileEntityClass); -@@ -54,7 +54,7 @@ public abstract class CraftLootable extends CraftC - setLootTable(getLootTable(), seed); - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - public - MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getSnapshot().setLootTable(key, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index cbd121c21adfaf098dadca33de16a2e68d83c19a..d9a2552782c9242fb84cc0c8309a614a44777509 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -@@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; - import org.bukkit.inventory.Inventory; - - @SuppressWarnings("deprecation") --public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { -+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 5ffb8108f456c2f7f3ed1a25249baccb4cbf4add..bf8b5b25d1af0c5129261e10abf2866521b2c375 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -@@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return getHandle().lootTableSeed; - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getHandle().setLootTable(newKey, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index 17a42aec76f32a28b0c9885c60d1ed50c6727161..bfdcf01d2c6570493e86330d56500427dbb23146 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.minecart.HopperMinecart; - import org.bukkit.inventory.Inventory; - --public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { -+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { diff --git a/Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch deleted file mode 100644 index a61442ff7167..000000000000 --- a/Spigot-Server-Patches/0097-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 May 2016 23:33:08 -0400 -Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 504efea7b6f50a0d17f4f353781953dfb18bdeca..1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -237,4 +237,9 @@ public class PaperConfig { - private static void enablePlayerCollisions() { - enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); - } -+ -+ public static boolean saveEmptyScoreboardTeams = false; -+ private static void saveEmptyScoreboardTeams() { -+ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -index 3998565ccd87c966c0fb9e6757cd1861faa5bc15..52f27bdbd0df8bbbf2ad5144bc262b5093d83413 100644 ---- a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -+++ b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -@@ -182,6 +182,7 @@ public class PersistentScoreboard extends PersistentBase { - - while (iterator.hasNext()) { - ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next(); -+ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayerNameSet().isEmpty()) continue; // Paper - NBTTagCompound nbttagcompound = new NBTTagCompound(); - - nbttagcompound.setString("Name", scoreboardteam.getName()); diff --git a/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch b/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch deleted file mode 100644 index e05a8f8155d3..000000000000 --- a/Spigot-Server-Patches/0098-System-property-for-disabling-watchdoge.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 12 May 2016 23:02:58 -0500 -Subject: [PATCH] System property for disabling watchdoge - - -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0cb3028872041ce9f75e57fdd84b79636d8809f3..882cd398ee6babc3088ea0bb442d61fb46d8bf08 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -61,7 +61,7 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); diff --git a/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch b/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch deleted file mode 100644 index 3f1918cdd8ec..000000000000 --- a/Spigot-Server-Patches/0099-Optimize-UserCache-Thread-Safe.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 20:47:41 -0400 -Subject: [PATCH] Optimize UserCache / Thread Safe - -Because Techable keeps complaining about how this isn't thread safe, -easier to do this than replace the entire thing. - -Additionally, move Saving of the User cache to be done async, incase -the user never changed the default setting for Spigot's save on stop only. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f990f242a8d812a93b454b065a17fd4e8170355a..283c1111d99b6ae09b6db0c0079eeb0f1cbb7b2b 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -907,7 +907,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - - try { - BufferedWriter bufferedwriter = Files.newWriter(this.g, StandardCharsets.UTF_8); -@@ -268,6 +270,14 @@ public class UserCache { - } catch (IOException ioexception) { - ; - } -+ // Paper start -+ }; -+ if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); -+ } else { -+ save.run(); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch b/Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index dd0b2f44b9b4..000000000000 --- a/Spigot-Server-Patches/0100-Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 23:19:16 -0400 -Subject: [PATCH] Avoid blocking on Network Manager creation - -Per Paper issue 294 - -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index f66a5ba901601c1d359a287861a2edd8e3a106a7..d992cb5cd827e0fe655809e1088939cdad9c2301 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -52,6 +52,15 @@ public class ServerConnection { - public volatile boolean c; - private final List listeningChannels = Collections.synchronizedList(Lists.newArrayList()); - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private void addPending() { -+ NetworkManager manager = null; -+ while ((manager = pending.poll()) != null) { -+ connectedChannels.add(manager); -+ } -+ } -+ // Paper end - - public ServerConnection(MinecraftServer minecraftserver) { - this.e = minecraftserver; -@@ -87,7 +96,8 @@ public class ServerConnection { - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); - -- ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); - } -@@ -126,6 +136,7 @@ public class ServerConnection { - - synchronized (this.connectedChannels) { - // Spigot Start -+ this.addPending(); // Paper - // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) - { diff --git a/Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch b/Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch deleted file mode 100644 index 6138102655c3..000000000000 --- a/Spigot-Server-Patches/0101-Optional-TNT-doesn-t-move-in-water.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional TNT doesn't move in water - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index eb04fdb172a50ec1f5b7fe78fa0e7655246abd60..6eca3f300020006f02dd36253b522db442e3cc33 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,7 +2,6 @@ package com.destroystokyo.paper; - - import java.util.List; - --import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -291,4 +290,14 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean preventTntFromMovingInWater; -+ private void preventTntFromMovingInWater() { -+ if (PaperConfig.version < 13) { -+ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ set("prevent-tnt-from-moving-in-water", oldVal); -+ } -+ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); -+ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index f5227aa761d326376d057eaadcdbef024ed30241..44b79c97d5cc7570683e1b7f025b4f3ad65beb81 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -67,7 +67,7 @@ public class EntityTrackerEntry { - private boolean q; - private boolean r; - // CraftBukkit start -- private final Set trackedPlayers; -+ final Set trackedPlayers; // Paper - private -> package - // Paper start - private java.util.Map trackedPlayerMap = null; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f942d75982409f7640f073f9c77f8939225c6939..88ffc594a2ee7f8718337883609ad4c082f85f50 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2766,6 +2766,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean bV() { -+ // Paper start -+ return this.pushedByWater(); -+ } -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 535e7d7297d81026b8586d5049b72fa65519b464..63b35feac07f01b200dd68c4836ceb419e951660 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -4,10 +4,14 @@ import javax.annotation.Nullable; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityPose; -@@ -96,7 +100,27 @@ public class EntityTNTPrimed extends Entity { - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } - } -- -+ // Paper start - Optional prevent TNT from moving in water -+ if (!this.dead && this.inWater && this.world.paperConfig.preventTntFromMovingInWater) { -+ /* -+ * Author: Jedediah Smith -+ */ -+ // Send position and velocity updates to nearby players on every tick while the TNT is in water. -+ // This does pretty well at keeping their clients in sync with the server. -+ PlayerChunkMap.EntityTracker ete = ((WorldServer)this.world).getChunkProvider().playerChunkMap.trackedEntities.get(this.getId()); -+ if (ete != null) { -+ PacketPlayOutEntityVelocity velocityPacket = new PacketPlayOutEntityVelocity(this); -+ PacketPlayOutEntityTeleport positionPacket = new PacketPlayOutEntityTeleport(this); -+ -+ ete.trackedPlayers.stream() -+ .filter(viewer -> (viewer.locX() - this.locX()) * (viewer.locY() - this.locY()) * (viewer.locZ() - this.locZ()) < 16 * 16) -+ .forEach(viewer -> { -+ viewer.playerConnection.sendPacket(velocityPacket); -+ viewer.playerConnection.sendPacket(positionPacket); -+ }); -+ } -+ } -+ // Paper end - } - - private void explode() { -@@ -165,4 +189,11 @@ public class EntityTNTPrimed extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - Optional prevent TNT from moving in water -+ @Override -+ public boolean pushedByWater() { -+ return !world.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch b/Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch deleted file mode 100644 index 7aa9554cd728..000000000000 --- a/Spigot-Server-Patches/0102-Faster-redstone-torch-rapid-clock-removal.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Mon, 23 May 2016 12:12:37 +0200 -Subject: [PATCH] Faster redstone torch rapid clock removal - -Only resize the the redstone torch list once, since resizing arrays / lists is costly - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index cad86b0273c05767f78bcb3bdfaa9ea01e26af4e..d8ab2e22a5c0144decb5c657a123cc61722fcbf5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -44,6 +44,7 @@ import net.minecraft.world.level.biome.BiomeBase; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; -+import net.minecraft.world.level.block.BlockRedstoneTorch; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.ITickable; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -142,6 +143,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -+ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here - - public CraftWorld getWorld() { - return this.world; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -index 8142c0be2978d8975612488b17da9c2e25f3b5dd..6771c16b4228c1495950484422b73928f6184929 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -@@ -22,7 +22,7 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit - public class BlockRedstoneTorch extends BlockTorch { - - public static final BlockStateBoolean LIT = BlockProperties.r; -- private static final Map> b = new WeakHashMap(); -+ // Paper - Move the mapped list to World - - protected BlockRedstoneTorch(BlockBase.Info blockbase_info) { - super(blockbase_info, ParticleParamRedstone.a); -@@ -69,11 +69,15 @@ public class BlockRedstoneTorch extends BlockTorch { - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { - boolean flag = this.a((World) worldserver, blockposition, iblockdata); -- List list = (List) BlockRedstoneTorch.b.get(worldserver); -- -- while (list != null && !list.isEmpty() && worldserver.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { -- list.remove(0); -+ // Paper start -+ java.util.ArrayDeque redstoneUpdateInfos = worldserver.redstoneUpdateInfos; -+ if (redstoneUpdateInfos != null) { -+ BlockRedstoneTorch.RedstoneUpdateInfo curr; -+ while ((curr = redstoneUpdateInfos.peek()) != null && worldserver.getTime() - curr.getTime() > 60L) { -+ redstoneUpdateInfos.poll(); -+ } - } -+ // Paper end - - // CraftBukkit start - org.bukkit.plugin.PluginManager manager = worldserver.getServer().getPluginManager(); -@@ -138,9 +142,12 @@ public class BlockRedstoneTorch extends BlockTorch { - } - - private static boolean a(World world, BlockPosition blockposition, boolean flag) { -- List list = (List) BlockRedstoneTorch.b.computeIfAbsent(world, (iblockaccess) -> { -- return Lists.newArrayList(); -- }); -+ // Paper start -+ java.util.ArrayDeque list = world.redstoneUpdateInfos; -+ if (list == null) { -+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); -+ } -+ - - if (flag) { - list.add(new BlockRedstoneTorch.RedstoneUpdateInfo(blockposition.immutableCopy(), world.getTime())); -@@ -148,9 +155,9 @@ public class BlockRedstoneTorch extends BlockTorch { - - int i = 0; - -- for (int j = 0; j < list.size(); ++j) { -- BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = (BlockRedstoneTorch.RedstoneUpdateInfo) list.get(j); -- -+ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { -+ BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = iterator.next(); -+ // Paper end - if (blockredstonetorch_redstoneupdateinfo.a.equals(blockposition)) { - ++i; - if (i >= 8) { -@@ -165,7 +172,7 @@ public class BlockRedstoneTorch extends BlockTorch { - public static class RedstoneUpdateInfo { - - private final BlockPosition a; -- private final long b; -+ private final long b; final long getTime() { return this.b; } // Paper - OBFHELPER - - public RedstoneUpdateInfo(BlockPosition blockposition, long i) { - this.a = blockposition; diff --git a/Spigot-Server-Patches/0103-Add-server-name-parameter.patch b/Spigot-Server-Patches/0103-Add-server-name-parameter.patch deleted file mode 100644 index 84270eddc921..000000000000 --- a/Spigot-Server-Patches/0103-Add-server-name-parameter.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Sat, 28 May 2016 16:54:03 +0200 -Subject: [PATCH] Add server-name parameter - - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 8507f9a81b6068eb2f50e6390e3b4afe6d04fbbb..89abd046dc4043e2a138fd93cbf55b96cd90f890 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -143,6 +143,14 @@ public class Main { - .defaultsTo(new File("paper.yml")) - .describedAs("Yml file"); - // Paper end -+ -+ // Paper start -+ acceptsAll(asList("server-name"), "Name of the server") -+ .withRequiredArg() -+ .ofType(String.class) -+ .defaultsTo("Unknown Server") -+ .describedAs("Name"); -+ // Paper end - } - }; - diff --git a/Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch deleted file mode 100644 index 0b6b3e6fdb44..000000000000 --- a/Spigot-Server-Patches/0104-Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 May 2016 22:53:50 -0400 -Subject: [PATCH] Only send Dragon/Wither Death sounds to same world - -Also fix view distance lookup - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 6c58cf9d39cc0f0eb0dc7ddb126b8a3cf6a08fe7..74802de01dba30e38e09f6fc1f61e7bb64cf5f09 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -619,8 +619,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (net.minecraft.server.level.EntityPlayer player : this.world.getMinecraftServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index f74949c855aea32ceb16d8cb07f266d50045b57e..145767e8b0fc4105a0afa47af17dcdbb75e952bc 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -258,8 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (EntityPlayer player : (List)this.world.getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch b/Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch deleted file mode 100644 index d3f7911b3575..000000000000 --- a/Spigot-Server-Patches/0105-Fix-Double-World-Add-issues.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Jun 2016 22:54:34 -0400 -Subject: [PATCH] Fix Double World Add issues - -Vanilla will double add Spider Jockeys to the world, so ignore already added. - -Also add debug if something else tries to, and abort before world gets bad state - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index c4bbc4e97ee1871ed6e4364c1fe9204b0dd2fdae..e008ef98d6902f5e1000da99870b12ae9d61bddb 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1038,6 +1038,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - if (entity.dead) { - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; diff --git a/Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch b/Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch deleted file mode 100644 index e06e5310496a..000000000000 --- a/Spigot-Server-Patches/0106-Fix-Old-Sign-Conversion.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 17 Jun 2016 20:50:11 -0400 -Subject: [PATCH] Fix Old Sign Conversion - -1) Sign loading code was trying to parse the JSON before the check for oldSign. - That code could then skip the old sign converting code if it triggers a JSON parse exception. -2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag - This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 58789a6e285c31947508deae37caefe7e182278c..9b44ca96669ce423e5649f11743226dfdd9ce746 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -34,6 +34,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -+ public boolean isLoadingStructure = false; // Paper - private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 29db550d91cf9e5a23052772df6e482a5e2b0b90..ec550aaa4e7943af4ecdd2275f1f32c21edf770a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -78,13 +78,14 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - try { -- IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); -+ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error - -- if (oldSign) { -+ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted - lines[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; - continue; - } - // CraftBukkit end -+ IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - after old sign - - if (this.world instanceof WorldServer) { - try { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -index a2bc771df054923a9a96c0024a426ef707624359..9b82ff37faaafc3a799413f6949fb88a993aa9a0 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -@@ -278,9 +278,11 @@ public class DefinedStructure { - definedstructure_blockinfo.c.setLong("LootTableSeed", random.nextLong()); - } - -+ tileentity.isLoadingStructure = true; // Paper - tileentity.load(definedstructure_blockinfo.b, definedstructure_blockinfo.c); - tileentity.a(definedstructureinfo.c()); - tileentity.a(definedstructureinfo.d()); -+ tileentity.isLoadingStructure = false; // Paper - } - } - diff --git a/Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch deleted file mode 100644 index 60ded561675e..000000000000 --- a/Spigot-Server-Patches/0107-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 16 Jul 2016 19:11:17 -0500 -Subject: [PATCH] Don't lookup game profiles that have no UUID and no name - - -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 39d1c379b781c08bfdd720cd6810a9c0bb9f0d09..4ad084e7cea3b341ca0dbaa6e853cfc685a555ff 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -92,7 +92,7 @@ public class UserCache { - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -- if (!c() && gameprofile == null) { -+ if (!c() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(s)) { // Paper - Don't lookup a profile with a blank name - UUID uuid = EntityHuman.a(new GameProfile((UUID) null, s)); - - gameprofile = new GameProfile(uuid, s); diff --git a/Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch b/Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch deleted file mode 100644 index 51f6873f3ba7..000000000000 --- a/Spigot-Server-Patches/0108-Add-setting-for-proxy-online-mode-status.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Fri, 5 Aug 2016 01:03:08 +0200 -Subject: [PATCH] Add setting for proxy online mode status - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 1b8e5671c9dc8c15ce33d351c1bb20f28919b9a2..c52dc0346f93527965ef29a0ccdc4bf3debe302e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -23,6 +23,7 @@ import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; -+import org.spigotmc.SpigotConfig; - - public class PaperConfig { - -@@ -242,4 +243,13 @@ public class PaperConfig { - private static void saveEmptyScoreboardTeams() { - saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); - } -+ -+ public static boolean bungeeOnlineMode = true; -+ private static void bungeeOnlineMode() { -+ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); -+ } -+ -+ public static boolean isProxyOnlineMode() { -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 8a343a857dc4661ba256e39cf391dd2c7a1cc970..8c1f328ca1ba12ed63ec7bd7efad54ff633ba802 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -66,7 +66,8 @@ public class NameReferencingFileConverter { - return new String[i]; - }); - -- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (minecraftserver.getOnlineMode() -+ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting - minecraftserver.getGameProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, profilelookupcallback); - } else { - String[] astring1 = astring; -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 4ad084e7cea3b341ca0dbaa6e853cfc685a555ff..b9f94f957dd5372c8b02d785204690e4ade36a98 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -89,6 +89,7 @@ public class UserCache { - } - }; - -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -@@ -106,7 +107,7 @@ public class UserCache { - } - - private static boolean c() { -- return UserCache.b; -+ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index a084beced6647d6815e9bd728b2107c03998777c..f6d4e8d008b85bcf52cfeceb6b40fe9d1a2b557b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1515,7 +1515,8 @@ public final class CraftServer implements Server { - // Spigot Start - GameProfile profile = null; - // Only fetch an online UUID in online mode -- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( getOnlineMode() -+ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting - { - profile = console.getUserCache().getProfile( name ); - } diff --git a/Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch b/Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch deleted file mode 100644 index 909f6b527312..000000000000 --- a/Spigot-Server-Patches/0109-Optimise-BlockState-s-hashCode-equals.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockState's hashCode/equals - -These are singleton "single instance" objects. We can rely on -object identity checks safely. - -Use a simpler optimized hashcode - -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -index 0701c1a178852345b6bf01bce8b1d0559c535d45..f2f94950681b198ae7a4c31a044fd62e98e448ab 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -@@ -30,8 +30,7 @@ public class BlockStateBoolean extends IBlockState { - return obool.toString(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateBoolean && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index de85894beae7ee7d276cf2af3daa77377ce131c3..3079cd13ea1465f4221fde4fec7df639f7c1eb49 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -50,8 +50,7 @@ public class BlockStateEnum & INamable> extends IBlockState - return ((INamable) t0).getName(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateEnum && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -index 518c2ebe4cdfe4704bbec2abe81522cbca38da55..190978c889222185b47065e9e5f96a82e59c7b4e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -@@ -38,8 +38,7 @@ public class BlockStateInteger extends IBlockState { - return this.a; - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateInteger && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index e3969bad5be64bb41e2973751605d6820c16f021..759d6a4adaa511488ace5e2650eb685cbb6c4c16 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -60,23 +60,17 @@ public abstract class IBlockState> { - } - - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (!(object instanceof IBlockState)) { -- return false; -- } else { -- IBlockState iblockstate = (IBlockState) object; -- -- return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b); -- } -+ return this == object; // Paper - only one instance per configuration - } - -+ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration -+ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration - public final int hashCode() { - if (this.c == null) { - this.c = this.b(); - } - -- return this.c; -+ return this.hashCode; // Paper - only one instance per configuration - } - - public int b() { diff --git a/Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch b/Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch deleted file mode 100644 index febebcbdef51..000000000000 --- a/Spigot-Server-Patches/0110-Configurable-packet-in-spam-threshold.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 11 Sep 2016 14:30:57 -0500 -Subject: [PATCH] Configurable packet in spam threshold - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c52dc0346f93527965ef29a0ccdc4bf3debe302e..64d7c9058ee757a6d3cf3b648596092a810e105c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -252,4 +252,13 @@ public class PaperConfig { - public static boolean isProxyOnlineMode() { - return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); - } -+ -+ public static int packetInSpamThreshold = 300; -+ private static void packetInSpamThreshold() { -+ if (version < 11) { -+ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); -+ set("settings.incoming-packet-spam-threshold", oldValue); -+ } -+ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 7cb946ff73de5171debe34b37a784b6ed4e09150..702b06fac36f51bdb53d530e0c01bfe1dd67c527 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1464,13 +1464,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Spigot start - limit place/interactions - private int limitedPackets; - private long lastLimitedPacket = -1; -+ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold - - private boolean checkLimit(long timestamp) { -- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { -+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 - return false; - } - -- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { -+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper - lastLimitedPacket = timestamp; - limitedPackets = 0; - return true; diff --git a/Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch b/Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch deleted file mode 100644 index 62eca51bb7e8..000000000000 --- a/Spigot-Server-Patches/0111-Configurable-flying-kick-messages.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Tue, 20 Sep 2016 00:58:01 +0000 -Subject: [PATCH] Configurable flying kick messages - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 64d7c9058ee757a6d3cf3b648596092a810e105c..4e2f243faa209925dcb7c3ef89df3ed875c5ff78 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -261,4 +261,11 @@ public class PaperConfig { - } - packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); - } -+ -+ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; -+ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; -+ private static void flyingKickMessages() { -+ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); -+ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 702b06fac36f51bdb53d530e0c01bfe1dd67c527..908d52f48b4bf2ddd638f2d718e1f6cb6148ce0a 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -307,7 +307,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.B && !this.player.isSleeping()) { - if (++this.C > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message - return; - } - } else { -@@ -326,7 +326,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message - return; - } - } else { diff --git a/Spigot-Server-Patches/0112-Chunk-registration-fixes.patch b/Spigot-Server-Patches/0112-Chunk-registration-fixes.patch deleted file mode 100644 index b6399aa64eba..000000000000 --- a/Spigot-Server-Patches/0112-Chunk-registration-fixes.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 22:54:28 -0400 -Subject: [PATCH] Chunk registration fixes - -World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated - -Keep them consistent - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e008ef98d6902f5e1000da99870b12ae9d61bddb..6137a88e1dc8d19a4e35ad97500dabeddba008a8 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -847,7 +847,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity.cl()) { - this.getMethodProfiler().enter("chunkCheck"); - int i = MathHelper.floor(entity.locX() / 16.0D); -- int j = MathHelper.floor(entity.locY() / 16.0D); -+ int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { diff --git a/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch deleted file mode 100644 index ece37f9326c7..000000000000 --- a/Spigot-Server-Patches/0113-Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 16 Jun 2016 00:17:23 -0400 -Subject: [PATCH] Remove FishingHook reference on Craft Entity removal - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index f8e897f0bc4e5d0a432d20983fd37998bb00ae0f..b480ca876687991685b5e070181721da8192a5b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -@@ -119,4 +119,14 @@ public class CraftFishHook extends CraftProjectile implements FishHook { - public HookState getState() { - return HookState.values()[getHandle().hookState.ordinal()]; - } -+ -+ // Paper start -+ @Override -+ public void remove() { -+ super.remove(); -+ if (getHandle().getOwner() != null) { -+ getHandle().getOwner().hookedFish = null; -+ } -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch b/Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch deleted file mode 100644 index b4d980555f0e..000000000000 --- a/Spigot-Server-Patches/0114-Auto-fix-bad-Y-levels-on-player-login.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 23:48:39 -0400 -Subject: [PATCH] Auto fix bad Y levels on player login - -Bring down to a saner Y level if super high, as this can cause the server to crash - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3f1f8f7fe9452f66b18a08ef480d50ef78ad3351..3fca9c3566b5d9a1fafeb0700942d7658cd5a279 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -340,6 +340,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - @Override - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world - if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.getMinecraftServer().getForceGamemode()) { - this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); diff --git a/Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch b/Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch deleted file mode 100644 index c9e047b2c414..000000000000 --- a/Spigot-Server-Patches/0115-Option-to-remove-corrupt-tile-entities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 5 Oct 2016 16:27:36 -0500 -Subject: [PATCH] Option to remove corrupt tile entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6eca3f300020006f02dd36253b522db442e3cc33..622affa0dc3cc1eadaed400511f2ca2cde3fca2a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -300,4 +300,9 @@ public class PaperWorldConfig { - preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); - log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); - } -+ -+ public boolean removeCorruptTEs = false; -+ private void removeCorruptTEs() { -+ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index b6898cd6e6117fef65198db32b98a64c806811d4..7918dd4ad3e8cbb905b3929062a70fb7961b7d68 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -679,6 +679,12 @@ public class Chunk implements IChunkAccess { - "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); -+ -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeTileEntity(tileentity.getPosition()); -+ this.markDirty(); -+ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); -+ } - // Paper end - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch b/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch deleted file mode 100644 index 329cff50ea99..000000000000 --- a/Spigot-Server-Patches/0116-Add-EntityZapEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:30 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index cc31c8f31a385f3a8bfe334e75c3553689397750..d6e1697f64e60f2a567288c604a1690159955f37 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -255,6 +255,11 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - } - - entitypigzombie.setPersistent(); -+ // Paper start -+ if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 651ee45431c22b944fac640f936608ae587c055d..6df58fe8084d866de1697ef3fdbfe6648fe42b5f 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -787,6 +787,12 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - EntityVillager.LOGGER.info("Villager {} was struck by lightning {}.", this, entitylightning); - EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a((World) worldserver); - -+ // Paper start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) { -+ return; -+ } -+ // Paper end -+ - entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch); - entitywitch.prepare(worldserver, worldserver.getDamageScaler(entitywitch.getChunkCoordinates()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) null); - entitywitch.setNoAI(this.isNoAI()); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 418becfe2b4fe5ca808f250469bbb46414a5cbc0..3951ccb8821a1363d9b5f76568f5e7f6dcbc675b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1095,6 +1095,14 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { -+ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); -+ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { - HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); - horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch deleted file mode 100644 index 4ed73d0d74c6..000000000000 --- a/Spigot-Server-Patches/0117-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 12 Nov 2016 23:25:22 -0600 -Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 622affa0dc3cc1eadaed400511f2ca2cde3fca2a..e83216be5a00d5b927d8c2fc364551bd3077c974 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -2,6 +2,7 @@ package com.destroystokyo.paper; - - import java.util.List; - -+import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -305,4 +306,12 @@ public class PaperWorldConfig { - private void removeCorruptTEs() { - removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); - } -+ -+ public boolean filterNBTFromSpawnEgg = true; -+ private void fitlerNBTFromSpawnEgg() { -+ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); -+ if (!filterNBTFromSpawnEgg) { -+ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 3f10e41b18e09186635fd6f7c653b04db7b39d8e..411e3915c0aa00249aacb6658ed04309665d2fb4 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -272,6 +272,13 @@ public class EntityFallingBlock extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState")); -+ // Paper start - Block FallingBlocks with Command Blocks -+ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" -+ final Block b = this.block.getBlock(); -+ if (this.world.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { -+ this.block = Blocks.STONE.getBlockData(); -+ } -+ // Paper end - this.ticksLived = nbttagcompound.getInt("Time"); - if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) { - this.hurtEntities = nbttagcompound.getBoolean("HurtEntities"); diff --git a/Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch b/Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch deleted file mode 100644 index 48d9a082cd43..000000000000 --- a/Spigot-Server-Patches/0118-Cache-user-authenticator-threads.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 08:31:45 -0500 -Subject: [PATCH] Cache user authenticator threads - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3fca9c3566b5d9a1fafeb0700942d7658cd5a279..e6dacf68cd678d64547dcdc23b1175a4cfd279d1 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -4,7 +4,9 @@ import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -+import java.util.ArrayDeque; // Paper - import java.util.Collection; -+import java.util.Deque; // Paper - import java.util.Iterator; - import java.util.List; - import java.util.Optional; -@@ -172,7 +174,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public PlayerConnection playerConnection; - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -- public final List removeQueue = Lists.newLinkedList(); -+ public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final AdvancementDataPlayer advancementDataPlayer; - private final ServerStatisticManager serverStatisticManager; - private float lastHealthScored = Float.MIN_VALUE; -@@ -550,13 +552,20 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - while (!this.removeQueue.isEmpty()) { - int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); - int[] aint = new int[i]; -- Iterator iterator = this.removeQueue.iterator(); -+ //Iterator iterator = this.removeQueue.iterator(); // Paper - int j = 0; - -- while (iterator.hasNext() && j < i) { -+ // Paper start -+ /* while (iterator.hasNext() && j < i) { - aint[j++] = (Integer) iterator.next(); - iterator.remove(); -+ } */ -+ -+ Integer integer; -+ while (j < i && (integer = this.removeQueue.poll()) != null) { -+ aint[j++] = integer.intValue(); - } -+ // Paper end - - this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); - } -@@ -1561,7 +1570,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit -- this.removeQueue.addAll(entityplayer.removeQueue); -+ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only -+ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" -+ // type logic so it does need to be called, maybe? This is silly. -+ // this.removeQueue.addAll(entityplayer.removeQueue); -+ if (this.removeQueue != entityplayer.removeQueue) { -+ this.removeQueue.addAll(entityplayer.removeQueue); -+ } -+ // Paper end - this.cd = entityplayer.cd; - this.ci = entityplayer.ci; - this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); diff --git a/Spigot-Server-Patches/0119-Optimise-removeQueue.patch b/Spigot-Server-Patches/0119-Optimise-removeQueue.patch deleted file mode 100644 index c45413d9b29d..000000000000 --- a/Spigot-Server-Patches/0119-Optimise-removeQueue.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 25 Nov 2016 13:22:40 +0000 -Subject: [PATCH] Optimise removeQueue - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 49a0aefc7f9544b36175fdf3161b255e878952a6..c45647f2d05ed6b170aad10c0a3fb94570d2dd90 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -116,6 +116,12 @@ public class LoginListener implements PacketLoginInListener { - - } - -+ // Paper start - Cache authenticator threads -+ private static final AtomicInteger threadId = new AtomicInteger(0); -+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -+ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) -+ ); -+ // Paper end - // Spigot start - public void initUUID() - { -@@ -195,8 +201,8 @@ public class LoginListener implements PacketLoginInListener { - this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic().getEncoded(), this.e)); - } else { - // Spigot start -- new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -- -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - @Override - public void run() { - try { -@@ -207,7 +213,8 @@ public class LoginListener implements PacketLoginInListener { - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); - } - } -- }.start(); -+ }); -+ // Paper end - // Spigot end - } - -@@ -236,7 +243,8 @@ public class LoginListener implements PacketLoginInListener { - throw new IllegalStateException("Protocol error", cryptographyexception); - } - -- Thread thread = new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - public void run() { - GameProfile gameprofile = LoginListener.this.i; - -@@ -281,10 +289,8 @@ public class LoginListener implements PacketLoginInListener { - - return LoginListener.this.server.W() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } -- }; -- -- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LoginListener.LOGGER)); -- thread.start(); -+ }); -+ // Paper end - } - - // Spigot start diff --git a/Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch b/Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 2639712bd1f0..000000000000 --- a/Spigot-Server-Patches/0120-Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:21:52 -0500 -Subject: [PATCH] Allow Reloading of Command Aliases - -Reload the aliases stored in commands.yml - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f6d4e8d008b85bcf52cfeceb6b40fe9d1a2b557b..e5ade7ac2bd059e2d05f2f38d0dae77070c989f7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2281,5 +2281,24 @@ public final class CraftServer implements Server { - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); - } -+ -+ @Override -+ public boolean reloadCommandAliases() { -+ Set removals = getCommandAliases().keySet().stream() -+ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) -+ .collect(java.util.stream.Collectors.toSet()); -+ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); -+ File file = getCommandsConfigFile(); -+ try { -+ commandsConfiguration.load(file); -+ } catch (FileNotFoundException ex) { -+ return false; -+ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); -+ return false; -+ } -+ commandMap.registerServerAliases(); -+ return true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch b/Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index e872dba64fba..000000000000 --- a/Spigot-Server-Patches/0121-Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Thu, 8 Sep 2016 08:48:33 -0700 -Subject: [PATCH] Add source to PlayerExpChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index a52cd6d0318e0fee28fc5d252a4b596b92860320..a17812943b5402684c68ddeac5408dc939e42cf6 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -203,7 +203,7 @@ public class EntityExperienceOrb extends Entity { - } - - if (this.value > 0) { -- entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() -+ entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object - } - - this.die(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 3951ccb8821a1363d9b5f76568f5e7f6dcbc675b..2127455979b25055c38a4e8088419069d948e539 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -119,6 +119,7 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1054,6 +1055,17 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - Add orb -+ public static PlayerExpChangeEvent callPlayerExpChangeEvent(EntityHuman entity, EntityExperienceOrb entityOrb) { -+ Player player = (Player) entity.getBukkitEntity(); -+ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); -+ int expAmount = source.getExperience(); -+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static boolean handleBlockGrowEvent(World world, BlockPosition pos, IBlockData block) { - return handleBlockGrowEvent(world, pos, block, 3); - } diff --git a/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch deleted file mode 100644 index 304934ac4752..000000000000 --- a/Spigot-Server-Patches/0122-Don-t-let-fishinghooks-use-portals.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 16 Dec 2016 16:03:19 -0600 -Subject: [PATCH] Don't let fishinghooks use portals - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index bcc411107d531529dbce9d1d43896a3c70e63012..57e7b9c7f7f43666d442648120cda3b4b3e5bfb2 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -240,6 +240,11 @@ public class EntityFishingHook extends IProjectile { - - this.setMot(this.getMot().a(0.92D)); - this.af(); -+ // Paper start - These shouldn't be going through portals -+ if (this.inPortal) { -+ this.die(); -+ } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch b/Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch deleted file mode 100644 index 630ff8979e98..000000000000 --- a/Spigot-Server-Patches/0123-Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 7868259a94766a6100d7b278c4296dde0a7f9397..c325c9fe680d9033b20909bcd6100ecc4b0195f6 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -198,6 +198,17 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ // Paper start - Call ProjectileCollideEvent -+ // TODO: flag - noclip - call cancelled? -+ if (object instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)object); -+ if (event.isCancelled()) { -+ object = null; -+ movingobjectpositionentity = null; -+ } -+ } -+ // Paper end -+ - if (object != null && !flag) { - this.preOnHit((MovingObjectPosition) object); // CraftBukkit - projectile hit event - this.impulse = true; -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 2ceae34365c437f2a15ae8587fa9517ea47ad6f2..9660dc2263c48a5818b767843658eeb9ee1748ea 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.World; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -72,7 +73,16 @@ public abstract class EntityFireball extends IProjectile { - - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - -- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ -+ if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event - - // CraftBukkit start - Fire ProjectileHitEvent -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -index 149588433cd0ea0f71b45267e39b28697ccfd2c0..8bc65e9c0fa5e134a8eb4e03f0da5b2ccd06cd7c 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -@@ -14,6 +14,7 @@ import net.minecraft.world.level.block.entity.TileEntityEndGateway; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - public abstract class EntityProjectile extends IProjectile { -@@ -57,7 +58,17 @@ public abstract class EntityProjectile extends IProjectile { - } - - if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ if (movingobjectposition != null) { -+ // Paper end - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event -+ } // Paper - } - - this.checkBlockCollisions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 2127455979b25055c38a4e8088419069d948e539..2ca0d109b148321964ac68259df82e4b1d7c57b2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1199,6 +1199,16 @@ public class CraftEventFactory { - return CraftItemStack.asNMSCopy(bitem); - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPositionEntity position) { -+ Projectile projectile = (Projectile) entity.getBukkitEntity(); -+ org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { - Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); - ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch b/Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch deleted file mode 100644 index d30b0eae3342..000000000000 --- a/Spigot-Server-Patches/0124-Prevent-Pathfinding-out-of-World-Border.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Dec 2016 23:07:42 -0500 -Subject: [PATCH] Prevent Pathfinding out of World Border - -This prevents Entities from trying to run outside of the World Border - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index d71a6e5991629ce59c8529d7cc8064960e385236..d134333c736dc1ee1c722d680d7a9c22c1b265bd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -148,7 +148,7 @@ public abstract class NavigationAbstract { - // Paper start - Pathfind event - boolean copiedSet = false; - for (BlockPosition possibleTarget : set) { -- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ if (!getEntity().getWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border - MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { - if (!copiedSet) { - copiedSet = true; diff --git a/Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch b/Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch deleted file mode 100644 index 2bc6bb0583cf..000000000000 --- a/Spigot-Server-Patches/0125-Optimize-World.isLoaded-BlockPosition-Z.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 2 Dec 2016 00:11:43 -0500 -Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z - -Reduce method invocations for World.isLoaded(BlockPosition)Z - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index d8ab2e22a5c0144decb5c657a123cc61722fcbf5..bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -305,6 +305,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return chunk == null ? null : chunk.getFluid(blockposition); - } - -+ public final boolean isLoaded(BlockPosition blockposition) { -+ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper -+ } -+ - public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline - return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; - } diff --git a/Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch b/Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch deleted file mode 100644 index 212f2d89eb04..000000000000 --- a/Spigot-Server-Patches/0126-Bound-Treasure-Maps-to-World-Border.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:15:11 -0500 -Subject: [PATCH] Bound Treasure Maps to World Border - -Make it so a Treasure Map does not target a structure outside of the -World Border, where players are not even able to reach. - -This also would help the case where a players close to the border, and one -that is outside happens to be closer, but unreachable, yet another reachable -one is in border that would of been missed. - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index f16c76df5d7b184d57f4cc397f069eac9cc430cb..50e2085766caabec1125ca24a2117549efd1a354 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -36,6 +36,18 @@ public class WorldBorder { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } - -+ // Paper start -+ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); -+ public boolean isBlockInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(chunkX, 64, chunkZ); -+ return this.isInBounds(this.mutPos); -+ } -+ public boolean isChunkInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); -+ return this.isInBounds(this.mutPos); -+ } -+ // Paper end -+ - public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 6724927be178cb9a358a9276d01894a63154b7b3..ea7e3e15fa778c573d24f956f72f60579ea0b1a1 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -175,6 +175,7 @@ public abstract class StructureGenerator - int i2 = l + k * k1; - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); -+ if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper - IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - diff --git a/Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch b/Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch deleted file mode 100644 index 82ccdd75a9b7..000000000000 --- a/Spigot-Server-Patches/0127-Configurable-Cartographer-Treasure-Maps.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:26:27 -0500 -Subject: [PATCH] Configurable Cartographer Treasure Maps - -Allow configuring for cartographers to return the same map location - -Also allow turning off treasure maps all together as they can eat up Map ID's -which are limited in quantity. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e83216be5a00d5b927d8c2fc364551bd3077c974..2dc58b9f769ea43b737804456aafab47ecc143b8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -314,4 +314,14 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); - } - } -+ -+ public boolean enableTreasureMaps = true; -+ public boolean treasureMapsAlreadyDiscovered = false; -+ private void treasureMapsAlreadyDiscovered() { -+ enableTreasureMaps = getBoolean("enable-treasure-maps", true); -+ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); -+ if (treasureMapsAlreadyDiscovered) { -+ log("Treasure Maps will return already discovered locations"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index 764ff5d9ffb541a356a6bc8b321e619849dde747..0a34e319998a95a9654822e55a22eb964b2d626b 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -124,7 +124,8 @@ public class VillagerTrades { - return null; - } else { - WorldServer worldserver = (WorldServer) entity.world; -- BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, true); -+ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper -+ BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper - - if (blockposition != null) { - ItemStack itemstack = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index 38125a60bad4830db9de3580ab6d85fd122a0689..7bf16c5a3f2bb5525ce1ca0c0190c7671fc94797 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -64,7 +64,16 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - - if (vec3d != null) { - WorldServer worldserver = loottableinfo.getWorld(); -- BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, this.i); -+ // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { -+ /* -+ * NOTE: I fear users will just get a plain map as their "treasure" -+ * This is preferable to disrespecting the config. -+ */ -+ return itemstack; -+ } -+ // Paper end -+ BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.i); // Paper - - if (blockposition != null) { - ItemStack itemstack1 = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), this.g, true, true); diff --git a/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch deleted file mode 100644 index 61881f07d251..000000000000 --- a/Spigot-Server-Patches/0128-Optimize-ItemStack.isEmpty.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Dec 2016 03:48:29 -0500 -Subject: [PATCH] Optimize ItemStack.isEmpty() - -Remove hashMap lookup every check, simplify code to remove ternary - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index d7c5065457d910f3e5481fda046d368d5f66f67b..58045d500a6fbb7eb568f48c7d8ce7730d357577 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -208,7 +208,7 @@ public final class ItemStack { - } - - public boolean isEmpty() { -- return this == ItemStack.b ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); -+ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper - } - - public ItemStack cloneAndSubtract(int i) { diff --git a/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 6b9000b82388..000000000000 --- a/Spigot-Server-Patches/0129-Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0631cd531647239858b2a7298f58cc770720f69a..6ee5e1b0bb34ba490a130fbcbdb7a2706c5ecf86 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -38,6 +38,7 @@ import net.minecraft.world.entity.ai.control.ControllerLook; - import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.control.EntityAIBodyControl; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; - import net.minecraft.world.entity.ai.navigation.Navigation; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; -@@ -45,6 +46,8 @@ import net.minecraft.world.entity.ai.sensing.EntitySenses; - import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.decoration.EntityLeash; - import net.minecraft.world.entity.item.EntityItem; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityEnderman; - import net.minecraft.world.entity.monster.IMonster; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 72e53968c5fb03301ddec7a0cf937ac2f8cf0901..2ef991aa7f739d3577fbbf4386064557e8f7c904 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -28,6 +28,7 @@ import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.EnumMainHand; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityArrow; - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -@@ -79,6 +80,7 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f rightArmPose; - public Vector3f leftLegPose; - public Vector3f rightLegPose; -+ public boolean canMove = true; // Paper - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -862,4 +864,13 @@ public class EntityArmorStand extends EntityLiving { - private EntitySize s(boolean flag) { - return flag ? EntityArmorStand.bp : (this.isBaby() ? EntityArmorStand.bq : this.getEntityType().l()); - } -+ -+ // Paper start -+ @Override -+ public void move(EnumMoveType moveType, Vec3D vec3d) { -+ if (this.canMove) { -+ super.move(moveType, vec3d); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 86c8662b3864b264e26f8c63474fdd39bd6c873c..6f922e4cbb095439fcd76ee0d0c08bc4160b8107 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -229,4 +229,15 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { - return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getSlotFlag() + lockType.ordinal() * 8)) != 0; - } -+ // Paper start -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch b/Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch deleted file mode 100644 index 064f2ab51a9c..000000000000 --- a/Spigot-Server-Patches/0130-Properly-fix-item-duplication-bug.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Tue, 27 Dec 2016 01:57:57 +0000 -Subject: [PATCH] Properly fix item duplication bug - -Credit to prplz for figuring out the real issue - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e6dacf68cd678d64547dcdc23b1175a4cfd279d1..5b2ae94ed7d499e401a058691eb6ed413b626150 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2069,8 +2069,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- public boolean isFrozen() { -- return super.isFrozen() || !getBukkitEntity().isOnline(); -+ protected boolean isFrozen() { -+ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 908d52f48b4bf2ddd638f2d718e1f6cb6148ce0a..8a5a1ca08073d1a4df949a53fbf7e75339bf2761 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2819,7 +2819,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - public final boolean isDisconnected() { -- return !this.player.joining && !this.networkManager.isConnected(); -+ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch b/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch deleted file mode 100644 index 20f702475a62..000000000000 --- a/Spigot-Server-Patches/0131-String-based-Action-Bar-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 15:02:42 -0500 -Subject: [PATCH] String based Action Bar API - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index c8bb06a31242089ad950713bd5f94abbfe12adc8..68ce7605bd63ea280b96db8230463d2afb0a6cb1 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -58,7 +58,7 @@ public class SystemUtils { - private static final ExecutorService e = a("Main"); - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; -- public static final UUID b = new UUID(0L, 0L); -+ public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER - private static final Logger LOGGER = LogManager.getLogger(); - - public static Collector, ?, Map> a() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6d7f1dee9ae2fb0b9620d85969de86eee09020cc..c3058d6fca2fd58aea5001e4310592aa8bd20640 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -244,6 +244,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - // Paper start -+ @Override -+ public void sendActionBar(BaseComponent[] message) { -+ if (getHandle().playerConnection == null) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, message, -1, -1, -1)); -+ } -+ -+ @Override -+ public void sendActionBar(String message) { -+ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); -+ } -+ -+ @Override -+ public void sendActionBar(char alternateChar, String message) { -+ if (message == null || message.isEmpty()) return; -+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); -+ } -+ - @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - if (header != null) { diff --git a/Spigot-Server-Patches/0132-Firework-API-s.patch b/Spigot-Server-Patches/0132-Firework-API-s.patch deleted file mode 100644 index e42242de5cc2..000000000000 --- a/Spigot-Server-Patches/0132-Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index bf4826e90976fed2ae95e84cadc7f29433af1ddf..d5508deff819309034554abc7b36aac40fa33503 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -153,6 +153,7 @@ public class NBTTagCompound implements NBTBase { - return GameProfileSerializer.a(this.get(s)); - } - -+ public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { - NBTBase nbtbase = this.get(s); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -index 2df84b56ef35a18648e74a134ac7ab97c518e481..9cc59439ae2c4e758c44b2a92b78bc328efdfa1b 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -@@ -38,7 +38,8 @@ public class EntityFireworks extends IProjectile { - public static final DataWatcherObject SHOT_AT_ANGLE = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.i); - private int ticksFlown; - public int expectedLifespan; -- private EntityLiving ridingEntity; -+ public EntityLiving ridingEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public EntityFireworks(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -285,6 +286,11 @@ public class EntityFireworks extends IProjectile { - } - - nbttagcompound.setBoolean("ShotAtAngle", (Boolean) this.datawatcher.get(EntityFireworks.SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -301,7 +307,11 @@ public class EntityFireworks extends IProjectile { - if (nbttagcompound.hasKey("ShotAtAngle")) { - this.datawatcher.set(EntityFireworks.SHOT_AT_ANGLE, nbttagcompound.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (nbttagcompound.hasUUID("SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index d52f3cb5d76bde1cf29c654dade6d8379b44c2e5..ec6c0836f02e7ac5b72fd224a3022a844dce55cb 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -205,6 +205,7 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - if (flag1) { - object = new EntityFireworks(world, itemstack1, entityliving, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true); -+ ((EntityFireworks) object).spawningEntity = entityliving.getUniqueID(); // Paper - } else { - object = a(world, entityliving, itemstack, itemstack1); - if (flag || f3 != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 9153945c2e245b9a2a098bdf58b0dcab052084ff..a2950faa48021782f10db0673d12d178443f7ccc 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -27,6 +27,7 @@ public class ItemFireworks extends Item { - Vec3D vec3d = itemactioncontext.getPos(); - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - - world.addEntity(entityfireworks); - itemstack.subtract(1); -@@ -41,7 +42,11 @@ public class ItemFireworks extends Item { - ItemStack itemstack = entityhuman.b(enumhand); - - if (!world.isClientSide) { -- world.addEntity(new EntityFireworks(world, itemstack, entityhuman)); -+ // Paper start -+ final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); -+ entityfireworks.spawningEntity = entityhuman.getUniqueID(); -+ world.addEntity(entityfireworks); -+ // Paper end - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 33162fd419ab9a7b650ca9d4270a0c03f06f19f6..73c2da316e41329114fcb3d30cb009d9cc7de7b9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getDataWatcher().set(EntityFireworks.SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ EntityLiving boostedEntity = getHandle().ridingEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index 6e0a520b6234..000000000000 --- a/Spigot-Server-Patches/0133-PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 21:44:50 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 0c5d9600eadc0a550cc2d5e7b4ee665c030faa89..2808cd0b100bd65a730aba315ab47a59a4621b30 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.BiomeDecoratorGroups; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; -@@ -180,7 +181,7 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - location.setPitch(player.getLocation().getPitch()); - location.setYaw(player.getLocation().getYaw()); - -- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); // Paper - Bukkit.getPluginManager().callEvent(teleEvent); - if (teleEvent.isCancelled()) { - return; diff --git a/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 6618bb4dd0a9..000000000000 --- a/Spigot-Server-Patches/0134-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5c488c8a40c648c5c432d38d95d3e00fde2cdb75..642efd930dc6cfad1d9436df97f151ea69b24b0c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -282,6 +282,48 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ int size = 0; -+ for (PlayerChunk playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.Chunk chunk = playerchunk.getChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.tileEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tileEntityListTick.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -+ if (chunkHolder.getChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { diff --git a/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch b/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch deleted file mode 100644 index cde18f2475d5..000000000000 --- a/Spigot-Server-Patches/0135-Enforce-Sync-Player-Saves.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:41:58 -0500 -Subject: [PATCH] Enforce Sync Player Saves - -Saving players async is extremely dangerous. This will force it to main -the same way we handle async chunk loads. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 95ff827b1d5704d279d258bdfb43fd33ec7a9187..d7cf89f4603779ce9a2e9a6f837a81684f209826 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1047,11 +1047,13 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper -+ return null; }); // Paper - ensure main - } - - public WhiteList getWhitelist() { diff --git a/Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch b/Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch deleted file mode 100644 index 51aa6dfbfc9d..000000000000 --- a/Spigot-Server-Patches/0136-Don-t-allow-entities-to-ride-themselves-572.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Sun, 8 Jan 2017 04:31:36 +0000 -Subject: [PATCH] Don't allow entities to ride themselves - #572 - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ee160558d84b24e1309262874a9d433bbe6593f3..49da1525cfc46743013bbac0528ec58501cab6eb 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2041,6 +2041,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean addPassenger(Entity entity) { // CraftBukkit -+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.getVehicle() != this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { diff --git a/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch deleted file mode 100644 index 1bdda8112e36..000000000000 --- a/Spigot-Server-Patches/0137-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:31:46 -0500 -Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player - -Adds lots of information about why this orb exists. - -Replaces isFromBottle() with logic that persists entity reloads too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 164fd6b867bc68f6aba3fa2c17371e87495baea3..74b4b127f39a0ad06e8f9add6861763724ab70ba 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -409,7 +409,7 @@ public class PlayerInteractManager { - - // Drop event experience - if (flag && event != null) { -- iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop(), this.player); // Paper - } - - return true; -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index a17812943b5402684c68ddeac5408dc939e42cf6..f4da22b33c704e675510b4b1a3aa7c180088be29 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -31,9 +31,59 @@ public class EntityExperienceOrb extends Entity { - public int value; - private EntityHuman targetPlayer; - private int targetTime; -+ // Paper start -+ public java.util.UUID sourceEntityId; -+ public java.util.UUID triggerEntityId; -+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ -+ private void loadPaperNBT(NBTTagCompound nbttagcompound) { -+ if (!nbttagcompound.hasKeyOfType("Paper.ExpData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = nbttagcompound.getCompound("Paper.ExpData"); -+ if (comp.hasUUID("source")) { -+ this.sourceEntityId = comp.getUUID("source"); -+ } -+ if (comp.hasUUID("trigger")) { -+ this.triggerEntityId = comp.getUUID("trigger"); -+ } -+ if (comp.hasKey("reason")) { -+ String reason = comp.getString("reason"); -+ try { -+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); -+ } catch (Exception e) { -+ this.world.getServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); -+ } -+ } -+ } -+ private void savePaperNBT(NBTTagCompound nbttagcompound) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.sourceEntityId != null) { -+ comp.setUUID("source", this.sourceEntityId); -+ } -+ if (this.triggerEntityId != null) { -+ comp.setUUID("trigger", triggerEntityId); -+ } -+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { -+ comp.setString("reason", this.spawnReason.name()); -+ } -+ nbttagcompound.set("Paper.ExpData", comp); -+ } - - public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { -+ this(world, d0, d1, d2, i, null, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { -+ this(world, d0, d1, d2, i, reason, triggerId, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { - this(EntityTypes.EXPERIENCE_ORB, world); -+ this.sourceEntityId = sourceId != null ? sourceId.getUniqueID() : null; -+ this.triggerEntityId = triggerId != null ? triggerId.getUniqueID() : null; -+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ // Paper end - this.setPosition(d0, d1, d2); - this.yaw = (float) (this.random.nextDouble() * 360.0D); - this.setMot((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); -@@ -168,6 +218,7 @@ public class EntityExperienceOrb extends Entity { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); - nbttagcompound.setShort("Value", (short) this.value); -+ this.savePaperNBT(nbttagcompound); // Paper - } - - @Override -@@ -175,6 +226,7 @@ public class EntityExperienceOrb extends Entity { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); - this.value = nbttagcompound.getShort("Value"); -+ this.loadPaperNBT(nbttagcompound); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index dc715a0275b148c3c66610d6fb873626180c82d5..b66b340fdef9423ad8dce290065e028a0c135ea8 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1594,7 +1594,8 @@ public abstract class EntityLiving extends Entity { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ EntityLiving attacker = killer != null ? killer : lastDamager; // Paper -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, this instanceof EntityPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } - this.expToDrop = 0; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -index 8d0c7469999bb6d75debf427ff4d7fa5d2d5c505..28dd42921961c6a47f2d85a5f93b8298f2c228d3 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -@@ -262,7 +262,7 @@ public abstract class EntityAnimal extends EntityAgeable { - if (worldserver.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 7941a083353bb1d9ba81c41d7a566b72bdc955d9..459b7727e946679989477f4a7e99c5ca47ac0b30 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -1306,7 +1306,7 @@ public class EntityFox extends EntityAnimal { - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 5d08b83e2832cad2c8726ae817e003d970bc52a0..bf224c97854daa379c61affff6a0ac9524c2c35d 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -561,7 +561,7 @@ public class EntityTurtle extends EntityAnimal { - Random random = this.animal.getRandom(); - - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 74802de01dba30e38e09f6fc1f61e7bb64cf5f09..97ef4c65c8cc569a99d9697f56bd44d32b151328 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -661,7 +661,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.killer, this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 3604fffb9ba13a019e98e0a1a0ef7ba81c8dc329..adce6f17a5dd33004f8a67cd55d195de029e0263 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -600,7 +600,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - if (merchantrecipe.isRewardExp()) { -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 46da22aeef6132a96e413301935c4fef7a96e0ee..4f81a97b1451fec0bb5fd1479acad97846c40c7c 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -189,7 +189,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - if (merchantrecipe.isRewardExp()) { - int i = 3 + this.random.nextInt(4); - -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 57e7b9c7f7f43666d442648120cda3b4b3e5bfb2..d40b056b2ff14033113bd7108a3295f8783b8bdf 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -503,7 +503,7 @@ public class EntityFishingHook extends IProjectile { - this.world.addEntity(entityitem); - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { -- entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop())); -+ entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper - } - // CraftBukkit end - if (itemstack1.getItem().a((Tag) TagsItem.FISHES)) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -index 87fe16c81b57ba07399f5566ab8bd77d71db36a1..e07353a6b34196e3d275ba482fbef7e4d209c31d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -@@ -54,7 +54,7 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getShooter(), this)); // Paper - } - - this.die(); -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index cba1de50f3035ae1b9366f474745d50a1f8fc014..fad7355a549aef811bca43be198af3d1c0a53980 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -94,7 +94,7 @@ public class ContainerGrindstone extends Container { - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, entityhuman)); // Paper - } - - world.triggerEffect(1042, blockposition, 0); -diff --git a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -index 48324295913dd9a9bd31332b5b811a729b621dfb..a114e576e5d80c25cc7f2b17f0dc3ad706a1b877 100644 ---- a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -+++ b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.TileEntityFurnace; - - public class SlotFurnaceResult extends Slot { - -- private final EntityHuman a; -+ private final EntityHuman a; public final EntityHuman getPlayer() { return this.a; } // Paper OBFHELPER - private int b; - - public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index d285c4e3d9f938973bf7fb904680044b414e6236..615a4418fd276cd3e0b3686d962ebaf13ef5d4be 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -267,13 +267,13 @@ public class Block extends BlockBase implements IMaterial { - } - } - -- public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i) { -+ public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i, net.minecraft.server.level.EntityPlayer player) { // Paper - if (worldserver.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - while (i > 0) { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 9744d51a52c5eb99c4cf9e36d9380c49674dd136..deaa4c136c23dc6c258cc1ce68523b3c007c80f9 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -603,7 +603,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper - } - - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ccd110c4bfaa263e04154dcc2a5bdbff1f3a7ec2..2513e9a5b66598337f5d380a036ee10fdbab38c3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1835,7 +1835,7 @@ public class CraftWorld implements World { - } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new EntityTNTPrimed(world, x, y, z, null); - } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new EntityExperienceOrb(world, x, y, z, 0); -+ entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper - } else if (LightningStrike.class.isAssignableFrom(clazz)) { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index da14f59aec2b6854c3a47fb531aadc9ddb74954c..c6880830720baa2723ab003e51be1b48574d7319 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -20,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; - } - -+ // Paper start -+ public java.util.UUID getTriggerEntityId() { -+ return getHandle().triggerEntityId; -+ } -+ public java.util.UUID getSourceEntityId() { -+ return getHandle().sourceEntityId; -+ } -+ public SpawnReason getSpawnReason() { -+ return getHandle().spawnReason; -+ } -+ // Paper end -+ - @Override - public EntityExperienceOrb getHandle() { - return (EntityExperienceOrb) entity; diff --git a/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch b/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch deleted file mode 100644 index 5f443dacfc58..000000000000 --- a/Spigot-Server-Patches/0138-Cap-Entity-Collisions.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 22 Jan 2017 18:07:56 -0500 -Subject: [PATCH] Cap Entity Collisions - -Limit a single entity to colliding a max of configurable times per tick. -This will alleviate issues where living entities are hoarded in 1x1 pens - -This is not tied to the maxEntityCramming rule. Cramming will still apply -just as it does in Vanilla, but entity pushing logic will be capped. - -You can set this to 0 to disable collisions. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299e27df7e3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -324,4 +324,10 @@ public class PaperWorldConfig { - log("Treasure Maps will return already discovered locations"); - } - } -+ -+ public int maxCollisionsPerEntity; -+ private void maxEntityCollision() { -+ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -+ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 49da1525cfc46743013bbac0528ec58501cab6eb..b798190628c1d83b5bf9e5497b515ef1e9f26707 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 6fa269cec002fcffd6d02125c20efa9314148243..2eee92f74a7c82ec7df05db6df79743b4345cc86 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2903,8 +2903,11 @@ public abstract class EntityLiving extends Entity { - } - } - -- for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - world.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < world.paperConfig.maxCollisionsPerEntity; ++j) { // Paper - Entity entity = (Entity) list.get(j); -+ entity.numCollisions++; // Paper -+ numCollisions++; // Paper - - this.C(entity); - } diff --git a/Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch b/Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch deleted file mode 100644 index db58842a9623..000000000000 --- a/Spigot-Server-Patches/0139-Remove-CraftScheduler-Async-Task-Debugger.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Feb 2017 00:04:04 -0500 -Subject: [PATCH] Remove CraftScheduler Async Task Debugger - -I have not once ever seen this system help debug a crash. -One report of a suspected memory leak with the system. - -This adds additional overhead to asynchronous task dispatching - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { - } - parsePending(); - } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) -@@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); - temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper - } - - private void addTask(final CraftTask task) { -@@ -507,10 +507,15 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public String toString() { -+ // Paper start -+ return ""; -+ /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); - return string.append('}').toString(); -+ */ -+ // Paper end - } - - @Deprecated diff --git a/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index a382dd4190be..000000000000 --- a/Spigot-Server-Patches/0140-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e8150c456efe72a561d6a6a7647eca05fbc8bd94..56f83a930c3dad1a1de366bff530131d92b4893c 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -121,7 +121,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; -- private final Queue A; -+ private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -179,7 +179,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMap = new PlayerMap(); - this.trackedEntities = new Int2ObjectOpenHashMap(); - this.z = new Long2ByteOpenHashMap(); -- this.A = Queues.newConcurrentLinkedQueue(); -+ this.A = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.definedStructureManager = definedstructuremanager; - this.w = convertable_conversionsession.a(worldserver.getDimensionKey()); - this.world = worldserver; -@@ -437,7 +437,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -459,7 +459,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - Runnable runnable; - -- while ((booleansupplier.getAsBoolean() || this.A.size() > 2000) && (runnable = (Runnable) this.A.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((booleansupplier.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch b/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch deleted file mode 100644 index 31754281aa81..000000000000 --- a/Spigot-Server-Patches/0141-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 2eee92f74a7c82ec7df05db6df79743b4345cc86..3d6b8fd09c07e78c0d786dff9658eb0089f853cf 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -338,6 +338,7 @@ public abstract class EntityLiving extends Entity { - super.a(d0, flag, iblockdata, blockposition); - } - -+ public boolean canBreatheUnderwater() { return this.cM(); } // Paper - OBFHELPER - public boolean cM() { - return this.getMonsterType() == EnumMonsterType.UNDEAD; - } -@@ -381,7 +382,7 @@ public abstract class EntityLiving extends Entity { - - if (this.isAlive()) { - if (this.a((Tag) TagsFluid.WATER) && !this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { -- if (!this.cM() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirTicks(this.l(this.getAirTicks())); - if (this.getAirTicks() == -20) { - this.setAirTicks(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 2ef991aa7f739d3577fbbf4386064557e8f7c904..57e0ea95df34fab22d6c5868ab839d56a3fa85fc 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -872,5 +872,10 @@ public class EntityArmorStand extends EntityLiving { - super.move(moveType, vec3d); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch b/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch deleted file mode 100644 index 4db53e83364b..000000000000 --- a/Spigot-Server-Patches/0142-Properly-handle-async-calls-to-restart-the-server.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Fri, 12 May 2017 23:34:11 -0500 -Subject: [PATCH] Properly handle async calls to restart the server - -The watchdog thread calls the server restart function asynchronously. Prior to -this change, it attempted to do several non-safe operations from the watchdog -thread, rather than the main. Specifically, because of a separate upstream change, -it causes player entities to be ticked asynchronously, among other things. - -This is dangerous. - -This patch moves the old handling into a synchronous variant, for calls from the -restart command, and adds separate handling for async calls, such as those from -the watchdog thread. - -When calling from the watchdog thread, we cannot assume the main thread is in a -tickable state; it may be completely deadlocked. In order to handle this, we mark -the server as stopping, in order to account for situations where the server should -complete a tick reasonbly soon, i.e. 99% of cases. - -Should the server not enter a state where it is stopping within 10 seconds, We -will assume that the server has in fact deadlocked and will proceed to force -kill the server. - -This modification does not force restart the server should we actually enter a -deadlocked state where the server is stopping, whereas this will in most cases -exit within a reasonable amount of time, to put a fixed limit on a process that -will have plugins and worlds saving to the disk has a high potential to result -in corruption/dataloss. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 283c1111d99b6ae09b6db0c0079eeb0f1cbb7b2b..d92ca78e483b3f085e3bad1d1250cac2f9031fa7 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -201,6 +201,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant, WorldServer> worldServer; - private PlayerList playerList; - private volatile boolean isRunning; -+ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart - private boolean isStopped; - private int ticks; - protected final Proxy proxy; -@@ -860,7 +861,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && new File( split[0] ).isFile() ) -+ // Paper - extract method and cleanup -+ boolean isRestarting = addShutdownHook( restartScript ); -+ if ( isRestarting ) - { -- System.out.println( "Attempting to restart with " + restartScript ); -+ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); -+ } else -+ { -+ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -+ } -+ // Stop the watchdog -+ WatchdogThread.doStop(); - -- // Disable Watchdog -- WatchdogThread.doStop(); -+ shutdownServer( isRestarting ); -+ // Paper end -+ } catch ( Exception ex ) -+ { -+ ex.printStackTrace(); -+ } -+ } - -- // Kick all players -- for ( EntityPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) -- { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); -- } -- // Give the socket a chance to send the packets -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -- // Close the socket so we can rebind with the new process -- MinecraftServer.getServer().getServerConnection().b(); -+ // Paper start - sync copied from above with minor changes, async added -+ private static void shutdownServer(boolean isRestarting) -+ { -+ if ( MinecraftServer.getServer().isMainThread() ) -+ { -+ // Kick all players -+ for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) -+ { -+ p.playerConnection.disconnect(SpigotConfig.restartMessage); -+ } -+ // Give the socket a chance to send the packets -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } - -- // Give time for it to kick in -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -+ closeSocket(); - -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { -- } -+ // Actually shutdown -+ try -+ { -+ MinecraftServer.getServer().close(); // calls stop() -+ } catch ( Throwable t ) -+ { -+ } -+ -+ // Actually stop the JVM -+ System.exit( 0 ); - -- // This will be done AFTER the server has completely halted -- Thread shutdownHook = new Thread() -+ } else -+ { -+ // Mark the server to shutdown at the end of the tick -+ MinecraftServer.getServer().safeShutdown( false, isRestarting ); -+ -+ // wait 10 seconds to see if we're actually going to try shutdown -+ try -+ { -+ Thread.sleep( 10000 ); -+ } -+ catch (InterruptedException ignored) -+ { -+ } -+ -+ // Check if we've actually hit a state where the server is going to safely shutdown -+ // if we have, let the server stop as usual -+ if (MinecraftServer.getServer().isStopped()) return; -+ -+ // If the server hasn't stopped by now, assume worse case and kill -+ closeSocket(); -+ System.exit( 0 ); -+ } -+ } -+ // Paper end -+ -+ // Paper - Split from moved code -+ private static void closeSocket() -+ { -+ // Close the socket so we can rebind with the new process -+ MinecraftServer.getServer().getServerConnection().b(); -+ -+ // Give time for it to kick in -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } -+ } -+ // Paper end -+ -+ // Paper start - copied from above and modified to return if the hook registered -+ private static boolean addShutdownHook(String restartScript) -+ { -+ String[] split = restartScript.split( " " ); -+ if ( split.length > 0 && new File( split[0] ).isFile() ) -+ { -+ Thread shutdownHook = new Thread() -+ { -+ @Override -+ public void run() - { -- @Override -- public void run() -+ try - { -- try -+ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -+ if ( os.contains( "win" ) ) - { -- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -- if ( os.contains( "win" ) ) -- { -- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -- } else -- { -- Runtime.getRuntime().exec( "sh " + restartScript ); -- } -- } catch ( Exception e ) -+ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -+ } else - { -- e.printStackTrace(); -+ Runtime.getRuntime().exec( "sh " + restartScript ); - } -+ } catch ( Exception e ) -+ { -+ e.printStackTrace(); - } -- }; -- -- shutdownHook.setDaemon( true ); -- Runtime.getRuntime().addShutdownHook( shutdownHook ); -- } else -- { -- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -- -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { - } -- } -- System.exit( 0 ); -- } catch ( Exception ex ) -+ }; -+ -+ shutdownHook.setDaemon( true ); -+ Runtime.getRuntime().addShutdownHook( shutdownHook ); -+ return true; -+ } else - { -- ex.printStackTrace(); -+ return false; - } - } -+ // Paper end -+ - } diff --git a/Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch b/Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch deleted file mode 100644 index 6de0abb61f2e..000000000000 --- a/Spigot-Server-Patches/0143-Add-system-property-to-disable-book-size-limits.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 13 May 2017 20:11:21 -0500 -Subject: [PATCH] Add system property to disable book size limits - -If anyone comes in with a watchdog crash related to books after this patch -you will not only be publicly shamed but also made an example of. - -Disables the security limits on books entirely, allowing plugins AND players -to make books with as much data as they want. Do not use this without -limiting incoming data from packets in some other way. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 0acf6571c02b41f178503966be7be3eface6a335..27217b633f9259a6fbad15ea566c8a188775f447 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -41,6 +41,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - static final int MAX_PAGES = 100; - static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes - static final int MAX_TITLE_LENGTH = 32; -+ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override - - protected String title; - protected String author; -@@ -243,7 +244,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - if (title == null) { - this.title = null; - return true; -- } else if (title.length() > MAX_TITLE_LENGTH) { -+ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - return false; - } - -@@ -440,7 +441,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - String validatePage(String page) { - if (page == null) { - page = ""; -- } else if (page.length() > MAX_PAGE_LENGTH) { -+ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - page = page.substring(0, MAX_PAGE_LENGTH); - } - return page; -@@ -450,7 +451,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - // asserted: page != null - if (this.pages == null) { - this.pages = new ArrayList(); -- } else if (this.pages.size() >= MAX_PAGES) { -+ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override - return; - } - this.pages.add(page); diff --git a/Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch deleted file mode 100644 index 270c71d6d4d4..000000000000 --- a/Spigot-Server-Patches/0144-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 16 May 2017 21:29:08 -0500 -Subject: [PATCH] Add option to make parrots stay on shoulders despite movement - -Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. -Instead, switches the behavior so that players have to sneak to make the birds leave. - -I suspect Mojang may switch to this behavior before full release. - -To be converted into a Paper-API event at some point in the future? - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c611b5a63498f5ad1f50a75ccd5d7299e27df7e3..9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -330,4 +330,10 @@ public class PaperWorldConfig { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); - log( "Max Entity Collisions: " + maxCollisionsPerEntity ); - } -+ -+ public boolean parrotsHangOnBetter; -+ private void parrotsHangOnBetter() { -+ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); -+ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 8a5a1ca08073d1a4df949a53fbf7e75339bf2761..bf3195eaf1fc7bdddafbb54d0ccf825e95b63210 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2052,6 +2052,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - switch (packetplayinentityaction.c()) { - case PRESS_SHIFT_KEY: - this.player.setSneaking(true); -+ -+ // Paper start - Hang on! -+ if (this.player.world.paperConfig.parrotsHangOnBetter) { -+ this.player.releaseShoulderEntities(); -+ } -+ // Paper end -+ - break; - case RELEASE_SHIFT_KEY: - this.player.setSneaking(false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index e3e3426a00128b56d523bb43a59b814b915ad0ff..ba26fc2405e17d582da971d03147fb1865e9b546 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -532,7 +532,7 @@ public abstract class EntityHuman extends EntityLiving { - this.j(this.getShoulderEntityLeft()); - this.j(this.getShoulderEntityRight()); - if (!this.world.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.isFlying || this.isSleeping()) { -- this.releaseShoulderEntities(); -+ if (!this.world.paperConfig.parrotsHangOnBetter) this.releaseShoulderEntities(); // Paper - Hang on! - } - - } diff --git a/Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch b/Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 90d6f97e8aff..000000000000 --- a/Spigot-Server-Patches/0145-Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Fri, 9 Jun 2017 07:24:34 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 4e2f243faa209925dcb7c3ef89df3ed875c5ff78..48319aaf1c525c6fb7bdee5c2f570a0d056d4eae 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -268,4 +268,9 @@ public class PaperConfig { - flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); - flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); - } -+ -+ public static boolean suggestPlayersWhenNullTabCompletions = true; -+ private static void suggestPlayersWhenNull() { -+ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e5ade7ac2bd059e2d05f2f38d0dae77070c989f7..e2062f2a86cd764c86e69709b370f54b7fb5e15c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2300,5 +2300,10 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - return true; - } -+ -+ @Override -+ public boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch b/Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch deleted file mode 100644 index 27a636d47a17..000000000000 --- a/Spigot-Server-Patches/0146-Use-TerminalConsoleAppender-for-console-improvements.patch +++ /dev/null @@ -1,549 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 9 Jun 2017 19:03:43 +0200 -Subject: [PATCH] Use TerminalConsoleAppender for console improvements - -Rewrite console improvements (console colors, tab completion, -persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. - -New features: - - Support console colors for Vanilla commands - - Add console colors for warnings and errors - - Server can now be turned off safely using CTRL + C. JLine catches - the signal and the implementation shuts down the server cleanly. - - Support console colors and persistent input line when running in - IntelliJ IDEA - -Other changes: - - Server starts 1-2 seconds faster thanks to optimizations in Log4j - configuration - -diff --git a/pom.xml b/pom.xml -index 8ce86529d55c256c745dac2cfa7bd2e3c702bf87..d82c43adadc2da44e9018a6be3e594d32d010bef 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -57,10 +57,26 @@ - compile - - -- jline -- jline -- 2.12.1 -- compile -+ net.minecrell -+ terminalconsoleappender -+ 1.2.0 -+ -+ -+ org.jline -+ jline-terminal-jansi -+ 3.12.1 -+ runtime -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-core -+ runtime - - - org.apache.logging.log4j -@@ -334,10 +350,18 @@ - - META-INF/services/java.sql.Driver - -+ - - - - -+ -+ -+ com.github.edwgiz -+ maven-shade-plugin.log4j2-cachefile-transformer -+ 2.13.1 -+ -+ - - - org.apache.maven.plugins -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -new file mode 100644 -index 0000000000000000000000000000000000000000..89eeb9d202405747409e65fcf226d95379987e29 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.console; -+ -+import net.minecraft.server.dedicated.DedicatedServer; -+import net.minecrell.terminalconsole.SimpleTerminalConsole; -+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -+import org.jline.reader.LineReader; -+import org.jline.reader.LineReaderBuilder; -+ -+public final class PaperConsole extends SimpleTerminalConsole { -+ -+ private final DedicatedServer server; -+ -+ public PaperConsole(DedicatedServer server) { -+ this.server = server; -+ } -+ -+ @Override -+ protected LineReader buildReader(LineReaderBuilder builder) { -+ return super.buildReader(builder -+ .appName("Paper") -+ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) -+ .completer(new ConsoleCommandCompleter(this.server)) -+ ); -+ } -+ -+ @Override -+ protected boolean isRunning() { -+ return !this.server.isStopped() && this.server.isRunning(); -+ } -+ -+ @Override -+ protected void runCommand(String command) { -+ this.server.issueCommand(command, this.server.getServerCommandListener()); -+ } -+ -+ @Override -+ protected void shutdown() { -+ this.server.safeShutdown(false); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.console; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; -+ -+public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { -+ -+ private static final Logger LOGGER = LogManager.getRootLogger(); -+ -+ @Override -+ public void sendRawMessage(String message) { -+ // TerminalConsoleAppender supports color codes directly in log messages -+ LOGGER.info(message); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d92ca78e483b3f085e3bad1d1250cac2f9031fa7..bad6dfcb9ed558499c39880c44ae514ee2051a3c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -12,6 +12,7 @@ import com.mojang.datafixers.DataFixer; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -160,7 +161,7 @@ import org.apache.logging.log4j.Logger; - import com.mojang.serialization.DynamicOps; - import com.mojang.serialization.Lifecycle; - import com.google.common.collect.ImmutableSet; --import jline.console.ConsoleReader; -+// import jline.console.ConsoleReader; // Paper - import joptsimple.OptionSet; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -@@ -255,7 +256,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -@@ -324,7 +325,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant replacements = new EnumMap(ChatColor.class); - private final ChatColor[] colors = ChatColor.values(); -@@ -93,5 +91,5 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { - } else { - return new ColouredConsoleSender(); - } -- } -+ }*/ // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index befcc19f9b56df9096b98a23b0020f1db793ea5b..a957695457cf3252848ce6ef37069692841b8e28 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -4,20 +4,31 @@ import java.util.Collections; - import java.util.List; - import java.util.concurrent.ExecutionException; - import java.util.logging.Level; --import jline.console.completer.Completer; -+import net.minecraft.server.dedicated.DedicatedServer; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.util.Waitable; -+ -+// Paper start - JLine update -+import org.jline.reader.Candidate; -+import org.jline.reader.Completer; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+// Paper end - import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { -- private final CraftServer server; -+ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer - -- public ConsoleCommandCompleter(CraftServer server) { -+ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; - } - -+ // Paper start - Change method signature for JLine update - @Override -- public int complete(final String buffer, final int cursor, final List candidates) { -+ public void complete(LineReader reader, ParsedLine line, List candidates) { -+ final CraftServer server = this.server.server; -+ final String buffer = line.line(); -+ // Paper end - Waitable> waitable = new Waitable>() { - @Override - protected List evaluate() { -@@ -29,25 +40,37 @@ public class ConsoleCommandCompleter implements Completer { - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); - } - }; -- this.server.getServer().processQueue.add(waitable); -+ server.getServer().processQueue.add(waitable); // Paper - Remove "this." - try { - List offers = waitable.get(); - if (offers == null) { -- return cursor; -+ return; // Paper - Method returns void -+ } -+ -+ // Paper start - JLine update -+ for (String completion : offers) { -+ if (completion.isEmpty()) { -+ continue; -+ } -+ -+ candidates.add(new Candidate(completion)); - } -- candidates.addAll(offers); -+ // Paper end - -+ // Paper start - JLine handles cursor now -+ /* - final int lastSpace = buffer.lastIndexOf(' '); - if (lastSpace == -1) { - return cursor - buffer.length(); - } else { - return cursor - (buffer.length() - lastSpace - 1); - } -+ */ -+ // Paper end - } catch (ExecutionException e) { -- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); -+ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } -- return cursor; - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 70f8d42992aa348ef7b2d03d22cdd59d7c73f0fe..449e99d1b673870ed6892f6ab2c715a2db35c35d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -17,7 +17,7 @@ public class ServerShutdownThread extends Thread { - server.close(); - } finally { - try { -- server.reader.getTerminal().restore(); -+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -index 99564fed7ce77e29dbdc591bcfe656af741acf8a..9a2da548b8860b496e396564b2c8f6383f020193 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -@@ -5,12 +5,12 @@ import java.io.IOException; - import java.io.OutputStream; - import java.util.logging.Level; - import java.util.logging.Logger; --import jline.console.ConsoleReader; -+//import jline.console.ConsoleReader; - import org.bukkit.craftbukkit.Main; --import org.fusesource.jansi.Ansi; --import org.fusesource.jansi.Ansi.Erase; -+//import org.fusesource.jansi.Ansi; -+//import org.fusesource.jansi.Ansi.Erase; - --public class TerminalConsoleWriterThread extends Thread { -+public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable - private final ConsoleReader reader; - private final OutputStream output; - -@@ -54,5 +54,5 @@ public class TerminalConsoleWriterThread extends Thread { - Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); - } - } -- } -+ }*/ - } -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -new file mode 100644 -index 0000000000000000000000000000000000000000..0694b21465fb9e4164e71862ff24b62241b191f2 ---- /dev/null -+++ b/src/main/resources/log4j2.component.properties -@@ -0,0 +1 @@ -+log4j.skipJansi=true -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 722ca84968cbbbdeffd09939abff0cccd0a84010..620b9490e5f159080e50289d127404a1b56adbef 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,17 +1,14 @@ - - - -- -- -- - - - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -24,10 +21,9 @@ - - - -- - -- - -+ - - - diff --git a/Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch b/Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch deleted file mode 100644 index 6832d0263e6e..000000000000 --- a/Spigot-Server-Patches/0147-provide-a-configurable-option-to-disable-creeper-lin.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Jun 2017 21:01:18 +0100 -Subject: [PATCH] provide a configurable option to disable creeper lingering - effect spawns - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9d1cddc6038f0fd0286e4a32013ae98ff0b00dd1..90ca51dfdbb3045dd528450225cba96f5834166e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -336,4 +336,10 @@ public class PaperWorldConfig { - parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); - log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); - } -+ -+ public boolean disableCreeperLingeringEffect; -+ private void setDisableCreeperLingeringEffect() { -+ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); -+ log("Creeper lingering effect: " + disableCreeperLingeringEffect); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 655bbb3fe27b3d38492f37e2b98675ea21e1ea2c..e3124c46f740df3a24b22128d50ce7efb7d76f17 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -262,7 +262,7 @@ public class EntityCreeper extends EntityMonster { - private void createEffectCloud() { - Collection collection = this.getEffects(); - -- if (!collection.isEmpty()) { -+ if (!collection.isEmpty() && !world.paperConfig.disableCreeperLingeringEffect) { // Paper - EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX(), this.locY(), this.locZ()); - - entityareaeffectcloud.setSource(this); // CraftBukkit diff --git a/Spigot-Server-Patches/0148-Item-canEntityPickup.patch b/Spigot-Server-Patches/0148-Item-canEntityPickup.patch deleted file mode 100644 index 3aa1baa985ee..000000000000 --- a/Spigot-Server-Patches/0148-Item-canEntityPickup.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:17 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 6ee5e1b0bb34ba490a130fbcbdb7a2706c5ecf86..c22b5f8fcdd4aa7dac242f634ef73edcd8745fc6 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -607,6 +607,11 @@ public abstract class EntityInsentient extends EntityLiving { - EntityItem entityitem = (EntityItem) iterator.next(); - - if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.p() && this.i(entityitem.getItemStack())) { -+ // Paper Start -+ if (!entityitem.canMobPickup) { -+ continue; -+ } -+ // Paper End - this.b(entityitem); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 38b91b450c6bdc25efaed495ce26d909a52531bf..c486c07a358c0b444e1a1372b6d0fa2901840eac 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -47,6 +47,7 @@ public class EntityItem extends Entity { - private UUID owner; - public final float b; - private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit -+ public boolean canMobPickup = true; // Paper - - public EntityItem(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index f333dd2726f554a3137a3a78d162905f4ed1435e..5988cdd18b7e4bfca0075fd2356cfe9c4e673954 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -49,6 +49,16 @@ public class CraftItem extends CraftEntity implements Item { - item.age = value; - } - -+ // Paper Start -+ public boolean canMobPickup() { -+ return item.canMobPickup; -+ } -+ -+ public void setCanMobPickup(boolean canMobPickup) { -+ item.canMobPickup = canMobPickup; -+ } -+ // Paper End -+ - @Override - public void setOwner(UUID uuid) { - item.setOwner(uuid); diff --git a/Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch b/Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index 2bbbc7656e51..000000000000 --- a/Spigot-Server-Patches/0149-PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:09 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index c486c07a358c0b444e1a1372b6d0fa2901840eac..3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -363,6 +363,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = entityhuman.inventory.canHold(itemstack); - int remaining = i - canHold; -+ boolean flyAtPlayer = false; // Paper - - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); -@@ -370,8 +371,14 @@ public class EntityItem extends Entity { - PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!entityhuman.canPickUpLoot); - this.world.getServer().getPluginManager().callEvent(playerEvent); -+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper - if (playerEvent.isCancelled()) { - itemstack.setCount(i); // SPIGOT-5294 - restore count -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - return; - } - -@@ -401,7 +408,11 @@ public class EntityItem extends Entity { - // CraftBukkit end - - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { -- entityhuman.receive(this, i); -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - if (itemstack.isEmpty()) { - this.die(); - itemstack.setCount(i); diff --git a/Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch b/Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 13d2f543544f..000000000000 --- a/Spigot-Server-Patches/0150-PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:30 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 3b72032f6f4f4bd64d1202658cc0c6ee4fb76ea9..de11fd9772f30ac72c3ca52ec4efc3fef4091425 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -36,6 +36,7 @@ import net.minecraft.server.MinecraftServer; - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper - - public class EntityItem extends Entity { - -@@ -365,6 +366,22 @@ public class EntityItem extends Entity { - int remaining = i - canHold; - boolean flyAtPlayer = false; // Paper - -+ // Paper start -+ if (this.pickupDelay <= 0) { -+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); -+ this.world.getServer().getPluginManager().callEvent(attemptEvent); -+ -+ flyAtPlayer = attemptEvent.getFlyAtPlayer(); -+ if (attemptEvent.isCancelled()) { -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ -+ return; -+ } -+ } -+ // Paper end -+ - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); - // Call legacy event diff --git a/Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch b/Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch deleted file mode 100644 index 9c039a3e699e..000000000000 --- a/Spigot-Server-Patches/0151-Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:21 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5d357b0f84b5242066dcce203752a0f46e9a249c..4f9c42a4b0256f181263bf5e0492714a01fbec38 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -104,6 +104,7 @@ import net.minecraft.world.level.storage.WorldNBTStorage; - import net.minecraft.world.level.storage.loot.LootTableRegistry; - import net.minecraft.world.phys.Vec3D; - import org.apache.commons.lang.Validate; -+import org.apache.commons.lang3.StringUtils; - import org.bukkit.BanList; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; -@@ -177,6 +178,7 @@ import org.bukkit.craftbukkit.util.Versioning; - import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions; - import org.bukkit.entity.Entity; - import org.bukkit.entity.Player; -+import org.bukkit.event.command.UnknownCommandEvent; // Paper - import org.bukkit.event.inventory.InventoryType; - import org.bukkit.event.player.PlayerChatTabCompleteEvent; - import org.bukkit.event.server.BroadcastMessageEvent; -@@ -793,7 +795,13 @@ public final class CraftServer implements Server { - - // Spigot start - if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { -- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); -+ // Paper start -+ UnknownCommandEvent event = new UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (StringUtils.isNotEmpty(event.getMessage())) { -+ sender.sendMessage(event.getMessage()); -+ } -+ // Paper end - } - // Spigot end - diff --git a/Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch b/Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch deleted file mode 100644 index 4db2f358ab0a..000000000000 --- a/Spigot-Server-Patches/0152-Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,575 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 22:11:48 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Establishes base extension of profile systems for future edits too - -diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3d9452892a4077e64f37424052a9e52d76dd7a6d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -@@ -0,0 +1,301 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.base.Charsets; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import com.mojang.authlib.properties.PropertyMap; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.players.UserCache; -+import org.apache.commons.lang3.Validate; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.spigotmc.SpigotConfig; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.AbstractSet; -+import java.util.Collection; -+import java.util.Iterator; -+import java.util.Objects; -+import java.util.Set; -+import java.util.UUID; -+ -+public class CraftPlayerProfile implements PlayerProfile { -+ -+ private GameProfile profile; -+ private final PropertySet properties = new PropertySet(); -+ -+ public CraftPlayerProfile(CraftPlayer player) { -+ this.profile = player.getHandle().getProfile(); -+ } -+ -+ public CraftPlayerProfile(UUID id, String name) { -+ this.profile = new GameProfile(id, name); -+ } -+ -+ public CraftPlayerProfile(GameProfile profile) { -+ Validate.notNull(profile, "GameProfile cannot be null!"); -+ this.profile = profile; -+ } -+ -+ @Override -+ public boolean hasProperty(String property) { -+ return profile.getProperties().containsKey(property); -+ } -+ -+ @Override -+ public void setProperty(ProfileProperty property) { -+ String name = property.getName(); -+ PropertyMap properties = profile.getProperties(); -+ properties.removeAll(name); -+ properties.put(name, new Property(name, property.getValue(), property.getSignature())); -+ } -+ -+ public GameProfile getGameProfile() { -+ return profile; -+ } -+ -+ @Nullable -+ @Override -+ public UUID getId() { -+ return profile.getId(); -+ } -+ -+ @Override -+ public UUID setId(@Nullable UUID uuid) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(uuid, prev.getName()); -+ copyProfileProperties(prev, this.profile); -+ return prev.getId(); -+ } -+ -+ @Nullable -+ @Override -+ public String getName() { -+ return profile.getName(); -+ } -+ -+ @Override -+ public String setName(@Nullable String name) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(prev.getId(), name); -+ copyProfileProperties(prev, this.profile); -+ return prev.getName(); -+ } -+ -+ @Nonnull -+ @Override -+ public Set getProperties() { -+ return properties; -+ } -+ -+ @Override -+ public void setProperties(Collection properties) { -+ properties.forEach(this::setProperty); -+ } -+ -+ @Override -+ public void clearProperties() { -+ profile.getProperties().clear(); -+ } -+ -+ @Override -+ public boolean removeProperty(String property) { -+ return !profile.getProperties().removeAll(property).isEmpty(); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ CraftPlayerProfile that = (CraftPlayerProfile) o; -+ return Objects.equals(profile, that.profile); -+ } -+ -+ @Override -+ public int hashCode() { -+ return profile.hashCode(); -+ } -+ -+ @Override -+ public String toString() { -+ return profile.toString(); -+ } -+ -+ @Override -+ public CraftPlayerProfile clone() { -+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); -+ clone.setProperties(getProperties()); -+ return clone; -+ } -+ -+ @Override -+ public boolean isComplete() { -+ return profile.isComplete(); -+ } -+ -+ @Override -+ public boolean completeFromCache() { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); -+ } -+ -+ public boolean completeFromCache(boolean onlineMode) { -+ return completeFromCache(false, onlineMode); -+ } -+ -+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ String name = profile.getName(); -+ UserCache userCache = server.getUserCache(); -+ if (profile.getId() == null) { -+ final GameProfile profile; -+ if (onlineMode) { -+ profile = lookupUUID ? userCache.getProfile(name) : userCache.getProfileIfCached(name); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ if (profile != null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } -+ } -+ -+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { -+ GameProfile profile = userCache.getProfile(this.profile.getId()); -+ if (profile != null) { -+ if (this.profile.getName() == null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } else { -+ copyProfileProperties(profile, this.profile); -+ } -+ } -+ } -+ return this.profile.isComplete(); -+ } -+ -+ public boolean complete(boolean textures) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return complete(textures, PaperConfig.isProxyOnlineMode()); -+ } -+ public boolean complete(boolean textures, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); -+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { -+ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); -+ if (result != null) { -+ copyProfileProperties(result, this.profile, true); -+ } -+ if (this.profile.isComplete()) { -+ server.getUserCache().saveProfile(this.profile); -+ } -+ } -+ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target) { -+ copyProfileProperties(source, target, false); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { -+ PropertyMap sourceProperties = source.getProperties(); -+ PropertyMap targetProperties = target.getProperties(); -+ if (clearTarget) targetProperties.clear(); -+ if (sourceProperties.isEmpty()) { -+ return; -+ } -+ -+ for (Property property : sourceProperties.values()) { -+ targetProperties.removeAll(property.getName()); -+ targetProperties.put(property.getName(), property); -+ } -+ } -+ -+ private static ProfileProperty toBukkit(Property property) { -+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { -+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); -+ copyProfileProperties(gameProfile, profile.profile); -+ return profile; -+ } -+ -+ public static PlayerProfile asBukkitMirror(GameProfile profile) { -+ return new CraftPlayerProfile(profile); -+ } -+ -+ public static Property asAuthlib(ProfileProperty property) { -+ return new Property(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static GameProfile asAuthlibCopy(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return asAuthlib(craft.clone()); -+ } -+ -+ public static GameProfile asAuthlib(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return craft.getGameProfile(); -+ } -+ -+ private class PropertySet extends AbstractSet { -+ -+ @Override -+ @Nonnull -+ public Iterator iterator() { -+ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); -+ } -+ -+ @Override -+ public int size() { -+ return profile.getProperties().size(); -+ } -+ -+ @Override -+ public boolean add(ProfileProperty property) { -+ setProperty(property); -+ return true; -+ } -+ -+ @Override -+ public boolean addAll(Collection c) { -+ //noinspection unchecked -+ setProperties((Collection) c); -+ return true; -+ } -+ -+ @Override -+ public boolean contains(Object o) { -+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); -+ } -+ -+ private class ProfilePropertyIterator implements Iterator { -+ private final Iterator iterator; -+ -+ ProfilePropertyIterator(Iterator iterator) { -+ this.iterator = iterator; -+ } -+ -+ @Override -+ public boolean hasNext() { -+ return iterator.hasNext(); -+ } -+ -+ @Override -+ public ProfileProperty next() { -+ return toBukkit(iterator.next()); -+ } -+ -+ @Override -+ public void remove() { -+ iterator.remove(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d64d45eb01c65864fca1077982d89bc05e0f811b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.*; -+import com.mojang.authlib.minecraft.MinecraftSessionService; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; -+ -+import java.net.Proxy; -+ -+public class PaperAuthenticationService extends YggdrasilAuthenticationService { -+ private final Environment environment; -+ public PaperAuthenticationService(Proxy proxy) { -+ super(proxy); -+ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; -+ } -+ -+ @Override -+ public UserAuthentication createUserAuthentication(Agent agent) { -+ return new PaperUserAuthentication(this, agent); -+ } -+ -+ @Override -+ public MinecraftSessionService createMinecraftSessionService() { -+ return new PaperMinecraftSessionService(this, this.environment); -+ } -+ -+ @Override -+ public GameProfileRepository createProfileRepository() { -+ return new PaperGameProfileRepository(this, this.environment); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -new file mode 100644 -index 0000000000000000000000000000000000000000..582c169c85ac66f1f9430f79042e4655f776c157 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -0,0 +1,18 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.ProfileLookupCallback; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; -+ -+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { -+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -+ super.findProfilesByNames(names, agent, callback); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..93d73c27340645c7502acafdc0b2cfbc1a759dd8 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.minecraft.MinecraftProfileTexture; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; -+ -+import java.util.Map; -+ -+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { -+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public Map getTextures(GameProfile profile, boolean requireSecure) { -+ return super.getTextures(profile, requireSecure); -+ } -+ -+ @Override -+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -+ return super.fillProfileProperties(profile, requireSecure); -+ } -+ -+ @Override -+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { -+ return super.fillGameProfile(profile, requireSecure); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3cdd06d3af7ff94f1fe1a11b9a9275e17c695a38 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -@@ -0,0 +1,12 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; -+import java.util.UUID; -+ -+public class PaperUserAuthentication extends YggdrasilUserAuthentication { -+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { -+ super(authenticationService, UUID.randomUUID().toString(), agent); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 18b56b59fd6efd618e6ff6f9cf3a02f57588d244..cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -1,6 +1,8 @@ - package net.minecraft.server; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; -@@ -11,6 +13,7 @@ import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.mojang.authlib.GameProfile; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -345,6 +348,10 @@ public final class MCUtil { - return run.get(); - } - -+ public static PlayerProfile toBukkit(GameProfile profile) { -+ return CraftPlayerProfile.asBukkitMirror(profile); -+ } -+ - /** - * Calculates distance between 2 entities - * @param e1 -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 89db31061fcc3420bc8e668533a4051cdbd12253..191a74bd9b894f9d64d0a55747cb17e07ceef597 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,7 +132,7 @@ public class Main { - } - - File file = (File) optionset.valueOf("universe"); // CraftBukkit -- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); -+ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); - UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index b9f94f957dd5372c8b02d785204690e4ade36a98..692d95c94df85d752a3ddc66e1f2af765565b160 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -45,7 +45,7 @@ public class UserCache { - - private static final Logger LOGGER = LogManager.getLogger(); - private static boolean b; -- private final Map c = Maps.newConcurrentMap(); -+ private final Map c = Maps.newConcurrentMap();private final Map nameCache = c; // Paper - OBFHELPER // Paper - private final Map d = Maps.newConcurrentMap(); - private final GameProfileRepository e; - private final Gson f = (new GsonBuilder()).create(); -@@ -110,6 +110,7 @@ public class UserCache { - return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - -+ public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize - Calendar calendar = Calendar.getInstance(); - -@@ -159,6 +160,13 @@ public class UserCache { - return gameprofile; - } - -+ // Paper start -+ @Nullable public GameProfile getProfileIfCached(String name) { -+ UserCache.UserCacheEntry entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); -+ return entry == null ? null : entry.getProfile(); -+ } -+ // Paper end -+ - @Nullable - public GameProfile getProfile(UUID uuid) { - UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(uuid); -@@ -341,7 +349,7 @@ public class UserCache { - - static class UserCacheEntry { - -- private final GameProfile a; -+ private final GameProfile a;public GameProfile getProfile() { return a; } // Paper - OBFHELPER - private final Date b; - private volatile long c; - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 92c68becf45d83dbc18d3a9c1f86f8aa308e0d87..c8ea7b8ad46ce0fab794b897b5f3fe414a679387 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -227,6 +227,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - -+import javax.annotation.Nullable; // Paper -+import javax.annotation.Nonnull; // Paper -+ - public final class CraftServer implements Server { - private final String serverName = "Paper"; // Paper - private final String serverVersion; -@@ -2317,5 +2320,24 @@ public final class CraftServer implements Server { - public boolean suggestPlayerNamesWhenNullTabCompletions() { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { -+ return createProfile(uuid, null); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { -+ return createProfile(null, name); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); -+ if (player != null) { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); -+ } -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index dff67a48961399f3746f99b4f2363724bfe51c36..8298ae9bf1c5635f08552c15f004b3d0f6e9f19b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -80,6 +80,13 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } - - private void setProfile(GameProfile profile) { -+ // Paper start -+ if (profile != null) { -+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); -+ paperProfile.completeFromCache(false, true); -+ profile = paperProfile.getGameProfile(); -+ } -+ // Paper end - this.profile = profile; - this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile); - } diff --git a/Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch b/Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch deleted file mode 100644 index ac464d6b5a76..000000000000 --- a/Spigot-Server-Patches/0153-Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:18:30 -0400 -Subject: [PATCH] Shoulder Entities Release API - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index ba26fc2405e17d582da971d03147fb1865e9b546..63e8062ae3f3407b92b72b5fccaa958c39282fb8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1880,20 +1880,44 @@ public abstract class EntityHuman extends EntityLiving { - - } - -+ // Paper start -+ public Entity releaseLeftShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); -+ if (entity != null) { -+ this.setShoulderEntityLeft(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ -+ public Entity releaseRightShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); -+ if (entity != null) { -+ this.setShoulderEntityRight(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ // Paper - maintain old signature - private boolean spawnEntityFromShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean -- if (!this.world.isClientSide && !nbttagcompound.isEmpty()) { -+ return spawnEntityFromShoulder0(nbttagcompound) != null; -+ } -+ -+ // Paper - return entity -+ private Entity spawnEntityFromShoulder0(@Nullable NBTTagCompound nbttagcompound) { -+ if (!this.world.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { - return EntityTypes.a(nbttagcompound, this.world).map((entity) -> { // CraftBukkit - if (entity instanceof EntityTameableAnimal) { - ((EntityTameableAnimal) entity).setOwnerUUID(this.uniqueID); - } - - entity.setPosition(this.locX(), this.locY() + 0.699999988079071D, this.locZ()); -- return ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -- }).orElse(true); // CraftBukkit -+ boolean addedToWorld = ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -+ return addedToWorld ? entity : null; -+ }).orElse(null); // CraftBukkit // Paper - false -> null - } - -- return true; // CraftBukkit -+ return null; // Paper - return null - } -+ // Paper end - - @Override - public abstract boolean isSpectator(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 105d0388998d1e35e634d2163fe1a44aa7037ac8..8661f97ac885daca068057c1fcc4eed54c6d7f14 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -493,6 +493,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - getHandle().getCooldownTracker().setCooldown(CraftMagicNumbers.getItem(material), ticks); - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { -+ if (!getHandle().getShoulderEntityLeft().isEmpty()) { -+ Entity entity = getHandle().releaseLeftShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public org.bukkit.entity.Entity releaseRightShoulderEntity() { -+ if (!getHandle().getShoulderEntityRight().isEmpty()) { -+ Entity entity = getHandle().releaseRightShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Override - public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Spigot-Server-Patches/0154-Profile-Lookup-Events.patch b/Spigot-Server-Patches/0154-Profile-Lookup-Events.patch deleted file mode 100644 index a9a4210f19bb..000000000000 --- a/Spigot-Server-Patches/0154-Profile-Lookup-Events.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 17:00:32 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -index 582c169c85ac66f1f9430f79042e4655f776c157..08fdb681a68e8be6e4062af0630957ce3e524806 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -1,11 +1,16 @@ - package com.destroystokyo.paper.profile; - -+import com.destroystokyo.paper.event.profile.LookupProfileEvent; -+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; -+import com.google.common.collect.Sets; - import com.mojang.authlib.Agent; - import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; - import com.mojang.authlib.ProfileLookupCallback; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; - -+import java.util.Set; - public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { - super(authenticationService, environment); -@@ -13,6 +18,50 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - - @Override - public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -- super.findProfilesByNames(names, agent, callback); -+ Set unfoundNames = Sets.newHashSet(); -+ for (String name : names) { -+ PreLookupProfileEvent event = new PreLookupProfileEvent(name); -+ event.callEvent(); -+ if (event.getUUID() != null) { -+ // Plugin provided UUI, we can skip network call. -+ GameProfile gameprofile = new GameProfile(event.getUUID(), name); -+ // We might even have properties! -+ Set profileProperties = event.getProfileProperties(); -+ if (!profileProperties.isEmpty()) { -+ for (ProfileProperty property : profileProperties) { -+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); -+ } -+ } -+ callback.onProfileLookupSucceeded(gameprofile); -+ } else { -+ unfoundNames.add(name); -+ } -+ } -+ -+ // Some things were not found.... Proceed to look up. -+ if (!unfoundNames.isEmpty()) { -+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); -+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); -+ } -+ } -+ -+ private static class PreProfileLookupCallback implements ProfileLookupCallback { -+ private final ProfileLookupCallback callback; -+ -+ PreProfileLookupCallback(ProfileLookupCallback callback) { -+ this.callback = callback; -+ } -+ -+ @Override -+ public void onProfileLookupSucceeded(GameProfile gameProfile) { -+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); -+ new LookupProfileEvent(from).callEvent(); -+ callback.onProfileLookupSucceeded(gameProfile); -+ } -+ -+ @Override -+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { -+ callback.onProfileLookupFailed(gameProfile, e); -+ } - } - } diff --git a/Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch b/Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch deleted file mode 100644 index 3b4a49574b27..000000000000 --- a/Spigot-Server-Patches/0155-Block-player-logins-during-server-shutdown.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sun, 2 Jul 2017 21:35:56 -0500 -Subject: [PATCH] Block player logins during server shutdown - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 9f87503c58f64bbfa829faa58600d7d9e64aecf1..651b84b3bba316407a217c941be4c20074c5bb90 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -68,6 +68,12 @@ public class LoginListener implements PacketLoginInListener { - } - - public void tick() { -+ // Paper start - Do not allow logins while the server is shutting down -+ if (!MinecraftServer.getServer().isRunning()) { -+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); -+ return; -+ } -+ // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { - this.c(); - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { diff --git a/Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch b/Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch deleted file mode 100644 index 3a00081a94e0..000000000000 --- a/Spigot-Server-Patches/0156-Entity-fromMobSpawner.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b798190628c1d83b5bf9e5497b515ef1e9f26707..6b6de18e368d48b61482a7210794b756d805a460 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -268,6 +268,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1665,6 +1666,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (this.origin != null) { - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ // Save entity's from mob spawner status -+ if (spawnedViaMobSpawner) { -+ nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -1793,6 +1798,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (!originTag.isEmpty()) { - origin = new org.bukkit.Location(world.getWorld(), originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); - } -+ -+ spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 76c98d576d3e567ec4482b30219f5a9107cb9703..43fcc001bb9815b352cb74af10290b2a4ccaa540 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -160,6 +160,7 @@ public abstract class MobSpawnerAbstract { - } - // Spigot End - } -+ entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index a58626b1a0160983a738a45c8a1d411eb347e6a2..4c2a35fb33da19a15a220dc5e0c9fa3233d657fb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1100,5 +1100,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - Location origin = getHandle().origin; - return origin == null ? null : origin.clone(); - } -+ -+ @Override -+ public boolean fromMobSpawner() { -+ return getHandle().spawnedViaMobSpawner; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch b/Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 5587fd6b920d..000000000000 --- a/Spigot-Server-Patches/0157-Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:24:06 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 00b97d9ee7a3dd622c87e8efa288795d34db8fc7..62ccef35e4b4238c50faf778fbf3ea9a494ca387 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -6,6 +6,7 @@ import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; - import org.apache.commons.lang.Validate; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; -+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; - import org.bukkit.entity.AbstractHorse; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.Horse; -@@ -99,6 +100,6 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - - @Override - public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventoryChest); -+ return new CraftSaddledInventory(getHandle().inventoryChest); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -index c3599b29c0b32d6fcf18a4a0adfbe8454c37834d..0389d15f8e0b6bb68316eaed0cf91acab8951cc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -@@ -4,7 +4,7 @@ import net.minecraft.world.IInventory; - import org.bukkit.inventory.HorseInventory; - import org.bukkit.inventory.ItemStack; - --public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { -+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { - - public CraftInventoryHorse(IInventory inventory) { - super(inventory); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8c2674ca1be1346ea84bcd7c9c5d6ea540802a5f ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -@@ -0,0 +1,12 @@ -+package org.bukkit.craftbukkit.inventory; -+ -+import net.minecraft.world.IInventory; -+import org.bukkit.inventory.SaddledHorseInventory; -+ -+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { -+ -+ public CraftSaddledInventory(IInventory inventory) { -+ super(inventory); -+ } -+ -+} diff --git a/Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch b/Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch deleted file mode 100644 index f7c4a06144c9..000000000000 --- a/Spigot-Server-Patches/0158-Implement-ensureServerConversions-API.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 22:43:12 -0400 -Subject: [PATCH] Implement ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index ccd27aa93b4ab1dc09a8d684b43b5ecb69100ed8..8206e85cefb0b02b1ac9b370808c06019211cdb1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -346,5 +346,11 @@ public final class CraftItemFactory implements ItemFactory { - public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); - } -+ -+ // Paper start -+ @Override -+ public ItemStack ensureServerConversions(ItemStack item) { -+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch b/Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch deleted file mode 100644 index 17848eb0019e..000000000000 --- a/Spigot-Server-Patches/0159-Implement-getI18NDisplayName.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:59:38 -0400 -Subject: [PATCH] Implement getI18NDisplayName - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/net/minecraft/locale/LocaleLanguage.java b/src/main/java/net/minecraft/locale/LocaleLanguage.java -index 9b8d5e7e4c86a699e26b1b4d0b82e88887a44054..5218214225b50ac4059ab704086a457318e93e00 100644 ---- a/src/main/java/net/minecraft/locale/LocaleLanguage.java -+++ b/src/main/java/net/minecraft/locale/LocaleLanguage.java -@@ -30,7 +30,7 @@ public abstract class LocaleLanguage { - - private static LocaleLanguage c() { - Builder builder = ImmutableMap.builder(); -- BiConsumer biconsumer = builder::put; -+ BiConsumer biconsumer = builder::put; // Paper - decompile fix - - try { - InputStream inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); -@@ -87,10 +87,12 @@ public abstract class LocaleLanguage { - - } - -+ public static LocaleLanguage getInstance() { return a(); } // Paper - OBFHELPER - public static LocaleLanguage a() { - return LocaleLanguage.d; - } - -+ public String translateKey(String key) { return a(key); } // Paper - OBFHELPER - public abstract String a(String s); - - public abstract boolean b(String s); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 8206e85cefb0b02b1ac9b370808c06019211cdb1..910c6109783dfef86e127a0a5b7d7d3865150d89 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -352,5 +352,18 @@ public final class CraftItemFactory implements ItemFactory { - public ItemStack ensureServerConversions(ItemStack item) { - return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); - } -+ -+ @Override -+ public String getI18NDisplayName(ItemStack item) { -+ net.minecraft.world.item.ItemStack nms = null; -+ if (item instanceof CraftItemStack) { -+ nms = ((CraftItemStack) item).handle; -+ } -+ if (nms == null) { -+ nms = CraftItemStack.asNMSCopy(item); -+ } -+ -+ return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch b/Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index 4b6d02529cb7..000000000000 --- a/Spigot-Server-Patches/0160-ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:10 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9db65b9d8f66ff83dcf32274fec98a425e7353d8..738a69a1a5765897fb3ca3b4ceb07cddade0d27f 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -615,9 +615,9 @@ public abstract class PlayerList { - - // return chatmessage; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure -- } else if (!this.isWhitelisted(gameprofile)) { -- chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure -+ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper -+ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper -+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -1009,9 +1009,25 @@ public abstract class PlayerList { - this.server.getCommandDispatcher().a(entityplayer); - } - -+ // Paper start - public boolean isWhitelisted(GameProfile gameprofile) { -- return !this.hasWhitelist || this.operators.d(gameprofile) || this.whitelist.d(gameprofile); -+ return isWhitelisted(gameprofile, null); - } -+ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { -+ boolean isOp = this.operators.d(gameprofile); -+ boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event.callEvent(); -+ if (!event.isWhitelisted()) { -+ if (loginEvent != null) { -+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); -+ } -+ return false; -+ } -+ return true; -+ } -+ // Paper end - - public boolean isOp(GameProfile gameprofile) { - return this.operators.d(gameprofile) || this.server.a(gameprofile) && this.server.getSaveData().o() || this.v; diff --git a/Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch b/Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch deleted file mode 100644 index ee16865333cf..000000000000 --- a/Spigot-Server-Patches/0161-Fix-this-stupid-bullshit.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DemonWav -Date: Sun, 6 Aug 2017 17:17:53 -0500 -Subject: [PATCH] Fix this stupid bullshit - -Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. - -modified in order to prevent merge conflicts when Spigot changes/disables the warning, -and to provide some level of hint without being disruptive. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bed1208223e4213dec2c246675c11f2a1965a4ee..463c41454d96e823d1ffd62619fc3b83af3bf168 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -224,10 +224,12 @@ public class Main { - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { -- System.err.println("*** Error, this build is outdated ***"); -+ // Paper start - This is some stupid bullshit -+ System.err.println("*** Warning, you've not updated in a while! ***"); - System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper -- System.err.println("*** Server will start in 20 seconds ***"); -- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ //System.err.println("*** Server will start in 20 seconds ***"); -+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ // Paper End - } - } - diff --git a/Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch b/Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch deleted file mode 100644 index e46048261033..000000000000 --- a/Spigot-Server-Patches/0162-Ocelot-despawns-should-honor-nametags-and-leash.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:54:40 -0500 -Subject: [PATCH] Ocelot despawns should honor nametags and leash - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -index b0296cef410aa5af42dcf89217dd8853f3800663..f3e9c73f28584bcccd6f82d8974eabe4b4a892fa 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -@@ -128,7 +128,7 @@ public class EntityOcelot extends EntityAnimal { - - @Override - public boolean isTypeNotPersistent(double d0) { -- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit -+ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash - } - - public static AttributeProvider.Builder eK() { diff --git a/Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch deleted file mode 100644 index 442ca8573709..000000000000 --- a/Spigot-Server-Patches/0163-Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:45:19 -0500 -Subject: [PATCH] Reset spawner timer when spawner event is cancelled - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 43fcc001bb9815b352cb74af10290b2a4ccaa540..883c724fbb86a84ee903b5e7127f14726fe4cf24 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -161,6 +161,7 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -184,7 +185,7 @@ public abstract class MobSpawnerAbstract { - ((EntityInsentient) entity).doSpawnEffect(); - } - -- flag = true; -+ /*flag = true;*/ // Paper - moved up above cancellable event - } - } - } diff --git a/Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch deleted file mode 100644 index 3dbcb05b9883..000000000000 --- a/Spigot-Server-Patches/0164-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mezz -Date: Wed, 9 Aug 2017 17:51:22 -0500 -Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index bd08ff18d8d7dbe63ed33c1efb6099b58aa02caa..8d4a28f98bd9c8a2dd1262f0f640909a456897fa 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -726,7 +726,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.enter("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { -- this.tileEntityListTick.removeAll(this.tileEntityListUnload); -+ // Paper start - Use alternate implementation with faster contains -+ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); -+ toRemove.addAll(tileEntityListUnload); -+ this.tileEntityListTick.removeAll(toRemove); -+ // Paper end - //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } diff --git a/Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch b/Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch deleted file mode 100644 index 1ac2a8b39263..000000000000 --- a/Spigot-Server-Patches/0165-Allow-specifying-a-custom-authentication-servers-dow.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Thu, 17 Aug 2017 16:08:20 -0700 -Subject: [PATCH] Allow specifying a custom "authentication servers down" kick - message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 48319aaf1c525c6fb7bdee5c2f570a0d056d4eae..52954fc3bf932cfc9d5ce63e3d3cace351305790 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.google.common.base.Strings; - import com.google.common.base.Throwables; - - import java.io.File; -@@ -273,4 +274,9 @@ public class PaperConfig { - private static void suggestPlayersWhenNull() { - suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); - } -+ -+ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message -+ private static void authenticationServersDownKickMessage() { -+ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 401833b7aeb9955fad2a3f1fe51d195cf0131094..9e175747e110e32be80498ed27a71d21e8c01c5e 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -277,6 +277,10 @@ public class LoginListener implements PacketLoginInListener { - LoginListener.this.i = LoginListener.this.a(gameprofile); - LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; - } else { -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { -+ LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); -+ } else // Paper end - LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down")); - LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); - } diff --git a/Spigot-Server-Patches/0166-LivingEntity-setKiller.patch b/Spigot-Server-Patches/0166-LivingEntity-setKiller.patch deleted file mode 100644 index 2777a89649c3..000000000000 --- a/Spigot-Server-Patches/0166-LivingEntity-setKiller.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:49:48 -0500 -Subject: [PATCH] LivingEntity#setKiller - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 3d6b8fd09c07e78c0d786dff9658eb0089f853cf..851aed157a233ab690a57e5736fa01beaff45b5c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -180,7 +180,7 @@ public abstract class EntityLiving extends Entity { - public float aE; - @Nullable - public EntityHuman killer; -- protected int lastDamageByPlayerTime; -+ public int lastDamageByPlayerTime; // Paper - protected -> public - protected boolean killed; - protected int ticksFarFromPlayer; - protected float aJ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c654026587bc9bf77b39f59a0c89991ac581da1e..c43c300963bae9bca6ab9c9389dd53e42318715c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -8,6 +8,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.effect.MobEffect; -@@ -344,6 +345,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().killer == null ? null : (Player) getHandle().killer.getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public void setKiller(Player killer) { -+ EntityPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); -+ getHandle().killer = entityPlayer; -+ getHandle().lastDamager = entityPlayer; -+ getHandle().lastDamageByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity -+ } -+ // Paper end -+ - @Override - public boolean addPotionEffect(PotionEffect effect) { - return addPotionEffect(effect, false); diff --git a/Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch b/Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch deleted file mode 100644 index 66d9ef47f0c5..000000000000 --- a/Spigot-Server-Patches/0167-Handle-plugin-prefixes-using-Log4J-configuration.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:55 +0200 -Subject: [PATCH] Handle plugin prefixes using Log4J configuration - -Display logger name in the console for all loggers except the -root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. -Since plugins now use the plugin name as logger name this will -restore the plugin prefixes without having to prepend them manually -to the log messages. - -Logger prefixes are shown by default for all loggers except for -the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. -This may cause additional prefixes to be disabled for plugins bypassing -the plugin logger. - -diff --git a/pom.xml b/pom.xml -index e0fcbe1b13a5ec1244d6d904ca76336a47967c9b..70a7778ae19941bb78b8669b1429cb3d525f58a4 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -76,7 +76,7 @@ - - org.apache.logging.log4j - log4j-core -- runtime -+ compile - - - org.apache.logging.log4j -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 3c93a497a790b8d800852db2ac48feca41f45cef..e8e5e5b568ba53dd006f1461cb4f027ceeae5528 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -290,7 +290,7 @@ public class SpigotConfig - private static void playerSample() - { - playerSample = getInt( "settings.sample-count", 12 ); -- System.out.println( "Server Ping Player Sample Count: " + playerSample ); -+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - - public static int playerShuffle; -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 620b9490e5f159080e50289d127404a1b56adbef..a8bdaaeaa1a9316848416f0533739b9b083ca151 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -5,10 +5,22 @@ - - - -- -+ -+ -+ -+ -+ -+ - - -- -+ -+ -+ -+ -+ -+ - - - diff --git a/Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch b/Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch deleted file mode 100644 index 5afb9562c0e1..000000000000 --- a/Spigot-Server-Patches/0168-Improve-Log4J-Configuration-Plugin-Loggers.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Sat, 23 Sep 2017 21:07:20 +0200 -Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers - -Add full exceptions to log4j to not truncate stack traces - -Disable logger prefix for various plugins bypassing the plugin logger - -Some plugins bypass the plugin logger and add the plugin prefix -manually to the log message. Since they use other logger names -(e.g. qualified class names) these would now also appear in the -log. Disable the logger prefix for these plugins so the messages -show up correctly. - -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index a8bdaaeaa1a9316848416f0533739b9b083ca151..476f4a5cbe664ddd05474cb88553018bd334a5b8 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,19 +6,21 @@ - - - -- -+ - -- -+ -+ - - - - - -- -+ - -- -+ -+ - - - diff --git a/Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch b/Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch deleted file mode 100644 index 61478af20680..000000000000 --- a/Spigot-Server-Patches/0169-Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 28 Sep 2017 17:21:44 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index bf3195eaf1fc7bdddafbb54d0ccf825e95b63210..7af07ca8e1fa20361c95841b48dd70cdf46a18b5 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1168,7 +1168,34 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean flag = d8 > 0.0D; - - if (this.player.isOnGround() && !packetplayinflying.b() && flag) { -- this.player.jump(); -+ // Paper start - Add player jump event -+ Player player = this.getPlayer(); -+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. -+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. -+ -+ // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packetplayinflying.hasPos) { -+ to.setX(packetplayinflying.x); -+ to.setY(packetplayinflying.y); -+ to.setZ(packetplayinflying.z); -+ } -+ -+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packetplayinflying.hasLook) { -+ to.setYaw(packetplayinflying.yaw); -+ to.setPitch(packetplayinflying.pitch); -+ } -+ -+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); -+ -+ if (event.callEvent()) { -+ this.player.jump(); -+ } else { -+ from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); -+ return; -+ } -+ // Paper end - } - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); diff --git a/Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch b/Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch deleted file mode 100644 index 1d3d75d1c52d..000000000000 --- a/Spigot-Server-Patches/0170-handle-PacketPlayInKeepAlive-async.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 5 Oct 2017 01:54:07 +0100 -Subject: [PATCH] handle PacketPlayInKeepAlive async - -In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main -thread, while entirely correct for the server, this causes issues with -plugins which are expecting the PlayerQuitEvent on the main thread. - -In order to counteract some bad behavior, we will post handling of the -disconnection to the main thread, but leave the actual processing of the packet -off the main thread. - -also adding some additional logging in order to help work out what is causing -random disconnections for clients. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 7af07ca8e1fa20361c95841b48dd70cdf46a18b5..685415240d7be66fe968198b33c1865a906e18c9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2778,14 +2778,18 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInKeepAlive packetplayinkeepalive) { -- PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit -+ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread - if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { - int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); - - this.player.ping = (this.player.ping * 3 + i) / 4; - this.awaitingKeepAlive = false; - } else if (!this.isExemptPlayer()) { -+ // Paper start - This needs to be handled on the main thread for plugins -+ minecraftServer.scheduleOnMain(() -> { - this.disconnect(new ChatMessage("disconnect.timeout")); -+ }); -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch b/Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index f04306c601fc..000000000000 --- a/Spigot-Server-Patches/0171-Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:45:20 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8a716c1647aa29906be26ac262e93ebd2c1adfaa ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -@@ -0,0 +1,50 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public class PaperNetworkClient implements NetworkClient { -+ -+ private final NetworkManager networkManager; -+ -+ PaperNetworkClient(NetworkManager networkManager) { -+ this.networkManager = networkManager; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return (InetSocketAddress) this.networkManager.getSocketAddress(); -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.networkManager.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.networkManager.virtualHost; -+ } -+ -+ public static InetSocketAddress prepareVirtualHost(String host, int port) { -+ int len = host.length(); -+ -+ // FML appends a marker to the host to recognize FML clients (\0FML\0) -+ int pos = host.indexOf('\0'); -+ if (pos >= 0) { -+ len = pos; -+ } -+ -+ // When clients connect with a SRV record, their host contains a trailing '.' -+ if (len > 0 && host.charAt(len - 1) == '.') { -+ len--; -+ } -+ -+ return InetSocketAddress.createUnresolved(host.substring(0, len), port); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index f093b465b868e6003bb2b5ee634a624b5b054493..60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -70,6 +70,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - private float s; - private int t; - private boolean u; -+ // Paper start - NetworkClient implementation -+ public int protocolVersion; -+ public java.net.InetSocketAddress virtualHost; -+ // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { - this.h = enumprotocoldirection; -diff --git a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -index b290ddfbc19aed3e44169281c3dae5429dac0062..14c002376540d2039fc2fe2ef746e53471a9cb08 100644 ---- a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -+++ b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -@@ -39,6 +39,7 @@ public class PacketHandshakingInSetProtocol implements Packet -Date: Sun, 15 Oct 2017 00:29:07 +0100 -Subject: [PATCH] revert serverside behavior of keepalives - -This patch intends to bump up the time that a client has to reply to the -server back to 30 seconds as per pre 1.12.2, which allowed clients -more than enough time to reply potentially allowing them to be less -tempermental due to lag spikes on the network thread, e.g. that caused -by plugins that are interacting with netty. - -We also add a system property to allow people to tweak how long the server -will wait for a reply. There is a compromise here between lower and higher -values, lower values will mean that dead connections can be closed sooner, -whereas higher values will make this less sensitive to issues such as spikes -from networking or during connections flood of chunk packets on slower clients, - at the cost of dead connections being kept open for longer. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 685415240d7be66fe968198b33c1865a906e18c9..3628965d2a18a367c2357b54b65786fb90c38205 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -223,7 +223,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER - private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER - private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields -@@ -254,6 +254,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; -@@ -340,18 +341,25 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); -- long i = SystemUtils.getMonotonicMillis(); -- -- if (i - this.lastKeepAlive >= 25000L) { // CraftBukkit -- if (this.awaitingKeepAlive) { -- this.disconnect(new ChatMessage("disconnect.timeout")); -- } else { -- this.awaitingKeepAlive = true; -- this.lastKeepAlive = i; -- this.h = i; -- this.sendPacket(new PacketPlayOutKeepAlive(this.h)); -+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 -+ long currentTime = SystemUtils.getMonotonicMillis(); -+ long elapsedTime = currentTime - this.getLastPing(); -+ -+ if (this.isPendingPing()) { -+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected -+ PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -+ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); -+ } -+ } else { -+ if (elapsedTime >= 15000L) { // 15 seconds -+ this.setPendingPing(true); -+ this.setLastPing(currentTime); -+ this.setKeepAliveID(currentTime); -+ this.sendPacket(new PacketPlayOutKeepAlive(this.getKeepAliveID())); - } - } -+ // Paper end - - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start diff --git a/Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch deleted file mode 100644 index 5c3d2d05c349..000000000000 --- a/Spigot-Server-Patches/0173-Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 31 Oct 2017 03:26:18 +0100 -Subject: [PATCH] Send attack SoundEffects only to players who can see the - attacker - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 63e8062ae3f3407b92b72b5fccaa958c39282fb8..f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -28,6 +28,7 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; -+import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -@@ -1126,7 +1127,7 @@ public abstract class EntityHuman extends EntityLiving { - int i = b0 + EnchantmentManager.b((EntityLiving) this); - - if (this.isSprinting() && flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - ++i; - flag1 = true; - } -@@ -1201,7 +1202,7 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.ex(); - } - -@@ -1229,15 +1230,15 @@ public abstract class EntityHuman extends EntityLiving { - } - - if (flag2) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.a(entity); - } - - if (!flag2 && !flag3) { - if (flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } - } - -@@ -1289,7 +1290,7 @@ public abstract class EntityHuman extends EntityLiving { - - this.applyExhaustion(world.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - if (flag4) { - entity.extinguish(); - } -@@ -1724,6 +1725,14 @@ public abstract class EntityHuman extends EntityLiving { - public int getExpToLevel() { - return this.expLevel >= 30 ? 112 + (this.expLevel - 30) * 9 : (this.expLevel >= 15 ? 37 + (this.expLevel - 15) * 5 : 7 + this.expLevel * 2); - } -+ // Paper start - send SoundEffect to everyone who can see fromEntity -+ private static void sendSoundEffect(EntityHuman fromEntity, double x, double y, double z, SoundEffect soundEffect, SoundCategory soundCategory, float volume, float pitch) { -+ fromEntity.world.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself -+ if (fromEntity instanceof EntityPlayer) { -+ ((EntityPlayer) fromEntity).playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundEffect, soundCategory, x, y, z, volume, pitch)); -+ } -+ } -+ // Paper end - - // CraftBukkit start - public void applyExhaustion(float f) { diff --git a/Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch b/Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch deleted file mode 100644 index a3621a8f2590..000000000000 --- a/Spigot-Server-Patches/0174-Option-for-maximum-exp-value-when-merging-orbs.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 10 Nov 2017 23:03:12 -0500 -Subject: [PATCH] Option for maximum exp value when merging orbs - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 90ca51dfdbb3045dd528450225cba96f5834166e..6c692e58cde22003ecbf6dc5695799147c39905a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -342,4 +342,10 @@ public class PaperWorldConfig { - disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } -+ -+ public int expMergeMaxValue; -+ private void expMergeMaxValue() { -+ expMergeMaxValue = getInt("experience-merge-max-value", -1); -+ log("Experience Merge Max Value: " + expMergeMaxValue); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 2ca0d109b148321964ac68259df82e4b1d7c57b2..d7a0a978411d56c93bec0d510060216eb592fed8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -596,16 +596,32 @@ public class CraftEventFactory { - EntityExperienceOrb xp = (EntityExperienceOrb) entity; - double radius = world.spigotConfig.expMerge; - if (radius > 0) { -+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics -+ final int maxValue = world.paperConfig.expMergeMaxValue; -+ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; -+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary -+ - List entities = world.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); - for (Entity e : entities) { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; -- if (!loopItem.dead) { -- xp.value += loopItem.value; -- loopItem.die(); -+ // Paper start -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ long newTotal = (long)xp.value + (long)loopItem.value; -+ if ((int) newTotal < 0) continue; // Overflow -+ if (maxValue > 0 && newTotal > (long)maxValue) { -+ loopItem.value = (int) (newTotal - maxValue); -+ xp.value = maxValue; -+ } else { -+ xp.value += loopItem.value; -+ loopItem.die(); -+ } -+ // Paper end - } - } - } -+ -+ } // Paper end - End iteration skip check - All tweaking ends here - } - // Spigot end - } else if (!(entity instanceof EntityPlayer)) { diff --git a/Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch b/Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index 5adb2dda30dc..000000000000 --- a/Spigot-Server-Patches/0175-Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:46:34 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index ff26ddce40d7ba74396360603a97bfab835b6202..8a43a85a728c15dbc0fdd2fc8dc5dfff9a589358 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity; - -+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper - import com.google.common.base.Objects; - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -2646,6 +2647,13 @@ public abstract class EntityLiving extends Entity { - ItemStack itemstack1 = this.getEquipment(enumitemslot); - - if (!ItemStack.matches(itemstack1, itemstack)) { -+ // Paper start - PlayerArmorChangeEvent -+ if (this instanceof EntityPlayer && enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { -+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); -+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); -+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); -+ } -+ // Paper end - if (map == null) { - map = Maps.newEnumMap(EnumItemSlot.class); - } -diff --git a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -index 8e7673c6072c3f8ddcebd7a719304ea41d809a36..59ad7d8dc1c8ee00d142dc6063c3416ccdce4ff8 100644 ---- a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -+++ b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -@@ -16,6 +16,7 @@ public enum EnumItemSlot { - this.j = s; - } - -+ public EnumItemSlot.Function getType() { return this.a(); } // Paper - OBFHELPER - public EnumItemSlot.Function a() { - return this.g; - } diff --git a/Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch b/Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch deleted file mode 100644 index ad5a02fae5e9..000000000000 --- a/Spigot-Server-Patches/0176-Prevent-logins-from-being-processed-when-the-player-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: killme -Date: Sun, 12 Nov 2017 19:40:01 +0100 -Subject: [PATCH] Prevent logins from being processed when the player has - disconnected - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 9e175747e110e32be80498ed27a71d21e8c01c5e..f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -75,7 +75,11 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { -- this.c(); -+ // Paper start - prevent logins to be processed even though disconnect was called -+ if (networkManager.isConnected()) { -+ this.c(); -+ } -+ // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { - EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); - diff --git a/Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch b/Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch deleted file mode 100644 index 4dc684be75a2..000000000000 --- a/Spigot-Server-Patches/0177-use-CB-BlockState-implementations-for-captured-block.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 16 Nov 2017 12:12:41 +0000 -Subject: [PATCH] use CB BlockState implementations for captured blocks - -When modifying the world, CB will store a copy of the affected -blocks in order to restore their state in the case that the event -is cancelled. This change only modifies the collection of blocks -in the world by normal means, e.g. not during tree population, -as the potentially marginal overheads would serve no advantage. - -CB was using a CraftBlockState for all blocks, which causes issues -should any block that uses information beyond a data ID would suffer -from missing information, e.g. Skulls. - -By using CBs CraftBlock#getState(), we will maintain a proper copy of -the blockstate that will be valid for restoration, as opposed to dropping -information on restoration when the event is cancelled. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8d4a28f98bd9c8a2dd1262f0f640909a456897fa..a9e7da1c848a6fe08fc112e445ceec1b7715d682 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -124,7 +124,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; -- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); -+ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper - public Map capturedTileEntities = new HashMap<>(); - public List captureDrops; - public long ticksPerAnimalSpawns; -@@ -346,7 +346,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -- CapturedBlockState blockstate = capturedBlockStates.get(blockposition); -+ CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); -@@ -366,7 +366,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - capture blockstates - boolean captured = false; - if (this.captureBlockStates && !this.capturedBlockStates.containsKey(blockposition)) { -- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, blockposition, i); -+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot -+ blockstate.setFlag(i); // Paper - set flag - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); - captured = true; - } -@@ -624,7 +625,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation - if (captureTreeGeneration) { -- CapturedBlockState previous = capturedBlockStates.get(blockposition); -+ CraftBlockState previous = capturedBlockStates.get(blockposition); // Paper - if (previous != null) { - return previous.getHandle(); - } diff --git a/Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch b/Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index 5fe5db1a8185..000000000000 --- a/Spigot-Server-Patches/0178-API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:08:22 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -also Avoid NPE during CraftBlockEntityState load if could not get TE - -If Tile Entity was null, correct Sign to return empty lines instead of null - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 9b44ca96669ce423e5649f11743226dfdd9ce746..48daa039ffa8ccb7b6f3ca47bdc56394addf9254 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -47,6 +47,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public TileEntity(TileEntityTypes tileentitytypes) { - this.position = BlockPosition.ZERO; - this.tileType = tileentitytypes; -+ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init - } - - // Paper start -@@ -95,7 +96,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - this.position = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - // CraftBukkit start - read container -- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); -+ this.persistentDataContainer.clear(); // Paper - clear instead of reinit - - net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues"); - if (persistentDataTag instanceof NBTTagCompound) { -@@ -245,7 +246,12 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - } - - // CraftBukkit start - add method -+ // Paper start - public InventoryHolder getOwner() { -+ return getOwner(true); -+ } -+ public InventoryHolder getOwner(boolean useSnapshot) { -+ // Paper end - if (world == null) return null; - // Spigot start - org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -@@ -254,7 +260,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return null; - } - // Spigot end -- org.bukkit.block.BlockState state = block.getState(); -+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper - if (state instanceof InventoryHolder) return (InventoryHolder) state; - return null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 255aac0803b436434bc00822f3698c4f3ba7e0ac..8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -316,6 +316,20 @@ public class CraftBlock implements Block { - - @Override - public BlockState getState() { -+ // Paper start - allow disabling the use of snapshots -+ return getState(true); -+ } -+ public BlockState getState(boolean useSnapshot) { -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; -+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ try { -+ return getState0(); -+ } finally { -+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ } -+ } -+ public BlockState getState0() { -+ // Paper end - Material material = getType(); - - switch (material) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a..2f0b48869077c27d0cacea81a99c9e34ff59c684 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -26,20 +26,40 @@ public class CraftBlockEntityState extends CraftBlockState - this.tileEntity = tileEntityClass.cast(world.getHandle().getTileEntity(this.getPosition())); - Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); - -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - -+ public final boolean snapshotDisabled; // Paper -+ public static boolean DISABLE_SNAPSHOT = false; // Paper -+ - public CraftBlockEntityState(Material material, T tileEntity) { - super(material); - - this.tileEntityClass = (Class) tileEntity.getClass(); - this.tileEntity = tileEntity; -- -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - - private T createSnapshot(T tileEntity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -index f342feee4e2274cdc51fef6caace52cc31eefb18..a4c888236bf09a25f234831a041ca5a4a2c972ef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -@@ -155,4 +155,10 @@ public final class CraftPersistentDataContainer implements PersistentDataContain - public Map serialize() { - return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); - } -+ -+ // Paper start -+ public void clear() { -+ this.customDataTags.clear(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch b/Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch deleted file mode 100644 index a9845876aea2..000000000000 --- a/Spigot-Server-Patches/0179-AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:19:58 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -Also adds isCommand and getLocation to the sync TabCompleteEvent - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 3628965d2a18a367c2357b54b65786fb90c38205..fc624315b156f450c1cbc87a81e9eeff5d31b4c2 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -713,10 +713,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInTabComplete packetplayintabcomplete) { -- PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); -+ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -- this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } - // CraftBukkit end -@@ -726,12 +726,35 @@ public class PlayerConnection implements PacketListenerPlayIn { - stringreader.skip(); - } - -- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ // Paper start - async tab completion -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ String buffer = packetplayintabcomplete.c(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server -+ if (!event.isHandled()) { -+ if (!event.isCancelled()) { - -- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -- }); -+ this.minecraftServer.scheduleOnMain(() -> { // Paper - This needs to be on main -+ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ -+ this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ }); -+ }); -+ } -+ } else if (!completions.isEmpty()) { -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ -+ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(builder::suggest); -+ player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ } -+ // Paper end - async tab completion - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c8ea7b8ad46ce0fab794b897b5f3fe414a679387..3c019719e6eaf789bd5e20f382b707973f8b39c6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1852,7 +1852,7 @@ public final class CraftServer implements Server { - offers = tabCompleteChat(player, message); - } - -- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); -+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPosition(pos)) : null); // Paper - getPluginManager().callEvent(tabEvent); - - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index a957695457cf3252848ce6ef37069692841b8e28..c5e00bd9e2790992202aadf8eec2002fc88c78f1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -28,6 +28,39 @@ public class ConsoleCommandCompleter implements Completer { - public void complete(LineReader reader, ParsedLine line, List candidates) { - final CraftServer server = this.server.server; - final String buffer = line.line(); -+ // Async Tab Complete -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ -+ if (event.isCancelled() || event.isHandled()) { -+ // Still fire sync event with the provided completions, if someone is listening -+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ List finalCompletions = completions; -+ Waitable> syncCompletions = new Waitable>() { -+ @Override -+ protected List evaluate() { -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); -+ } -+ }; -+ server.getServer().processQueue.add(syncCompletions); -+ try { -+ completions = syncCompletions.get(); -+ } catch (InterruptedException | ExecutionException e1) { -+ e1.printStackTrace(); -+ } -+ } -+ -+ if (!completions.isEmpty()) { -+ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ } -+ return; -+ } -+ - // Paper end - Waitable> waitable = new Waitable>() { - @Override diff --git a/Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch b/Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch deleted file mode 100644 index 22279d4515f3..000000000000 --- a/Spigot-Server-Patches/0180-Avoid-NPE-in-PathfinderGoalTempt.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 29 Nov 2017 22:18:54 -0500 -Subject: [PATCH] Avoid NPE in PathfinderGoalTempt - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -index 54b345b5d2fc8d3c511533281f6d387f046f8000..9a120ab9c5c6c858bf3d1690196fe657e76cc1b7 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -@@ -65,7 +65,7 @@ public class PathfinderGoalTempt extends PathfinderGoal { - } - this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); - } -- return tempt; -+ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled - // CraftBukkit end - } - } diff --git a/Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch b/Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch deleted file mode 100644 index 994fed3ea2bf..000000000000 --- a/Spigot-Server-Patches/0181-PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:02:53 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index f4da22b33c704e675510b4b1a3aa7c180088be29..e3dfb018b06c0139594ddbb88fab2ca8d43ab12f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -5,6 +5,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityExperienceOrb; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -232,7 +233,7 @@ public class EntityExperienceOrb extends Entity { - @Override - public void pickup(EntityHuman entityhuman) { - if (!this.world.isClientSide) { -- if (this.d == 0 && entityhuman.bu == 0) { -+ if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - entityhuman.bu = 2; - entityhuman.receive(this, 1); - Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); diff --git a/Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch b/Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch deleted file mode 100644 index 591aa85fc9d7..000000000000 --- a/Spigot-Server-Patches/0182-ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:57:26 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d7a0a978411d56c93bec0d510060216eb592fed8..e068896b1b8aab8bba8acd641bf0479c89ad3321 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -606,7 +606,7 @@ public class CraftEventFactory { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; - // Paper start -- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - long newTotal = (long)xp.value + (long)loopItem.value; - if ((int) newTotal < 0) continue; // Overflow - if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch b/Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index d494effb54e8..000000000000 --- a/Spigot-Server-Patches/0183-Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:36:49 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index e3dfb018b06c0139594ddbb88fab2ca8d43ab12f..3387a19044b3ee2a1ef549c328c8bc354a5b6d23 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -265,10 +265,12 @@ public class EntityExperienceOrb extends Entity { - } - } - -+ public final int durToXp(int i) { return b(i); } // Paper OBFHELPER - private int b(int i) { - return i / 2; - } - -+ public final int xpToDur(int i) { return c(i); } // Paper OBFHELPER - private int c(int i) { - return i * 2; - } -diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -index d313b02f41e4f4a90676cbb37afce4e92dd4d664..72afbf8f537770540e90a2880ea81de137ea10f5 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -@@ -269,8 +269,8 @@ public class EnchantmentManager { - return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0; - } - -- @Nullable -- public static Entry b(Enchantment enchantment, EntityLiving entityliving) { -+ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) { Entry entry = b(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER -+ @Nullable public static Entry b(Enchantment enchantment, EntityLiving entityliving) { - return a(enchantment, entityliving, (itemstack) -> { - return true; - }); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b9a12d59e0144becc7e9c06d9a3c3079d006b583..e00b33493208865c0bd1bd11a96dd2ed1348da7c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -58,13 +58,17 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; -+import net.minecraft.world.item.enchantment.EnchantmentManager; -+import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -1178,8 +1182,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId()); - } - -+ // Paper start - @Override -- public void giveExp(int exp) { -+ public int applyMending(int amount) { -+ EntityPlayer handle = getHandle(); -+ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties -+ net.minecraft.world.item.ItemStack itemstack = EnchantmentManager.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); -+ if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) { -+ -+ EntityExperienceOrb orb = EntityTypes.EXPERIENCE_ORB.create(handle.world); -+ orb.value = amount; -+ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; -+ orb.setPositionRaw(handle.locX(), handle.locY(), handle.locZ()); -+ -+ int i = Math.min(orb.xpToDur(amount), itemstack.getDamage()); -+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); -+ i = event.getRepairAmount(); -+ orb.dead = true; -+ if (!event.isCancelled()) { -+ amount -= orb.durToXp(i); -+ itemstack.setDamage(itemstack.getDamage() - i); -+ } -+ } -+ return amount; -+ } -+ -+ @Override -+ public void giveExp(int exp, boolean applyMending) { -+ if (applyMending) { -+ exp = this.applyMending(exp); -+ } -+ // Paper end - getHandle().giveExp(exp); - } - diff --git a/Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch b/Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch deleted file mode 100644 index d6706377d799..000000000000 --- a/Spigot-Server-Patches/0184-Make-max-squid-spawn-height-configurable.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 11 Jan 2018 16:47:28 -0600 -Subject: [PATCH] Make max squid spawn height configurable - -I don't know why upstream made only the minimum height configurable but -whatever - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c692e58cde22003ecbf6dc5695799147c39905a..3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -348,4 +348,9 @@ public class PaperWorldConfig { - expMergeMaxValue = getInt("experience-merge-max-value", -1); - log("Experience Merge Max Value: " + expMergeMaxValue); - } -+ -+ public double squidMaxSpawnHeight; -+ private void squidMaxSpawnHeight() { -+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 3cc9af925aaf116140d5f36cfc56aa001ffb4e35..7ce5e2597b34d3a4d2a79d73c15e893c064fc88c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -196,7 +196,8 @@ public class EntitySquid extends EntityWaterAnimal { - } - - public static boolean b(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -- return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < generatoraccess.getSeaLevel(); // Spigot -+ final double maxHeight = generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : generatoraccess.getSeaLevel(); // Paper -+ return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper - } - - public void a(float f, float f1, float f2) { diff --git a/Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch b/Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch deleted file mode 100644 index 24bbe6c28fa9..000000000000 --- a/Spigot-Server-Patches/0185-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index a707ba365e25ea15e2e9d22110696b6136aa0c6f..1355c074353611669c947cb0f06c67be0ab418aa 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -17,6 +17,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; -@@ -317,6 +318,20 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -index 41f1aecbf6b506231a1b3b525fe0ce23b35c7840..6c01e460d3a1ff7f865ebc34dfd28d55b16aab98 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -@@ -33,7 +33,7 @@ public class SensorGolemLastSeen extends Sensor { - Optional> optional = entityliving.getBehaviorController().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes - return entityliving1.getEntityType().equals(EntityTypes.IRON_GOLEM); - }); - -@@ -44,6 +44,7 @@ public class SensorGolemLastSeen extends Sensor { - } - } - -+ public static void setDetectedRecently(EntityLiving entityLiving) { b(entityLiving); } // Paper - OBFHELPER - public static void b(EntityLiving entityliving) { - entityliving.getBehaviorController().a(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0c579cff2fcabd15a2a0af919fcc60b4e7ce25ad..858bbfbc08a5f2e1ef93ff52d6708059b32fbbbf 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; -@@ -943,6 +944,21 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - BlockPosition blockposition1 = this.a(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ SensorGolemLastSeen.b(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - EntityIronGolem entityirongolem = (EntityIronGolem) EntityTypes.IRON_GOLEM.createCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition1, EnumMobSpawn.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 883c724fbb86a84ee903b5e7127f14726fe4cf24..d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -12,6 +12,7 @@ import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; - import net.minecraft.util.WeightedRandom; -@@ -125,6 +126,27 @@ public abstract class MobSpawnerAbstract { - WorldServer worldserver = (WorldServer) world; - - if (EntityPositionTypes.a((EntityTypes) optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityTypes entityType = optional.get(); -+ String key = EntityTypes.getName(entityType).getKey(); -+ -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, d3, d4, d5), -+ type, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ ); -+ if (!event.callEvent()) { -+ flag = true; -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ } -+ // Paper end - Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> { - entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index fd0595fd584046326eccacdf0a6afe40c5e84eed..1969d1002b3182338614a2be0519fcdc385b7a44 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -216,9 +217,16 @@ public final class SpawnerCreature { - j1 = biomesettingsmobs_c.d + worldserver.random.nextInt(1 + biomesettingsmobs_c.e - biomesettingsmobs_c.d); - } - -- if (a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper start -+ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper end - EntityInsentient entityinsentient = a(worldserver, biomesettingsmobs_c.c); - -+ - if (entityinsentient == null) { - return; - } -@@ -271,8 +279,24 @@ public final class SpawnerCreature { - } - } - -- private static boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -+ private static Boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { // Paper - EntityTypes entitytypes = biomesettingsmobs_c.c; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(entitytypes).getKey()); -+ if (type != null) { -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), -+ type, SpawnReason.NATURAL -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ return null; -+ } -+ return false; -+ } -+ } -+ // Paper end - - if (entitytypes.e() == EnumCreatureType.MISC) { - return false; diff --git a/Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch b/Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index 1367843d5305..000000000000 --- a/Spigot-Server-Patches/0186-PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:36:02 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 9ed97d5db81e3603ccccca7500420d7e401ef2a5..b9bde85a90b429659e1a4ab111253cddd797368e 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -611,6 +611,15 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ //Paper start - call player naturally spawn event -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -+ chunkRange = Math.min(chunkRange, 8); -+ for (EntityPlayer entityPlayer : this.world.getPlayers()) { -+ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -+ entityPlayer.playerNaturallySpawnedEvent.callEvent(); -+ }; -+ // Paper end - this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5b2ae94ed7d499e401a058691eb6ed413b626150..de7167ddf7b36ef266e511187789f99244401c21 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.level; - -+import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; -@@ -228,6 +229,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean sentListPacket = false; - public Integer clientViewDistance; - // CraftBukkit end -+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 1d71a19a7bbe463f537861531113dd1ed3e5b977..d1e45dfb99074ec027d4f943391a024c726d93b2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -966,12 +966,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; - -- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; -+ final int finalChunkRange = chunkRange; // Paper for lambda below -+ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end - long i = chunkcoordintpair.pair(); - - return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -+ double blockRange = 16384.0D; -+ if (reducedRange) { -+ event = entityplayer.playerNaturallySpawnedEvent; -+ if (event == null || event.isCancelled()) return false; -+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -+ } -+ -+ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -+ // Paper end - }); - } - diff --git a/Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch b/Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index da897bd9728c..000000000000 --- a/Spigot-Server-Patches/0187-Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:36:25 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -index 80ee7ab69ff70431d51321d403e5e3400a24bd67..00fb749f4d181d8d830496cf741d589e10af5098 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -@@ -1,5 +1,7 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.base.Preconditions; - import com.mojang.authlib.GameProfile; - import net.minecraft.server.MinecraftServer; -@@ -15,6 +17,7 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.block.data.Directional; - import org.bukkit.block.data.Rotatable; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import javax.annotation.Nullable; - - public class CraftSkull extends CraftBlockEntityState implements Skull { - -@@ -105,6 +108,20 @@ public class CraftSkull extends CraftBlockEntityState implement - } - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(PlayerProfile profile) { -+ Preconditions.checkNotNull(profile, "profile"); -+ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public BlockFace getRotation() { - BlockData blockData = getBlockData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 8298ae9bf1c5635f08552c15f004b3d0f6e9f19b..6db0d35eba647a0e81ca464fa52dc4a404ddd2ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -8,6 +8,8 @@ import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.OfflinePlayer; -@@ -18,6 +20,7 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.SkullMeta; - -+import javax.annotation.Nullable; - @DelegateDeserialization(SerializableMeta.class) - class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - -@@ -149,6 +152,19 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(@Nullable PlayerProfile profile) { -+ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOwningPlayer() { - if (hasOwner()) { -@@ -175,7 +191,7 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } else { - // Paper start - Use Online Players Skull - GameProfile newProfile = null; -- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ net.minecraft.server.level.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); - if (player != null) newProfile = player.getProfile(); - if (newProfile == null) newProfile = new GameProfile(null, name); - setProfile(newProfile); diff --git a/Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch b/Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch deleted file mode 100644 index 30643d081c2c..000000000000 --- a/Spigot-Server-Patches/0188-Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:26 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -index 93d73c27340645c7502acafdc0b2cfbc1a759dd8..5c7d2ee19243d0911a3a00af3ae42078a2ccba94 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -1,6 +1,8 @@ - package com.destroystokyo.paper.profile; - - import com.mojang.authlib.Environment; -+import com.destroystokyo.paper.event.profile.FillProfileEvent; -+import com.destroystokyo.paper.event.profile.PreFillProfileEvent; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.minecraft.MinecraftProfileTexture; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -@@ -20,7 +22,15 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi - - @Override - public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -- return super.fillProfileProperties(profile, requireSecure); -+ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); -+ new PreFillProfileEvent(playerProfile).callEvent(); -+ profile = playerProfile.getGameProfile(); -+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { -+ return profile; -+ } -+ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); -+ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); -+ return gameProfile; - } - - @Override diff --git a/Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch b/Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index e919ba303208..000000000000 --- a/Spigot-Server-Patches/0189-PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:29 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index d832cc2f3cc1ee73299a7f07eb2ccc3d392d5cf8..7d37626277823d5db05189c20bb1ebf91aa2a286 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -297,6 +297,12 @@ public class AdvancementDataPlayer { - boolean flag1 = advancementprogress.isDone(); - - if (advancementprogress.a(s)) { -+ // Paper start -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, s).callEvent()) { -+ advancementprogress.b(s); -+ return false; -+ } -+ // Paper end - this.d(advancement); - this.j.add(advancement); - flag = true; diff --git a/Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch b/Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 658b0384d9ef..000000000000 --- a/Spigot-Server-Patches/0190-Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 27 Jan 2018 17:04:14 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -Fixes GH-559 - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -index c593499aee3a2737cd80739ce61e7fba133d11ec..6b460841a8428727dd55a841fe5af06de9b1bdd1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -@@ -9,9 +9,22 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; - import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; - - @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) --public class CraftMetaArmorStand extends CraftMetaItem { -+public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper - - static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); -+ // Paper start -+ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); -+ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); -+ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); -+ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); -+ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); -+ -+ private boolean invisible; -+ private boolean noBasePlate; -+ private boolean showArms; -+ private boolean small; -+ private boolean marker; -+ // Paper end - NBTTagCompound entityTag; - - CraftMetaArmorStand(CraftMetaItem meta) { -@@ -22,6 +35,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; -+ // Paper start -+ this.invisible = armorStand.invisible; -+ this.noBasePlate = armorStand.noBasePlate; -+ this.showArms = armorStand.showArms; -+ this.small = armorStand.small; -+ this.marker = armorStand.marker; -+ // Paper end - this.entityTag = armorStand.entityTag; - } - -@@ -30,11 +50,47 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - if (tag.hasKey(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); -+ -+ // Paper start -+ if (entityTag.hasKey(INVISIBLE.NBT)) { -+ invisible = entityTag.getBoolean(INVISIBLE.NBT); -+ } -+ -+ if (entityTag.hasKey(NO_BASE_PLATE.NBT)) { -+ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); -+ } -+ -+ if (entityTag.hasKey(SHOW_ARMS.NBT)) { -+ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); -+ } -+ -+ if (entityTag.hasKey(SMALL.NBT)) { -+ small = entityTag.getBoolean(SMALL.NBT); -+ } -+ -+ if (entityTag.hasKey(MARKER.NBT)) { -+ marker = entityTag.getBoolean(MARKER.NBT); -+ } -+ // Paper end - } - } - - CraftMetaArmorStand(Map map) { - super(map); -+ -+ // Paper start -+ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); -+ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); -+ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); -+ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); -+ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); -+ -+ this.invisible = invis; -+ this.noBasePlate = noBase; -+ this.showArms = showArms; -+ this.small = small; -+ this.marker = marker; -+ // Paper end - } - - @Override -@@ -57,6 +113,32 @@ public class CraftMetaArmorStand extends CraftMetaItem { - void applyToItem(NBTTagCompound tag) { - super.applyToItem(tag); - -+ // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new NBTTagCompound(); -+ } -+ -+ if (isInvisible()) { -+ entityTag.setBoolean(INVISIBLE.NBT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ entityTag.setBoolean(NO_BASE_PLATE.NBT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ entityTag.setBoolean(SHOW_ARMS.NBT, showArms); -+ } -+ -+ if (isSmall()) { -+ entityTag.setBoolean(SMALL.NBT, small); -+ } -+ -+ if (isMarker()) { -+ entityTag.setBoolean(MARKER.NBT, marker); -+ } -+ // Paper end -+ - if (entityTag != null) { - tag.set(ENTITY_TAG.NBT, entityTag); - } -@@ -78,7 +160,7 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - boolean isArmorStandEmpty() { -- return !(entityTag != null); -+ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); - } - - @Override -@@ -89,7 +171,13 @@ public class CraftMetaArmorStand extends CraftMetaItem { - if (meta instanceof CraftMetaArmorStand) { - CraftMetaArmorStand that = (CraftMetaArmorStand) meta; - -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; -+ // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; -+ // Paper end - } - return true; - } -@@ -104,9 +192,14 @@ public class CraftMetaArmorStand extends CraftMetaItem { - final int original; - int hash = original = super.applyHash(); - -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); -- } -+ // Paper start -+ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; -+ hash += isInvisible() ? 61 * hash + 1231 : 0; -+ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; -+ hash += shouldShowArms() ? 61 * hash + 1231 : 0; -+ hash += isSmall() ? 61 * hash + 1231 : 0; -+ hash += isMarker() ? 61 * hash + 1231 : 0; -+ // Paper end - - return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; - } -@@ -115,6 +208,28 @@ public class CraftMetaArmorStand extends CraftMetaItem { - Builder serialize(Builder builder) { - super.serialize(builder); - -+ // Paper start -+ if (isInvisible()) { -+ builder.put(INVISIBLE.BUKKIT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ builder.put(SHOW_ARMS.BUKKIT, showArms); -+ } -+ -+ if (isSmall()) { -+ builder.put(SMALL.BUKKIT, small); -+ } -+ -+ if (isMarker()) { -+ builder.put(MARKER.BUKKIT, marker); -+ } -+ // Paper end -+ - return builder; - } - -@@ -128,4 +243,56 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - return clone; - } -+ -+ // Paper start -+ @Override -+ public boolean isInvisible() { -+ return invisible; -+ } -+ -+ @Override -+ public boolean hasNoBasePlate() { -+ return noBasePlate; -+ } -+ -+ @Override -+ public boolean shouldShowArms() { -+ return showArms; -+ } -+ -+ @Override -+ public boolean isSmall() { -+ return small; -+ } -+ -+ @Override -+ public boolean isMarker() { -+ return marker; -+ } -+ -+ @Override -+ public void setInvisible(boolean invisible) { -+ this.invisible = invisible; -+ } -+ -+ @Override -+ public void setNoBasePlate(boolean noBasePlate) { -+ this.noBasePlate = noBasePlate; -+ } -+ -+ @Override -+ public void setShowArms(boolean showArms) { -+ this.showArms = showArms; -+ } -+ -+ @Override -+ public void setSmall(boolean small) { -+ this.small = small; -+ } -+ -+ @Override -+ public void setMarker(boolean marker) { -+ this.marker = marker; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 57a6e66866ea82caccbbbfd55948a081f50f6bbe..7f790c484fec77e1d1f1dc6abe0daa19d009ae46 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -1442,6 +1442,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaCrossbow.CHARGED.NBT, - CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, - CraftMetaSuspiciousStew.EFFECTS.NBT, -+ // Paper start -+ CraftMetaArmorStand.ENTITY_TAG.NBT, -+ CraftMetaArmorStand.INVISIBLE.NBT, -+ CraftMetaArmorStand.NO_BASE_PLATE.NBT, -+ CraftMetaArmorStand.SHOW_ARMS.NBT, -+ CraftMetaArmorStand.SMALL.NBT, -+ CraftMetaArmorStand.MARKER.NBT, -+ // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.NBT -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 9a351c137776ac622f4df7353bb353142b3a6ccc..42f577ed3508ba5a380648461e149f16ce97c9bd 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -313,6 +313,7 @@ public class ItemMetaTest extends AbstractTestingBase { - final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); - meta.entityTag = new NBTTagCompound(); - meta.entityTag.setBoolean("Small", true); -+ meta.setInvisible(true); // Paper - cleanStack.setItemMeta(meta); - return cleanStack; - } diff --git a/Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch b/Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch deleted file mode 100644 index d3407a908a71..000000000000 --- a/Spigot-Server-Patches/0191-Extend-Player-Interact-cancellation.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Feb 2018 10:43:46 +0000 -Subject: [PATCH] Extend Player Interact cancellation - -GUIs are opened on the client, meaning that the server cannot block them from opening, -However, it is possible to close these GUIs from the server. - -Flower pots are also not updated on the client when interaction is cancelled, this patch -also resolves this. - -Update adjacent blocks of doors, double plants, pistons and beds -when cancelling interaction. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 74b4b127f39a0ad06e8f9add6861763724ab70ba..14f287d30c9a141f78f6311bef02a6fc4fa17564 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.network.protocol.game.PacketPlayInBlockDig; - import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak; -+import net.minecraft.network.protocol.game.PacketPlayOutCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; -@@ -18,6 +19,7 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockFlowerPot; - import net.minecraft.world.level.block.BlockJigsaw; - import net.minecraft.world.level.block.BlockStructure; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -180,6 +182,11 @@ public class PlayerInteractManager { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - if (event.isCancelled()) { - // Let the client know the block still exists -+ // Paper start - brute force neighbor blocks for any attached blocks -+ for (EnumDirection dir : EnumDirection.values()) { -+ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.shift(dir))); -+ } -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); - // Update any tile entity data for this block - TileEntity tileentity = this.world.getTileEntity(blockposition); -@@ -484,6 +491,7 @@ public class PlayerInteractManager { - interactItemStack = itemstack.cloneItemStack(); - - if (event.useInteractedBlock() == Event.Result.DENY) { -+ - // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. - if (iblockdata.getBlock() instanceof BlockDoor) { - boolean bottom = iblockdata.get(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; -@@ -496,7 +504,13 @@ public class PlayerInteractManager { - - // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) - entityplayer.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.up())); -+ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method -+ } else if (iblockdata.getBlock() instanceof BlockStructure) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); -+ } else if (iblockdata.getBlock() instanceof BlockCommand) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); - } -+ // Paper end - extend Player Interact cancellation - entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867 - enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; - } else if (this.gamemode == EnumGamemode.SPECTATOR) { diff --git a/Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch b/Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch deleted file mode 100644 index eae20f237a5d..000000000000 --- a/Spigot-Server-Patches/0192-Tameable-getOwnerUniqueId-API.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 24 Feb 2018 01:14:55 -0500 -Subject: [PATCH] Tameable#getOwnerUniqueId API - -This is faster if all you need is the UUID, as .getOwner() will cause -an OfflinePlayer to be loaded from disk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 62ccef35e4b4238c50faf778fbf3ea9a494ca387..5b66165471197aad57e23f9a6669b11f25a5e4f2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -90,6 +90,9 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - } - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index 3ac6623199f991ba16dbd62f4d6eed9982b22bcb..73a8ae346fb2ca5af172d96fa6b28e4d41a8c294 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -@@ -17,6 +17,9 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat - return (EntityTameableAnimal) super.getHandle(); - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - try { - return getHandle().getOwnerUUID(); diff --git a/Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch deleted file mode 100644 index 70c6b6d3e1b1..000000000000 --- a/Spigot-Server-Patches/0193-Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 10 Mar 2018 00:50:24 +0100 -Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c39f1bb3d88baaaed4dd43c51faeef89bb5c6c2..48f0385c7203c7955de5a015f3dc42be2ab7b681 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -192,6 +192,11 @@ public class PaperWorldConfig { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } - -+ public boolean disablePlayerCrits; -+ private void disablePlayerCrits() { -+ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); -+ } -+ - public boolean allChunksAreSlimeChunks; - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index f9d0623a3ed5f49758cd5e97fe9f63a5b3198e58..18b0020d184e46c8957e82100681c8c66b1c3b62 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1134,6 +1134,7 @@ public abstract class EntityHuman extends EntityLiving { - - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.isClimbing() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof EntityLiving; - -+ flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper - flag2 = flag2 && !this.isSprinting(); - if (flag2) { - f *= 1.5F; diff --git a/Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch deleted file mode 100644 index 8ea2e3bb7431..000000000000 --- a/Spigot-Server-Patches/0194-Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Mar 2018 16:33:15 -0500 -Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index e32e94868386ff06ff29254e6cc3bee9b446a293..cbe8a6db356396f9fd9ce7cc61a5845bb8e6499d 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -40,7 +40,8 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[j]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata1 = worldserver.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata1 == null) { continue; } // Paper - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { - worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay -@@ -83,7 +84,9 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[l]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- if (iblockaccess.getType(blockposition_mutableblockposition).a((Block) this)) { -+ // Paper start -+ IBlockData type = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (type != null && type.a((Block) this)) { // Paper end - ++j; - if (j >= i) { - return false; diff --git a/Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch b/Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch deleted file mode 100644 index c5919e14be84..000000000000 --- a/Spigot-Server-Patches/0195-Disable-Explicit-Network-Manager-Flushing.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 11 Mar 2018 14:13:33 -0400 -Subject: [PATCH] Disable Explicit Network Manager Flushing - -This seems completely pointless, as packet dispatch uses .writeAndFlush. - -Things seem to work fine without explicit flushing, but incase issues arise, -provide a System property to re-enable it using improved logic of doing the -flushing on the netty event loop, so it won't do the flush on the main thread. - -Renable flushing by passing -Dpaper.explicit-flush=true - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 60e4a4aa3854aaeb250d1318f2f25cf3591ea1d3..297820baef99e97e1216a64c527219e9ccc3e320 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -73,6 +73,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - // Paper start - NetworkClient implementation - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; -+ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -240,7 +241,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - if (this.channel != null) { -- this.channel.flush(); -+ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version - } - - if (this.t++ % 20 == 0) { diff --git a/Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch b/Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch deleted file mode 100644 index 66ba1bb225c4..000000000000 --- a/Spigot-Server-Patches/0196-Implement-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:56:26 +0200 -Subject: [PATCH] Implement extended PaperServerListPingEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e7f1efd0466a5d7bb9584ffbd6fbac1ecc6153a5 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -@@ -0,0 +1,31 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.entity.Player; -+import org.bukkit.util.CachedServerIcon; -+ -+import javax.annotation.Nullable; -+ -+class PaperServerListPingEventImpl extends PaperServerListPingEvent { -+ -+ private final MinecraftServer server; -+ -+ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { -+ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), -+ server.getServerModName() + ' ' + server.getVersion(), protocolVersion, icon); -+ this.server = server; -+ } -+ -+ @Override -+ protected final Object[] getOnlinePlayers() { -+ return this.server.getPlayerList().players.toArray(); -+ } -+ -+ @Override -+ protected final Player getBukkitPlayer(Object player) { -+ return ((EntityPlayer) player).getBukkitEntity(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..46e84ac6ba5d32d030267fb0c991c281a673c716 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -@@ -0,0 +1,11 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+class PaperStatusClient extends PaperNetworkClient implements StatusClient { -+ -+ PaperStatusClient(NetworkManager networkManager) { -+ super(networkManager); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..174326871df9b61beec51ef6a1e5f26932404b6a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -@@ -0,0 +1,110 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.google.common.base.MoreObjects; -+import com.google.common.base.Strings; -+import com.mojang.authlib.GameProfile; -+import io.papermc.paper.adventure.AdventureComponent; -+import java.util.List; -+import java.util.UUID; -+import javax.annotation.Nonnull; -+import net.minecraft.network.NetworkManager; -+import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; -+import net.minecraft.network.protocol.status.ServerPing; -+import net.minecraft.server.MinecraftServer; -+ -+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { -+ -+ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; -+ private static final UUID FAKE_UUID = new UUID(0, 0); -+ -+ private GameProfile[] originalSample; -+ -+ private StandardPaperServerListPingEventImpl(MinecraftServer server, NetworkManager networkManager, ServerPing ping) { -+ super(server, new PaperStatusClient(networkManager), ping.getServerData() != null ? ping.getServerData().getProtocolVersion() : -1, server.server.getServerIcon()); -+ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE -+ } -+ -+ @Nonnull -+ @Override -+ public List getPlayerSample() { -+ List sample = super.getPlayerSample(); -+ -+ if (this.originalSample != null) { -+ for (GameProfile profile : this.originalSample) { -+ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); -+ } -+ this.originalSample = null; -+ } -+ -+ return sample; -+ } -+ -+ private GameProfile[] getPlayerSampleHandle() { -+ if (this.originalSample != null) { -+ return this.originalSample; -+ } -+ -+ List entries = super.getPlayerSample(); -+ if (entries.isEmpty()) { -+ return EMPTY_PROFILES; -+ } -+ -+ GameProfile[] profiles = new GameProfile[entries.size()]; -+ for (int i = 0; i < profiles.length; i++) { -+ /* -+ * Avoid null UUIDs/names since that will make the response invalid -+ * on the client. -+ * Instead, fall back to a fake/empty UUID and an empty string as name. -+ * This can be used to create custom lines in the player list that do not -+ * refer to a specific player. -+ */ -+ -+ PlayerProfile profile = entries.get(i); -+ if (profile.getId() != null && profile.getName() != null) { -+ profiles[i] = CraftPlayerProfile.asAuthlib(profile); -+ } else { -+ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); -+ } -+ } -+ -+ return profiles; -+ } -+ -+ @SuppressWarnings("deprecation") -+ public static void processRequest(MinecraftServer server, NetworkManager networkManager) { -+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getServerPing()); -+ server.server.getPluginManager().callEvent(event); -+ -+ // Close connection immediately if event is cancelled -+ if (event.isCancelled()) { -+ networkManager.close(null); -+ return; -+ } -+ -+ // Setup response -+ ServerPing ping = new ServerPing(); -+ -+ // Description -+ ping.setMOTD(new AdventureComponent(event.motd())); -+ -+ // Players -+ if (!event.shouldHidePlayers()) { -+ ping.setPlayerSample(new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), event.getNumPlayers())); -+ ping.getPlayers().setSample(event.getPlayerSampleHandle()); -+ } -+ -+ // Version -+ ping.setServerInfo(new ServerPing.ServerData(event.getVersion(), event.getProtocolVersion())); -+ -+ // Favicon -+ if (event.getServerIcon() != null) { -+ ping.setFavicon(event.getServerIcon().getData()); -+ } -+ -+ // Send response -+ networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -index 0ebeacaaeb265d202f52c758566a5160c42e8a55..cb37805c8cc5a064391f338c6359df518f6db39a 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -+++ b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -@@ -2,6 +2,7 @@ package net.minecraft.network.protocol.status; - - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatModifier; -@@ -12,7 +13,9 @@ import net.minecraft.util.ChatTypeAdapterFactory; - - public class PacketStatusOutServerInfo implements Packet { - -- private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()).create(); -+ private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()) -+ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) -+ .create(); - private ServerPing b; - - public PacketStatusOutServerInfo() {} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -index 005ae7a75dfb19152abb606da29acad07c85e499..b9e36a83837913cd3e5abe598f695ba7a9ffc417 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -@@ -31,6 +31,7 @@ public class ServerPing { - this.a = ichatbasecomponent; - } - -+ public ServerPingPlayerSample getPlayers() { return b(); } // Paper - OBFHELPER - public ServerPing.ServerPingPlayerSample b() { - return this.b; - } -@@ -162,10 +163,12 @@ public class ServerPing { - return this.b; - } - -+ public GameProfile[] getSample() { return c(); } // Paper - OBFHELPER - public GameProfile[] c() { - return this.c; - } - -+ public void setSample(GameProfile[] sample) { a(sample); } // Paper - OBFHELPER - public void a(GameProfile[] agameprofile) { - this.c = agameprofile; - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bad6dfcb9ed558499c39880c44ae514ee2051a3c..925dd2dc2b4af5596c9dc891f756bad66baadbea 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,6 +2,9 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -1240,7 +1243,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 5000000000L) { - this.T = i; - this.serverPing.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.getMaxPlayers(), this.getPlayerCount())); -- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; -+ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper - int j = MathHelper.nextInt(this.r, 0, this.getPlayerCount() - agameprofile.length); - - for (int k = 0; k < agameprofile.length; ++k) { -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index d219eda271a71f786808a6958b829fca40a1aaba..e1997563984540e6edf5d3b697d029dc5f3c40e1 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -48,6 +48,8 @@ public class PacketStatusListener implements PacketStatusInListener { - this.networkManager.close(PacketStatusListener.a); - } else { - this.d = true; -+ // Paper start - Replace everything -+ /* - // CraftBukkit start - // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); - final Object[] players = minecraftServer.getPlayerList().players.toArray(); -@@ -143,6 +145,9 @@ public class PacketStatusListener implements PacketStatusInListener { - ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); - - this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ */ -+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.minecraftServer, this.networkManager); -+ // Paper end - } - // CraftBukkit end - } -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index e8e5e5b568ba53dd006f1461cb4f027ceeae5528..11f8a2e5bf43013bce8675ea310ff42eacf14754 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -289,7 +289,7 @@ public class SpigotConfig - public static int playerSample; - private static void playerSample() - { -- playerSample = getInt( "settings.sample-count", 12 ); -+ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts - Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - diff --git a/Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch b/Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch deleted file mode 100644 index b0ae82322167..000000000000 --- a/Spigot-Server-Patches/0197-Improved-Async-Task-Scheduler.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Mar 2018 22:59:43 -0400 -Subject: [PATCH] Improved Async Task Scheduler - -The Craft Scheduler still uses the primary thread for task scheduling. -This results in the main thread still having to do work as part of the -dispatching of async tasks. - -If plugins make use of lots of async tasks, such as particle emitters -that want to keep the logic off the main thread, the main thread still -receives quite a bit of load from processing all of these queued tasks. - -Additionally, resizing and managing the pending entries for all of -these asynchronous tasks takes up time on the main thread too. - -This commit replaces the implementation of the scheduler when working -with asynchronous tasks, by forwarding calls to the new scheduler. - -The Async Scheduler uses a single thread executor for "management" tasks. -The Management Thread is responsible for all adding and dispatching of -scheduled tasks. - -The mainThreadHeartbeat will send a heartbeat task to the management thread -with the currentTick value, so that it can find which tasks to execute. - -Scheduling of an async tasks also dispatches a management task, ensuring -that any Queue resizing operation occurs off of the main thread. - -The async queue uses a complete separate PriorityQueue, ensuring that resize -operations are decoupled from the sync tasks queue. - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3c1992e212a6d6f1db4d5b807b38d71913619fc0 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * 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. -+ */ -+ -+package org.bukkit.craftbukkit.scheduler; -+ -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.SynchronousQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+ -+public class CraftAsyncScheduler extends CraftScheduler { -+ -+ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( -+ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), -+ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); -+ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() -+ .setNameFormat("Craft Async Scheduler Management Thread").build()); -+ private final List temp = new ArrayList<>(); -+ -+ CraftAsyncScheduler() { -+ super(true); -+ executor.allowCoreThreadTimeOut(true); -+ executor.prestartAllCoreThreads(); -+ } -+ -+ @Override -+ public void cancelTask(int taskId) { -+ this.management.execute(() -> this.removeTask(taskId)); -+ } -+ -+ private synchronized void removeTask(int taskId) { -+ parsePending(); -+ this.pending.removeIf((task) -> { -+ if (task.getTaskId() == taskId) { -+ task.cancel0(); -+ return true; -+ } -+ return false; -+ }); -+ } -+ -+ @Override -+ public void mainThreadHeartbeat(int currentTick) { -+ this.currentTick = currentTick; -+ this.management.execute(() -> this.runTasks(currentTick)); -+ } -+ -+ private synchronized void runTasks(int currentTick) { -+ parsePending(); -+ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { -+ CraftTask task = this.pending.remove(); -+ if (executeTask(task)) { -+ final long period = task.getPeriod(); -+ if (period > 0) { -+ task.setNextRun(currentTick + period); -+ temp.add(task); -+ } -+ } -+ parsePending(); -+ } -+ this.pending.addAll(temp); -+ temp.clear(); -+ } -+ -+ private boolean executeTask(CraftTask task) { -+ if (isValid(task)) { -+ this.runners.put(task.getTaskId(), task); -+ this.executor.execute(new ServerSchedulerReportingWrapper(task)); -+ return true; -+ } -+ return false; -+ } -+ -+ @Override -+ public synchronized void cancelTasks(Plugin plugin) { -+ parsePending(); -+ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { -+ CraftTask task = iterator.next(); -+ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { -+ task.cancel0(); -+ iterator.remove(); -+ } -+ } -+ } -+ -+ /** -+ * Task is not cancelled -+ * @param runningTask -+ * @return -+ */ -+ static boolean isValid(CraftTask runningTask) { -+ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0e0f361c3af363539d5d1d865603114bdb84fd67..ca90237a53c9a026919d28adaedf483ca3c7c2a8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -63,7 +63,7 @@ public class CraftScheduler implements BukkitScheduler { - /** - * Main thread logic only - */ -- private final PriorityQueue pending = new PriorityQueue(10, -+ final PriorityQueue pending = new PriorityQueue(10, // Paper - new Comparator() { - @Override - public int compare(final CraftTask o1, final CraftTask o2) { -@@ -80,12 +80,13 @@ public class CraftScheduler implements BukkitScheduler { - /** - * These are tasks that are currently active. It's provided for 'viewing' the current state. - */ -- private final ConcurrentHashMap runners = new ConcurrentHashMap(); -+ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper - /** - * The sync task that is currently running on the main thread. - */ - private volatile CraftTask currentTask = null; -- private volatile int currentTick = -1; -+ // Paper start - Improved Async Task Scheduler -+ volatile int currentTick = -1;/* - private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); - private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { - @Override -@@ -94,12 +95,31 @@ public class CraftScheduler implements BukkitScheduler { - } - }; - private CraftAsyncDebugger debugTail = debugHead; -+ -+ */ // Paper end - private static final int RECENT_TICKS; - - static { - RECENT_TICKS = 30; - } - -+ -+ // Paper start -+ private final CraftScheduler asyncScheduler; -+ private final boolean isAsyncScheduler; -+ public CraftScheduler() { -+ this(false); -+ } -+ -+ public CraftScheduler(boolean isAsync) { -+ this.isAsyncScheduler = isAsync; -+ if (isAsync) { -+ this.asyncScheduler = this; -+ } else { -+ this.asyncScheduler = new CraftAsyncScheduler(); -+ } -+ } -+ // Paper end - @Override - public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { - return this.scheduleSyncDelayedTask(plugin, task, 0L); -@@ -222,7 +242,7 @@ public class CraftScheduler implements BukkitScheduler { - } else if (period < CraftTask.NO_REPEATING) { - period = CraftTask.NO_REPEATING; - } -- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); -+ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper - } - - @Override -@@ -238,6 +258,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return; - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTask(taskId); -+ } -+ // Paper end - CraftTask task = runners.get(taskId); - if (task != null) { - task.cancel0(); -@@ -280,6 +305,11 @@ public class CraftScheduler implements BukkitScheduler { - @Override - public void cancelTasks(final Plugin plugin) { - Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTasks(plugin); -+ } -+ // Paper end - final CraftTask task = new CraftTask( - new Runnable() { - @Override -@@ -319,6 +349,13 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public boolean isCurrentlyRunning(final int taskId) { -+ // Paper start -+ if (!isAsyncScheduler) { -+ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { -+ return true; -+ } -+ } -+ // Paper end - final CraftTask task = runners.get(taskId); - if (task == null) { - return false; -@@ -337,6 +374,11 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return false; - } -+ // Paper start -+ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { -+ return true; -+ } -+ // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { - if (task.getTaskId() == taskId) { - return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run -@@ -348,6 +390,12 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public List getActiveWorkers() { -+ // Paper start -+ if (!isAsyncScheduler) { -+ //noinspection TailRecursion -+ return this.asyncScheduler.getActiveWorkers(); -+ } -+ // Paper end - final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { - // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread -@@ -385,6 +433,11 @@ public class CraftScheduler implements BukkitScheduler { - pending.add(task); - } - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ pending.addAll(this.asyncScheduler.getPendingTasks()); -+ } -+ // Paper end - return pending; - } - -@@ -392,6 +445,11 @@ public class CraftScheduler implements BukkitScheduler { - * This method is designed to never block or wait for locks; an immediate execution of all current tasks. - */ - public void mainThreadHeartbeat(final int currentTick) { -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.mainThreadHeartbeat(currentTick); -+ } -+ // Paper end - this.currentTick = currentTick; - final List temp = this.temp; - parsePending(); -@@ -431,7 +489,7 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper -+ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } -@@ -450,7 +508,7 @@ public class CraftScheduler implements BukkitScheduler { - //debugHead = debugHead.getNextHead(currentTick); // Paper - } - -- private void addTask(final CraftTask task) { -+ protected void addTask(final CraftTask task) { - final AtomicReference tail = this.tail; - CraftTask tailTask = tail.get(); - while (!tail.compareAndSet(tailTask, task)) { -@@ -459,7 +517,13 @@ public class CraftScheduler implements BukkitScheduler { - tailTask.setNext(task); - } - -- private CraftTask handle(final CraftTask task, final long delay) { -+ protected CraftTask handle(final CraftTask task, final long delay) { // Paper -+ // Paper start -+ if (!this.isAsyncScheduler && !task.isSync()) { -+ this.asyncScheduler.handle(task, delay); -+ return task; -+ } -+ // Paper end - task.setNextRun(currentTick + delay); - addTask(task); - return task; -@@ -478,8 +542,8 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); - } - -- private void parsePending() { -- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); -+ void parsePending() { // Paper -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -498,7 +562,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper - } - - private boolean isReady(final int currentTick) { diff --git a/Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index 9b4622cc4414..000000000000 --- a/Spigot-Server-Patches/0198-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:45:57 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index f95f5a8b30f42c8f5b6cee3ef6adb1f4e09832dc..31d404c5343c33b9b64724c5ac40d0c52ad5af66 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.exceptions.AuthenticationUnavailableException; - import java.math.BigInteger; -@@ -38,6 +40,7 @@ import org.apache.logging.log4j.Logger; - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -316,8 +319,16 @@ public class LoginListener implements PacketLoginInListener { - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); -+ // Paper start -+ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); -+ profile = asyncEvent.getPlayerProfile(); -+ profile.complete(); -+ i = CraftPlayerProfile.asAuthlibCopy(profile); -+ playerName = i.getName(); -+ uniqueId = i.getId(); -+ // Paper end - - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch b/Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch deleted file mode 100644 index 2fc79938cb62..000000000000 --- a/Spigot-Server-Patches/0199-Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:29:48 -0400 -Subject: [PATCH] Player.setPlayerProfile API - -This can be useful for changing name or skins after a player has logged in. - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 31d404c5343c33b9b64724c5ac40d0c52ad5af66..21e70a133278d85ecd65fec36a273ed4faabf6cc 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -56,7 +56,7 @@ public class LoginListener implements PacketLoginInListener { - public final NetworkManager networkManager; - private LoginListener.EnumProtocolState g; - private int h; -- private GameProfile i; -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; -@@ -320,12 +320,12 @@ public class LoginListener implements PacketLoginInListener { - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start -- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); -- profile.complete(); -- i = CraftPlayerProfile.asAuthlibCopy(profile); -+ profile.complete(true); -+ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); - playerName = i.getName(); - uniqueId = i.getId(); - // Paper end -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 18b0020d184e46c8957e82100681c8c66b1c3b62..41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -162,7 +162,7 @@ public abstract class EntityHuman extends EntityLiving { - protected int bG; - protected final float bH = 0.02F; - private int g; -- private final GameProfile bJ; -+ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER - private ItemStack bL; - private final ItemCooldown bM; - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e00b33493208865c0bd1bd11a96dd2ed1348da7c..e1d1aaa278287214e2edac5f690d4f5257696ed0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -70,6 +70,7 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; - import net.minecraft.world.phys.Vec3D; -@@ -1310,8 +1311,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - hiddenPlayers.put(player.getUniqueId(), hidingPlugins); - - // Remove this player from the hidden player's EntityTrackerEntry -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ unregisterPlayer(other); -+ } -+ private void unregisterPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - PlayerChunkMap.EntityTracker entry = tracker.trackedEntities.get(other.getId()); - if (entry != null) { - entry.clear(getHandle()); -@@ -1352,8 +1358,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - hiddenPlayers.remove(player.getUniqueId()); - -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ registerPlayer(other); -+ } -+ private void registerPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - - getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); - -@@ -1362,6 +1373,50 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - entry.updatePlayer(getHandle()); - } - } -+ // Paper start -+ private void reregisterPlayer(EntityPlayer player) { -+ if (!hiddenPlayers.containsKey(player.getUniqueID())) { -+ unregisterPlayer(player); -+ registerPlayer(player); -+ } -+ } -+ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { -+ EntityPlayer self = getHandle(); -+ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); -+ if (!self.sentListPacket) { -+ return; -+ } -+ List players = server.getServer().getPlayerList().players; -+ for (EntityPlayer player : players) { -+ player.getBukkitEntity().reregisterPlayer(self); -+ } -+ refreshPlayer(); -+ } -+ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); -+ } -+ -+ private void refreshPlayer() { -+ EntityPlayer handle = getHandle(); -+ -+ Location loc = getLocation(); -+ -+ PlayerConnection connection = handle.playerConnection; -+ reregisterPlayer(handle); -+ -+ //Respawn the player then update their position and selected slot -+ WorldServer worldserver = handle.getWorldServer(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutRespawn(worldserver.getDimensionManager(), worldserver.getDimensionKey(), BiomeManager.a(worldserver.getSeed()), handle.playerInteractManager.getGameMode(), handle.playerInteractManager.c(), worldserver.isDebugWorld(), worldserver.isFlatWorld(), true)); -+ handle.updateAbilities(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); -+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().updateClient(handle); -+ -+ if (this.isOp()) { -+ this.setOp(false); -+ this.setOp(true); -+ } -+ } -+ // Paper end - - public void removeDisconnectingPlayer(Player player) { - hiddenPlayers.remove(player.getUniqueId()); diff --git a/Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch b/Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch deleted file mode 100644 index 1ec120745b07..000000000000 --- a/Spigot-Server-Patches/0200-Fix-Dragon-Server-Crashes.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Mar 2018 20:52:07 -0400 -Subject: [PATCH] Fix Dragon Server Crashes - -If the dragon tries to find "ground" and hits a hole, or off edge, -it will infinitely keep looking for non air and eventually crash. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index fbecb61b8c511fc7daa21690b2a653254be74246..5adbd9fe858aad9c775a10254eb53b34719a9bd6 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -63,7 +63,7 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - double d3 = d2; - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d2, d1); - -- while (this.a.world.isEmpty(blockposition_mutableblockposition)) { -+ while (this.a.world.isEmpty(blockposition_mutableblockposition ) && d2 > 0) { // Paper - --d3; - if (d3 < 0.0D) { - d3 = d2; diff --git a/Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch b/Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch deleted file mode 100644 index 5b2a688e7f0d..000000000000 --- a/Spigot-Server-Patches/0201-getPlayerUniqueId-API.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 22 Mar 2018 01:40:24 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -In Offline Mode, will return an Offline UUID - -This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3c019719e6eaf789bd5e20f382b707973f8b39c6..d15314af5ed58c846b97997fdfdf28786873ae01 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1519,6 +1519,25 @@ public final class CraftServer implements Server { - return recipients.size(); - } - -+ // Paper start -+ @Nullable -+ public UUID getPlayerUniqueId(String name) { -+ Player player = Bukkit.getPlayerExact(name); -+ if (player != null) { -+ return player.getUniqueId(); -+ } -+ GameProfile profile; -+ // Only fetch an online UUID in online mode -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { -+ profile = console.getUserCache().getProfile( name ); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ return profile != null ? profile.getId() : null; -+ } -+ // Paper end -+ - @Override - @Deprecated - public OfflinePlayer getOfflinePlayer(String name) { diff --git a/Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch b/Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch deleted file mode 100644 index 7a7b4d199394..000000000000 --- a/Spigot-Server-Patches/0202-Make-player-data-saving-configurable.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 26 Mar 2018 18:30:53 +0300 -Subject: [PATCH] Make player data saving configurable - -Upstream has added a patch which negates the need for this patch, -however, we should still migrate our configuration back upstream, -to prevent unexpected situations - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 52954fc3bf932cfc9d5ce63e3d3cace351305790..05a5abb951abe37f30a719cb75376d2d43c0d252 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -279,4 +279,13 @@ public class PaperConfig { - private static void authenticationServersDownKickMessage() { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } -+ -+ private static void savePlayerData() { -+ Object val = config.get("settings.save-player-data"); -+ if (val instanceof Boolean) { -+ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; -+ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); -+ SpigotConfig.save(); -+ } -+ } - } diff --git a/Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch b/Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch deleted file mode 100644 index a437521ba2ad..000000000000 --- a/Spigot-Server-Patches/0203-Make-legacy-ping-handler-more-reliable.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 18:22:50 +0200 -Subject: [PATCH] Make legacy ping handler more reliable - -The Minecraft server often fails to respond to old ("legacy") pings -from old Minecraft versions using the protocol used before the switch -to Netty in Minecraft 1.7. - -Due to packet fragmentation[1], we might not have all needed bytes -available when the LegacyPingHandler is called. In this case, it will -run into an error, remove the handler and continue using the modern -protocol. - -This is unlikely to happen for the first two revisions of the legacy -ping protocol (used in Minecraft 1.5.x and older) since the request -consists of only one or two bytes, but happens frequently for the -last/third revision introduced in Minecraft 1.6. - -It has much larger, variable packet sizes due to the inclusion of -the virtual host (the hostname/port used to connect to the server). - -The solution[2] is simple: If we find more than two matching bytes, -we buffer the remaining bytes until we have enough to fully read and -respond to the request. - -[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 -[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 - -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index e0edebf3eb93c11de2ed5c9013565950b4ad2375..0286d30b63e42224028b343315e1d1a9db2fe3d1 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -15,6 +15,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ServerConnection b; -+ private ByteBuf buf; // Paper - - public LegacyPingHandler(ServerConnection serverconnection) { - this.b = serverconnection; -@@ -23,6 +24,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { - ByteBuf bytebuf = (ByteBuf) object; - -+ // Paper start - Make legacy ping handler more reliable -+ if (this.buf != null) { -+ try { -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ } finally { -+ bytebuf.release(); -+ } -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); - boolean flag = true; - -@@ -53,6 +64,10 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - this.a(channelhandlercontext, this.a(s)); - break; - default: -+ // Paper start - Replace with improved version below -+ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ /* - boolean flag1 = bytebuf.readUnsignedByte() == 1; - - flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -76,6 +91,7 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } finally { - bytebuf1.release(); - } -+ */ // Paper end - Replace with improved version below - } - - bytebuf.release(); -@@ -93,6 +109,90 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - } - -+ // Paper start -+ private static String readLegacyString(ByteBuf buf) { -+ int size = buf.readShort() * Character.BYTES; -+ if (!buf.isReadable(size)) { -+ return null; -+ } -+ -+ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); -+ buf.skipBytes(size); // toString doesn't increase readerIndex automatically -+ return result; -+ } -+ -+ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { -+ ByteBuf buf = this.buf; -+ -+ if (buf == null) { -+ this.buf = buf = ctx.alloc().buffer(); -+ buf.markReaderIndex(); -+ } else { -+ buf.resetReaderIndex(); -+ } -+ -+ buf.writeBytes(part); -+ -+ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { -+ return; -+ } -+ -+ String s = readLegacyString(buf); -+ if (s == null) { -+ return; -+ } -+ -+ if (!s.equals("MC|PingHost")) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { -+ return; -+ } -+ -+ MinecraftServer server = this.b.d(); -+ int protocolVersion = buf.readByte(); -+ String host = readLegacyString(buf); -+ if (host == null) { -+ removeHandler(ctx); -+ return; -+ } -+ int port = buf.readInt(); -+ -+ if (buf.isReadable()) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ buf.release(); -+ this.buf = null; -+ -+ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -+ Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ this.a(ctx, this.a(response)); -+ } -+ -+ private void removeHandler(ChannelHandlerContext ctx) { -+ ByteBuf buf = this.buf; -+ this.buf = null; -+ -+ buf.resetReaderIndex(); -+ ctx.pipeline().remove(this); -+ ctx.fireChannelRead(buf); -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) { -+ if (this.buf != null) { -+ this.buf.release(); -+ this.buf = null; -+ } -+ } -+ // Paper end -+ - private void a(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { - channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); - } diff --git a/Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch b/Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch deleted file mode 100644 index 9274b7f30aaf..000000000000 --- a/Spigot-Server-Patches/0204-Call-PaperServerListPingEvent-for-legacy-pings.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:51 +0200 -Subject: [PATCH] Call PaperServerListPingEvent for legacy pings - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..74c012fd40491f1d870fbc1aa8c318a2197eb106 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang3.StringUtils; -+import org.bukkit.ChatColor; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public final class PaperLegacyStatusClient implements StatusClient { -+ -+ private final InetSocketAddress address; -+ private final int protocolVersion; -+ @Nullable private final InetSocketAddress virtualHost; -+ -+ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ this.address = address; -+ this.protocolVersion = protocolVersion; -+ this.virtualHost = virtualHost; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return this.address; -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.virtualHost; -+ } -+ -+ @Override -+ public boolean isLegacy() { -+ return true; -+ } -+ -+ public static PaperServerListPingEvent processRequest(MinecraftServer server, -+ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ -+ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, -+ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); -+ server.server.getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ return null; -+ } -+ -+ return event; -+ } -+ -+ public static String getMotd(PaperServerListPingEvent event) { -+ return getFirstLine(event.getMotd()); -+ } -+ -+ public static String getUnformattedMotd(PaperServerListPingEvent event) { -+ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) -+ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); -+ } -+ -+ private static String getFirstLine(String s) { -+ int pos = s.indexOf('\n'); -+ return pos >= 0 ? s.substring(0, pos) : s; -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index 0286d30b63e42224028b343315e1d1a9db2fe3d1..765dea6653b450802d45b76c7d2ac3d5778da9df 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -1,5 +1,7 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.network.PaperLegacyStatusClient; -+ - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; - import io.netty.channel.ChannelFutureListener; -@@ -46,12 +48,19 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - MinecraftServer minecraftserver = this.b.d(); - int i = bytebuf.readableBytes(); - String s; -- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit -+ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper - - switch (i) { - case 0: - LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(channelhandlercontext, this.a(s)); - break; - case 1: -@@ -60,7 +69,14 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } - - LegacyPingHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit -+ // Paper end - this.a(channelhandlercontext, this.a(s)); - break; - default: -@@ -170,8 +186,16 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); - -- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -- Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( -+ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); -+ if (event == null) { -+ ctx.close(); -+ return; -+ } -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), -+ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(ctx, this.a(response)); - } - diff --git a/Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch b/Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch deleted file mode 100644 index 96390756fc29..000000000000 --- a/Spigot-Server-Patches/0205-Flag-to-disable-the-channel-limit.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 31 Mar 2018 17:04:26 +0100 -Subject: [PATCH] Flag to disable the channel limit - -In some enviroments, the channel limit set by spigot can cause issues, -e.g. servers which allow and support the usage of mod packs. - -provide an optional flag to disable this check, at your own risk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e1d1aaa278287214e2edac5f690d4f5257696ed0..2abd5157b0964fc02994ca7a9317d2fb5539dc1c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -146,6 +146,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper start - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; -+ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -1579,7 +1580,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void addChannel(String channel) { -- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); -+ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit - channel = StandardMessenger.validateAndCorrectChannel(channel); - if (channels.add(channel)) { - server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch b/Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index 203a050a8249..000000000000 --- a/Spigot-Server-Patches/0206-Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:29:37 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 8661f97ac885daca068057c1fcc4eed54c6d7f14..db7ad5a94d449f58a5749115776e61f448ff2f52 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -30,6 +30,7 @@ import net.minecraft.world.level.block.BlockWorkbench; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityContainer; -+import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.state.IBlockData; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -603,6 +604,17 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start - Add method to open already placed sign -+ @Override -+ public void openSign(org.bukkit.block.Sign sign) { -+ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); -+ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; -+ TileEntitySign teSign = craftSign.getTileEntity(); -+ // Make sign editable temporarily, will be set back to false in PlayerConnection later -+ teSign.isEditable = true; -+ getHandle().openSign(teSign); -+ } -+ // Paper end - @Override - public boolean dropItem(boolean dropAll) { - return getHandle().dropItem(dropAll); diff --git a/Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch b/Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch deleted file mode 100644 index 99fb21f6e50b..000000000000 --- a/Spigot-Server-Patches/0207-Configurable-sprint-interruption-on-attack.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Sat, 14 Apr 2018 20:20:46 +0200 -Subject: [PATCH] Configurable sprint interruption on attack - -If the sprint interruption is disabled players continue sprinting when they attack entities. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 48f0385c7203c7955de5a015f3dc42be2ab7b681..cebf1a623a9bec72d60fdd23dda01868ef6431d4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -358,4 +358,9 @@ public class PaperWorldConfig { - private void squidMaxSpawnHeight() { - squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); - } -+ -+ public boolean disableSprintInterruptionOnAttack; -+ private void disableSprintInterruptionOnAttack() { -+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 41dd46c6ef95f7dc41d9ca36a5f0b85f5608fdeb..7839553662d7f1f378969d42fb7a560e489852f4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1183,7 +1183,11 @@ public abstract class EntityHuman extends EntityLiving { - } - - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); -- this.setSprinting(false); -+ // Paper start - Configuration option to disable automatic sprint interruption -+ if (!world.paperConfig.disableSprintInterruptionOnAttack) { -+ this.setSprinting(false); -+ } -+ // Paper end - } - - if (flag3) { diff --git a/Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch deleted file mode 100644 index e6e146f50dc5..000000000000 --- a/Spigot-Server-Patches/0208-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 0x22 <0x22@futureclient.net> -Date: Thu, 26 Apr 2018 04:41:11 -0400 -Subject: [PATCH] Fix exploit that allowed colored signs to be created - - -diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java -index b92975aa85fd79c70d6bec014284e8f55d0d3a4b..d5d6c545182b9b0b6aa5e52f1f9858450a17038e 100644 ---- a/src/main/java/net/minecraft/SharedConstants.java -+++ b/src/main/java/net/minecraft/SharedConstants.java -@@ -20,6 +20,7 @@ public class SharedConstants { - return c0 != 167 && c0 >= ' ' && c0 != 127; - } - -+ public static String filterAllowedChatCharacters(String input) { return a(input); } // Paper - OBFHELPER - public static String a(String s) { - StringBuilder stringbuilder = new StringBuilder(); - char[] achar = s.toCharArray(); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index fc624315b156f450c1cbc87a81e9eeff5d31b4c2..d4862a3a7f523c13c452e7b67072261556162437 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2787,7 +2787,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/0209-EndermanEscapeEvent.patch b/Spigot-Server-Patches/0209-EndermanEscapeEvent.patch deleted file mode 100644 index 428f29678a6c..000000000000 --- a/Spigot-Server-Patches/0209-EndermanEscapeEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:15:55 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 2de3210bd8988b156b756723d0f781fd92bc151a..b889c1954df39b6180351c418393f5c772702589 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster; - - import java.util.EnumSet; - import java.util.Optional; -+import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper - import java.util.Random; - import java.util.UUID; - import java.util.function.Predicate; -@@ -109,6 +110,12 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - setGoalTarget(entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); - } - -+ // Paper start -+ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { -+ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); -+ } -+ // Paper end -+ - @Override - public boolean setGoalTarget(EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { - if (!super.setGoalTarget(entityliving, reason, fireEvent)) { -@@ -262,7 +269,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.world.isDay() && this.ticksLived >= this.bs + 600) { - float f = this.aR(); - -- if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { -+ if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - this.setGoalTarget((EntityLiving) null); - this.eL(); - } -@@ -360,17 +367,19 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.isInvulnerable(damagesource)) { - return false; - } else if (damagesource instanceof EntityDamageSourceIndirect) { -+ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { - if (this.eL()) { - return true; - } - } -+ } // Paper end - - return false; - } else { - boolean flag = super.damageEntity(damagesource, f); - -- if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0) { -+ if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0 && this.tryEscape(damagesource == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 - this.eL(); - } - -@@ -515,7 +524,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - static class PathfinderGoalPlayerWhoLookedAtTarget extends PathfinderGoalNearestAttackableTarget { - -- private final EntityEnderman i; -+ private final EntityEnderman i; public final EntityEnderman getEnderman() { return this.i; } // Paper - OBFHELPER - private EntityHuman j; - private int k; - private int l; -@@ -578,7 +587,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - } else { - if (this.c != null && !this.i.isPassenger()) { - if (this.i.g((EntityHuman) this.c)) { -- if (this.c.h((Entity) this.i) < 16.0D) { -+ if (this.c.h((Entity) this.i) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper - this.i.eL(); - } - diff --git a/Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch b/Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch deleted file mode 100644 index b64598e13945..000000000000 --- a/Spigot-Server-Patches/0210-Enderman.teleportRandomly.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:44 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index b889c1954df39b6180351c418393f5c772702589..ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -278,6 +278,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - super.mobTick(); - } - -+ public final boolean teleportRandomly() { return this.eL(); } // Paper - OBFHELPER - protected boolean eL() { - if (!this.world.s_() && this.isAlive()) { - double d0 = this.locX() + (this.random.nextDouble() - 0.5D) * 64.0D; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index 8894d619796c7b81acde9ff27d0f9191122eade4..f54175a4b13ddedc475ef028942edb08eb4ff631 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -@@ -16,6 +16,7 @@ public class CraftEnderman extends CraftMonster implements Enderman { - super(server, entity); - } - -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper - @Override - public MaterialData getCarriedMaterial() { - IBlockData blockData = getHandle().getCarried(); diff --git a/Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch b/Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch deleted file mode 100644 index 38fdf2a1054b..000000000000 --- a/Spigot-Server-Patches/0211-Block-Enderpearl-Travel-Exploit.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:15:26 -0400 -Subject: [PATCH] Block Enderpearl Travel Exploit - -Players are able to use alt accounts and enderpearls to travel -long distances utilizing the pearls in unloaded chunks and loading -the chunk later when convenient. - -This disables that by not saving the thrower when the chunk is unloaded. - -This is mainly useful for survival servers that do not allow freeform teleporting. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cebf1a623a9bec72d60fdd23dda01868ef6431d4..e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -363,4 +363,10 @@ public class PaperWorldConfig { - private void disableSprintInterruptionOnAttack() { - disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); - } -+ -+ public boolean disableEnderpearlExploit = true; -+ private void disableEnderpearlExploit() { -+ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); -+ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 5c9ffd02b4f2977ee13a962a214887f74c91594f..8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -63,6 +63,7 @@ public abstract class IProjectile extends Entity { - protected void loadData(NBTTagCompound nbttagcompound) { - if (nbttagcompound.b("Owner")) { - this.shooter = nbttagcompound.a("Owner"); -+ if (this instanceof EntityEnderPearl && this.world != null && this.world.paperConfig.disableEnderpearlExploit) { this.shooter = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit - } - - this.d = nbttagcompound.getBoolean("LeftOwner"); diff --git a/Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch b/Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index da5eceecb809..000000000000 --- a/Spigot-Server-Patches/0212-Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 15 Aug 2017 22:29:12 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. -Adds an option to control the force mode of the particle. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 744ec6f09a1b3ccdf0d74fe50f1e1c913ee2df86..b73315df7dae243dd76e44d586dfc1d8f9017a56 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -170,7 +170,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); -- private final List players = Lists.newArrayList(); -+ public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; -@@ -1478,12 +1478,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper start - Particle API Expansion -+ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); -+ } -+ public int sendParticles(List receivers, EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper end - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); - // CraftBukkit end - int j = 0; - -- for (int k = 0; k < this.players.size(); ++k) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); -+ for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion -+ EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion - if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit - - if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d7d58a0feac2d0b4303c625b7952103613e8c33e..13d3b6accfb86383660a7d0e991519fd930bd518 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2352,11 +2352,17 @@ public class CraftWorld implements World { - - @Override - public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper start - Particle API Expansion -+ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); -+ } -+ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper end - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } - getHandle().sendParticles( -- null, // Sender -+ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion -+ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion - CraftParticle.toNMS(particle, data), // Particle - x, y, z, // Position - count, // Count diff --git a/Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch b/Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch deleted file mode 100644 index 08c3406719f0..000000000000 --- a/Spigot-Server-Patches/0213-EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:18:54 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index ef2f0211cd4d20dad0d3757c38c3c2882e99b2f2..aa6cb15637144c9d8db1b1861e58f3f02d68357a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -221,7 +221,15 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - this.a((WorldServer) this.world, nbttagcompound); - } - -+ // Paper start - OBFHELPER - ok not really, but verify this on updates - private boolean g(EntityHuman entityhuman) { -+ boolean shouldAttack = g_real(entityhuman); -+ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) entityhuman.getBukkitEntity()); -+ event.setCancelled(!shouldAttack); -+ return event.callEvent(); -+ } -+ private boolean g_real(EntityHuman entityhuman) { -+ // Paper end - ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); - - if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.getItem()) { diff --git a/Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch b/Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch deleted file mode 100644 index 4c8539424474..000000000000 --- a/Spigot-Server-Patches/0214-WitchConsumePotionEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:35:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 814ef118e983ee6807108b2e07cd9b35ef9dae15..0bfdcbe4a792e8243de86ded6c64d930ec6e4de8 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -124,7 +124,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - if (itemstack.getItem() == Items.POTION) { -- List list = PotionUtil.getEffects(itemstack); -+ // Paper start -+ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); -+ -+ List list = event.callEvent() ? PotionUtil.getEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; -+ // Paper end - - if (list != null) { - Iterator iterator = list.iterator(); diff --git a/Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch b/Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch deleted file mode 100644 index a9232360d458..000000000000 --- a/Spigot-Server-Patches/0215-WitchThrowPotionEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:44:58 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0bfdcbe4a792e8243de86ded6c64d930ec6e4de8..2e65f6107ffecfe00c9c09baa60dec3021aac527 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -224,9 +224,16 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - potionregistry = Potions.WEAKNESS; - } - -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry); -+ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ if (!event.callEvent()) { -+ return; -+ } -+ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); - EntityPotion entitypotion = new EntityPotion(this.world, this); -- -- entitypotion.setItem(PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry)); -+ entitypotion.setItem(potion); -+ // Paper end - entitypotion.pitch -= -20.0F; - entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); - if (!this.isSilent()) { diff --git a/Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch deleted file mode 100644 index e6991dda173a..000000000000 --- a/Spigot-Server-Patches/0216-Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Jun 2018 20:39:20 -0400 -Subject: [PATCH] Allow spawning Item entities with World.spawnEntity - -This API has more capabilities than .dropItem with the Consumer function - -Item can be set inside of the Consumer pre spawn function. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 13d3b6accfb86383660a7d0e991519fd930bd518..2cc25177110d669e0f425668e26a38794c11c101 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1515,6 +1515,10 @@ public class CraftWorld implements World { - if (Boat.class.isAssignableFrom(clazz)) { - entity = new EntityBoat(world, x, y, z); - entity.setPositionRotation(x, y, z, yaw, pitch); -+ // Paper start -+ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { -+ entity = new EntityItem(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.getItemOf(net.minecraft.world.level.block.Blocks.DIRT))); -+ // Paper end - } else if (FallingBlock.class.isAssignableFrom(clazz)) { - entity = new EntityFallingBlock(world, x, y, z, world.getType(new BlockPosition(x, y, z))); - } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch b/Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch deleted file mode 100644 index 379b2c175105..000000000000 --- a/Spigot-Server-Patches/0217-WitchReadyPotionEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:26 -0400 -Subject: [PATCH] WitchReadyPotionEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 2e65f6107ffecfe00c9c09baa60dec3021aac527..c6d79125e7dd982fc528ce61144005194cbaa323 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -157,7 +157,11 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- this.setSlot(EnumItemSlot.MAINHAND, PotionUtil.a(new ItemStack(Items.POTION), potionregistry)); -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end - this.bq = this.getItemInMainHand().k(); - this.v(true); - if (!this.isSilent()) { diff --git a/Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch b/Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index e22c07338a49..000000000000 --- a/Spigot-Server-Patches/0218-ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 23:00:29 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index cac92ccacc9d5ff17c70ee266cf12bacce6242ea..2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -606,6 +606,7 @@ public final class ItemStack { - this.getItem().b(this, world, entityhuman); - } - -+ public int getItemUseMaxDuration() { return k(); } // Paper - OBFHELPER - public int k() { - return this.getItem().e_(this); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 7221ac52c9f66ae0af6f6cbf15c8d47f9c0291a0..315addab147dfecf4aa88d32d154cefe850d0a78 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -174,6 +174,13 @@ public final class CraftItemStack extends ItemStack { - return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); - } - -+ // Paper start -+ @Override -+ public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); -+ } -+ // Paper end -+ - @Override - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index 188e40842328..000000000000 --- a/Spigot-Server-Patches/0219-Implement-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 14:08:39 +0200 -Subject: [PATCH] Implement EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 2808cd0b100bd65a730aba315ab47a59a4621b30..b7548d0b3938d95328fc86db4000190532eaa8f5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -194,9 +194,20 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - - } - // CraftBukkit end -+ // Paper start - EntityTeleportEndGatewayEvent - replicated from above -+ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); -+ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ location.setPitch(bukkitEntity.getLocation().getPitch()); -+ location.setYaw(bukkitEntity.getLocation().getYaw()); -+ -+ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - - entity1.resetPortalCooldown(); -- entity1.enderTeleportAndLoad((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); -+ entity1.enderTeleportAndLoad(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper - } - - this.h(); diff --git a/Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch deleted file mode 100644 index 72ccc51e069d..000000000000 --- a/Spigot-Server-Patches/0220-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 01:18:49 -0400 -Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event - -Otherwise the creeper infinite explodes - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 08292753f925f33d75f3aca835c1fd19494b22ec..cbb973e077e04e5221bcc837f434b7093bdbcc2a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -48,7 +48,7 @@ public class EntityCreeper extends EntityMonster { - - private static final DataWatcherObject b = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.b); - private static final DataWatcherObject POWERED = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -- private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -+ private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); private static final DataWatcherObject isIgnitedDW = d; // Paper OBFHELPER - private int bo; - public int fuseTicks; // PAIL - public int maxFuseTicks = 30; -@@ -253,6 +253,7 @@ public class EntityCreeper extends EntityMonster { - this.createEffectCloud(); - } else { - fuseTicks = 0; -+ this.datawatcher.set(isIgnitedDW, Boolean.valueOf(false)); // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch b/Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch deleted file mode 100644 index bb0a09f3ce7e..000000000000 --- a/Spigot-Server-Patches/0221-Fix-CraftEntity-hashCode.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 20:20:15 -0400 -Subject: [PATCH] Fix CraftEntity hashCode - -hashCodes are not allowed to change, however bukkit used a value -that does change, the entityId. - -When an entity is teleported dimensions, the entity reference is -replaced with a new one with a new entity ID. - -For hashCode, we can simply use the UUID's hashCode to keep -the hashCode from changing. - -equals() is ok to use getEntityId() because equals() should only -be true if both the left and right are the same reference. - -Since entity ids can not duplicate during runtime, this -check is essentially the same as this.getHandle() == other.getHandle() - -However, replaced it too to make it clearer of intent. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 4c2a35fb33da19a15a220dc5e0c9fa3233d657fb..3642b17cafffd2818ee7a18d26bc25645f596115 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -745,14 +745,15 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return false; - } - final CraftEntity other = (CraftEntity) obj; -- return (this.getEntityId() == other.getEntityId()); -+ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer - } - -+ // Paper - Fix hashCode. entity ID's are not static. -+ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change - @Override - public int hashCode() { -- int hash = 7; -- hash = 29 * hash + this.getEntityId(); -- return hash; -+ return getUniqueId().hashCode(); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch b/Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch deleted file mode 100644 index e0ee8431f3a7..000000000000 --- a/Spigot-Server-Patches/0222-Configurable-Alternative-LootPool-Luck-Formula.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 00:30:32 -0400 -Subject: [PATCH] Configurable Alternative LootPool Luck Formula - -Rewrites the Vanilla luck application formula so that luck can be -applied to items that do not have any quality defined. - -See: https://luckformula.emc.gs for data and details ------------ - -The rough summary is: -My goal was that in a pool, when luck was applied, the pool -rebalances so the percentages for bigger items is -lowered and smaller items is boosted. - -Do this by boosting and then reducing the weight value, -so that larger numbers are penalized more than smaller numbers. -resulting in a larger reduction of entries for more common -items than the reduction on small weights, -giving smaller weights more of a chance - ------------ - -This work kind of obsoletes quality, but quality would be useful -for 2 items with same weight that you want luck to impact -in varying directions. - -Fishing still falls into that as the weights are closer, so luck -will invalidate junk more. - -This change will result in some major changes to fishing formulas. - ------------ - -I would love to see this change in Vanilla, so Mojang please pull :) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 05a5abb951abe37f30a719cb75376d2d43c0d252..77a03abd59db4a43f6f2d59d4c7ef176e782f205 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -288,4 +288,12 @@ public class PaperConfig { - SpigotConfig.save(); - } - } -+ -+ public static boolean useAlternativeLuckFormula = false; -+ private static void useAlternativeLuckFormula() { -+ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); -+ if (useAlternativeLuckFormula) { -+ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index ceb9a1e1b1d55a0a8cd74189450f356b9ad4c46c..632002c4db01ca3f3c19aa583226cf36f17afe7f 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -20,8 +20,8 @@ import org.apache.commons.lang3.ArrayUtils; - - public abstract class LootSelectorEntry extends LootEntryAbstract { - -- protected final int c; -- protected final int e; -+ protected final int c; public int getWeight() { return c; } // Paper - OBFHELPER -+ protected final int e; public int getQuality() { return e; } // Paper - OBFHELPER - protected final LootItemFunction[] f; - private final BiFunction g; - private final LootEntry h = new LootSelectorEntry.c() { -@@ -152,11 +152,38 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public abstract class c implements LootEntry { - -- protected c() {} -+ protected c() { -+ } - - @Override - public int a(float f) { -- return Math.max(MathHelper.d((float) LootSelectorEntry.this.c + (float) LootSelectorEntry.this.e * f), 0); -+ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies -+ // SEE: https://luckformula.emc.gs for details and data -+ if (lastLuck != null && lastLuck == f) { -+ return lastWeight; -+ } -+ // This is vanilla -+ float qualityModifer = (float) getQuality() * f; -+ double baseWeight = (getWeight() + qualityModifer); -+ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { -+ // Random boost to avoid losing precision in the final int cast on return -+ final int weightBoost = 100; -+ baseWeight *= weightBoost; -+ // If we have vanilla 1, bump that down to 0 so nothing is is impacted -+ // vanilla 3 = 300, 200 basis = impact 2% -+ // =($B2*(($B2-100)/100/100)) -+ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); -+ // =($B$7/100) -+ float luckModifier = Math.min(100, f * 10) / 100; -+ // =B2 - (C2 *($B$7/100)) -+ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); -+ } -+ lastLuck = f; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); -+ return lastWeight; - } - } -+ private Float lastLuck = null; -+ private int lastWeight = 0; -+ // Paper end - } diff --git a/Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch b/Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch deleted file mode 100644 index de373f15f090..000000000000 --- a/Spigot-Server-Patches/0223-Print-Error-details-when-failing-to-save-player-data.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 20:37:03 -0400 -Subject: [PATCH] Print Error details when failing to save player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index 191c9e9a00b9871038f60d54bc22620322f6bdbd..4d30ca69dd303f1d76c8e6292021deda97851773 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -43,7 +43,7 @@ public class WorldNBTStorage { - - SystemUtils.a(file1, file, file2); - } catch (Exception exception) { -- WorldNBTStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getDisplayName().getString()); -+ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper - } - - } diff --git a/Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch b/Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch deleted file mode 100644 index a569f09272e6..000000000000 --- a/Spigot-Server-Patches/0224-Make-shield-blocking-delay-configurable.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 16 Jun 2018 01:18:16 -0500 -Subject: [PATCH] Make shield blocking delay configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e8e1e7dafaf1c105b2f58cf3e118e3d665dc50ec..3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -369,4 +369,9 @@ public class PaperWorldConfig { - disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); - log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); - } -+ -+ public int shieldBlockingDelay = 5; -+ private void shieldBlockingDelay() { -+ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 8a43a85a728c15dbc0fdd2fc8dc5dfff9a589358..d4ffff5ecb24af8439e5bfaa02e8136a10fdde90 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3311,7 +3311,7 @@ public abstract class EntityLiving extends Entity { - if (this.isHandRaised() && !this.activeItem.isEmpty()) { - Item item = this.activeItem.getItem(); - -- return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= 5; -+ return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay - } else { - return false; - } -@@ -3567,4 +3567,15 @@ public abstract class EntityLiving extends Entity { - public void broadcastItemBreak(EnumHand enumhand) { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } -+ // Paper start -+ public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; -+ -+ public int getShieldBlockingDelay() { -+ return shieldBlockingDelay; -+ } -+ -+ public void setShieldBlockingDelay(int shieldBlockingDelay) { -+ this.shieldBlockingDelay = shieldBlockingDelay; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c43c300963bae9bca6ab9c9389dd53e42318715c..2d1c54eed8fa6885837d63014ff1f4b33dd35bd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -711,5 +711,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setArrowsStuck(int arrows) { - getHandle().setArrowCount(arrows); - } -+ -+ @Override -+ public int getShieldBlockingDelay() { -+ return getHandle().getShieldBlockingDelay(); -+ } -+ -+ @Override -+ public void setShieldBlockingDelay(int delay) { -+ getHandle().setShieldBlockingDelay(delay); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch b/Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch deleted file mode 100644 index 4d145bf944a5..000000000000 --- a/Spigot-Server-Patches/0225-Improve-EntityShootBowEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:51:17 -0400 -Subject: [PATCH] Improve EntityShootBowEvent - -Adds missing call to Illagers and also adds Arrow ItemStack to skeltons - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -index 54a4a295660375a0fcc54e02d80d569d9a32e73e..fee9a5140f097225b5da58b18bfbd528dffdc77b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -@@ -171,8 +171,18 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - double d3 = (double) MathHelper.sqrt(d0 * d0 + d2 * d2); - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); -+ // Paper start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, entityliving.getRaisedHand(), 0.8F, true); -+ if (event.isCancelled()) { -+ event.getProjectile().remove(); -+ return; -+ } -+ -+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { -+ this.world.addEntity(entityarrow); -+ } - this.playSound(SoundEffects.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); -- this.world.addEntity(entityarrow); -+ // Paper end - } - - class a extends EntityIllagerWizard.PathfinderGoalCastSpell { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index a2a67bccf38464731670e98cb155348df94474c5..4dca5ea9127c15b2739483b2ad74a5296a6b96ad 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -197,7 +197,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); - // CraftBukkit start -- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { - event.getProjectile().remove(); - return; diff --git a/Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch b/Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch deleted file mode 100644 index 48c889f7190b..000000000000 --- a/Spigot-Server-Patches/0226-PlayerReadyArrowEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 18 Jun 2018 01:12:53 -0400 -Subject: [PATCH] PlayerReadyArrowEvent - -Called when a player is firing a bow and the server is choosing an arrow to use. -Plugins can skip selection of certain arrows and control which is used. - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 7839553662d7f1f378969d42fb7a560e489852f4..408732c59ed817c056671a78e43a734b048a818e 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2142,6 +2142,17 @@ public abstract class EntityHuman extends EntityLiving { - return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); - } - -+ // Paper start -+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { -+ return !(this instanceof EntityPlayer) || -+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( -+ ((EntityPlayer) this).getBukkitEntity(), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) -+ ).callEvent(); -+ // Paper end -+ } -+ - @Override - public ItemStack f(ItemStack itemstack) { - if (!(itemstack.getItem() instanceof ItemProjectileWeapon)) { -@@ -2158,7 +2169,7 @@ public abstract class EntityHuman extends EntityLiving { - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack2 = this.inventory.getItem(i); - -- if (predicate.test(itemstack2)) { -+ if (predicate.test(itemstack2) && tryReadyArrow(itemstack, itemstack2)) { // Paper - return itemstack2; - } - } diff --git a/Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch b/Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index b18f3dbaa798..000000000000 --- a/Spigot-Server-Patches/0227-Implement-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:46:23 +0200 -Subject: [PATCH] Implement EntityKnockbackByEntityEvent - -This event is called when an entity receives knockback by another entity. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index c22b5f8fcdd4aa7dac242f634ef73edcd8745fc6..41566398f5eee6cf93376f2e2200728bb6d2181c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -1568,7 +1568,7 @@ public abstract class EntityInsentient extends EntityLiving { - - if (flag) { - if (f1 > 0.0F && entity instanceof EntityLiving) { -- ((EntityLiving) entity).a(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index d4ffff5ecb24af8439e5bfaa02e8136a10fdde90..4798eac1498ebeecf0476a61a093d3871c00d5a5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1339,7 +1339,7 @@ public abstract class EntityLiving extends Entity { - } - - this.ap = (float) (MathHelper.d(d1, d0) * 57.2957763671875D - (double) this.yaw); -- this.a(0.4F, d0, d1); -+ this.doKnockback(0.4F, d0, d1, entity1); // Paper - } else { - this.ap = (float) ((int) (Math.random() * 2.0D) * 180); - } -@@ -1387,7 +1387,7 @@ public abstract class EntityLiving extends Entity { - } - - protected void e(EntityLiving entityliving) { -- entityliving.a(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ()); -+ entityliving.doKnockback(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ(), this); // Paper - } - - private boolean f(DamageSource damagesource) { -@@ -1630,6 +1630,11 @@ public abstract class EntityLiving extends Entity { - } - - public void a(float f, double d0, double d1) { -+ // Paper start - add knockbacking entity parameter -+ this.doKnockback(f, d0, d1, null); -+ } -+ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { -+ // Paper end - add knockbacking entity parameter - f = (float) ((double) f * (1.0D - this.b(GenericAttributes.KNOCKBACK_RESISTANCE))); - if (f > 0.0F) { - this.impulse = true; -@@ -1637,6 +1642,16 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d1 = (new Vec3D(d0, 0.0D, d1)).d().a((double) f); - - this.setMot(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); -+ -+ // Paper start - call EntityKnockbackByEntityEvent -+ Vec3D currentMot = this.getMot(); -+ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); -+ // Restore old velocity to be able to access it in the event -+ this.setMot(vec3d); -+ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { -+ this.setMot(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); -+ } -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 408732c59ed817c056671a78e43a734b048a818e..3c49d7acd4ad0717886adf6c469e8a49a58e859b 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1177,7 +1177,7 @@ public abstract class EntityHuman extends EntityLiving { - if (flag5) { - if (i > 0) { - if (entity instanceof EntityLiving) { -- ((EntityLiving) entity).a((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } else { - entity.i((double) (-MathHelper.sin(this.yaw * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (MathHelper.cos(this.yaw * 0.017453292F) * (float) i * 0.5F)); - } -@@ -1201,7 +1201,7 @@ public abstract class EntityHuman extends EntityLiving { - if (entityliving != this && entityliving != entity && !this.r(entityliving) && (!(entityliving instanceof EntityArmorStand) || !((EntityArmorStand) entityliving).isMarker()) && this.h((Entity) entityliving) < 9.0D) { - // CraftBukkit start - Only apply knockback if the damage hits - if (entityliving.damageEntity(DamageSource.playerAttack(this).sweep(), f4)) { -- entityliving.a(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ entityliving.doKnockback(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0228-Expand-Explosions-API.patch b/Spigot-Server-Patches/0228-Expand-Explosions-API.patch deleted file mode 100644 index 2dcb0871e704..000000000000 --- a/Spigot-Server-Patches/0228-Expand-Explosions-API.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Jun 2018 23:17:24 -0400 -Subject: [PATCH] Expand Explosions API - -Add Entity as a Source capability, and add more API choices, and on Location. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2cc25177110d669e0f425668e26a38794c11c101..1fce5548544f00fd79839a23e05ec5690f6f0621 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -889,6 +889,11 @@ public class CraftWorld implements World { - public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { - return !world.createExplosion(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; - } -+ // Paper start -+ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { -+ return !world.createExplosion(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; -+ } -+ // Paper end - - @Override - public boolean createExplosion(Location loc, float power) { diff --git a/Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch b/Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 4f4303b92cf5..000000000000 --- a/Spigot-Server-Patches/0229-LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:21:28 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 4798eac1498ebeecf0476a61a093d3871c00d5a5..2b10ae84ee8e9f63382d732e8c051fc47f0c5d9f 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -212,7 +212,7 @@ public abstract class EntityLiving extends Entity { - private float bu; - private int jumpTicks; - private float bw; -- protected ItemStack activeItem; -+ public ItemStack activeItem; // Paper - public - protected int bd; - protected int be; - private BlockPosition bx; -@@ -3294,10 +3294,12 @@ public abstract class EntityLiving extends Entity { - return this.activeItem; - } - -+ public int getItemUseRemainingTime() { return this.dZ(); } // Paper - OBFHELPER - public int dZ() { - return this.bd; - } - -+ public int getHandRaisedTime() { return this.ea(); } // Paper - OBFHELPER - public int ea() { - return this.isHandRaised() ? this.activeItem.k() - this.dZ() : 0; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 2d1c54eed8fa6885837d63014ff1f4b33dd35bd7..bd24b9865f37c34ffd63cd411ddc84abe5ab30d0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -721,5 +721,25 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setShieldBlockingDelay(int delay) { - getHandle().setShieldBlockingDelay(delay); - } -+ -+ @Override -+ public ItemStack getActiveItem() { -+ return getHandle().activeItem.asBukkitMirror(); -+ } -+ -+ @Override -+ public int getItemUseRemainingTime() { -+ return getHandle().getItemUseRemainingTime(); -+ } -+ -+ @Override -+ public int getHandRaisedTime() { -+ return getHandle().getHandRaisedTime(); -+ } -+ -+ @Override -+ public boolean isHandRaised() { -+ return getHandle().isHandRaised(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0230-RangedEntity-API.patch b/Spigot-Server-Patches/0230-RangedEntity-API.patch deleted file mode 100644 index e0765e9b6961..000000000000 --- a/Spigot-Server-Patches/0230-RangedEntity-API.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 26 Jun 2018 22:00:49 -0400 -Subject: [PATCH] RangedEntity API - -Allows you to determine if an entity is capable of ranged attacks, -and to perform an attack. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0195d4036f06db0f3f56f134dbfbc4360d44ed86 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -@@ -0,0 +1,19 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.monster.IRangedEntity; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+ -+public interface CraftRangedEntity extends RangedEntity { -+ T getHandle(); -+ -+ @Override -+ default void rangedAttack(LivingEntity target, float charge) { -+ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); -+ } -+ -+ @Override -+ default void setChargingAttack(boolean raiseHands) { -+ getHandle().setChargingAttack(raiseHands); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -index d79e6b28c77edc468c6471d909306c2135b496c7..0f0aaa8a15301dea8405e26333d30b385831506c 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -+++ b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -@@ -4,5 +4,8 @@ import net.minecraft.world.entity.EntityLiving; - - public interface IRangedEntity { - -- void a(EntityLiving entityliving, float f); -+ void a(EntityLiving entityliving, float f); default void rangedAttack(EntityLiving entityliving, float f) { a(entityliving, f); } // Paper - OBFHELPER -+ -+ // - see EntitySkeletonAbstract melee goal -+ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -index 3bb39dae11847bea1330ef68f53c90309fd2a095..bba2e3fba5b225e90744e78df085b3c318a029ce 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.Drowned; - import org.bukkit.entity.EntityType; - --public class CraftDrowned extends CraftZombie implements Drowned { -+public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftDrowned(CraftServer server, EntityDrowned entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -index 0dabb012b37b6dda58368765b220b7d0aaf8e2d4..3763fb13920c98bb7cd250883ec89cdd1805dbd6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Illusioner; - --public class CraftIllusioner extends CraftSpellcaster implements Illusioner { -+public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftIllusioner(CraftServer server, EntityIllagerIllusioner entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 6dcf196fd83f2175a5d34c8d138d923c32ddb899..818034c62893a71808e3af0aa33393605611acdd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.entity.CraftRangedEntity; - import com.google.common.base.Preconditions; - import net.minecraft.world.entity.animal.horse.EntityLlama; - import org.bukkit.craftbukkit.CraftServer; -@@ -10,7 +11,7 @@ import org.bukkit.entity.Llama; - import org.bukkit.entity.Llama.Color; - import org.bukkit.inventory.LlamaInventory; - --public class CraftLlama extends CraftChestedHorse implements Llama { -+public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper - - public CraftLlama(CraftServer server, EntityLlama entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index a224ebf16834fa10e169fa3239d89b1e60673dbb..b3b5d3a7f8ed522680f764cfd20d1e5c69627804 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Piglin; - --public class CraftPiglin extends CraftPiglinAbstract implements Piglin { -+public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPiglin(CraftServer server, EntityPiglin entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index 72ac9eae71028a40541f949d617ce326c00c6369..87eeb5b632b581dca7613973bc9a25f152839a33 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -@@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Pillager; - import org.bukkit.inventory.Inventory; - --public class CraftPillager extends CraftIllager implements Pillager { -+public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPillager(CraftServer server, EntityPillager entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index cebb90fd4a84c0a97d7493a6923d16d0c4215f5e..c2acfa2cc27a187154e17b7f45908682b41b52af 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Skeleton; - import org.bukkit.entity.Skeleton.SkeletonType; - --public class CraftSkeleton extends CraftMonster implements Skeleton { -+public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index 5720bdf64eadec1ebe1a2253e2b537ca299ffa6d..a262cf88eefca2767eb6e5da856626be34352ccd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Snowman; - --public class CraftSnowman extends CraftGolem implements Snowman { -+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSnowman(CraftServer server, EntitySnowman entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 796bd26d41b52941c38d81411688116af7053535..9cc34cdb43596eff34625045f884b93da3f27ab6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; - --public class CraftWitch extends CraftRaider implements Witch { -+public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 7150702d8dac0d9db44661b1b17f520302988b45..1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Wither; - --public class CraftWither extends CraftMonster implements Wither { -+public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - private BossBar bossBar; - diff --git a/Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch b/Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch deleted file mode 100644 index 153410f43a21..000000000000 --- a/Spigot-Server-Patches/0231-Add-config-to-disable-ender-dragon-legacy-check.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 22 Jun 2018 10:38:31 -0500 -Subject: [PATCH] Add config to disable ender dragon legacy check - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3e4bd1d6718d3ad2498fe9bd72eaac45044ecb77..4813f62d1e382d5ac6971b2244df3f13c80d1950 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -374,4 +374,9 @@ public class PaperWorldConfig { - private void shieldBlockingDelay() { - shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); - } -+ -+ public boolean scanForLegacyEnderDragon = true; -+ private void scanForLegacyEnderDragon() { -+ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index f727cc456bd23816c4e70be83c395d1d8ca7d876..0869af4670f040344f5b6c2c10bff5e5226f707c 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -73,7 +73,7 @@ public class EnderDragonBattle { - private boolean dragonKilled; - private boolean previouslyKilled; - public UUID dragonUUID; -- private boolean n; -+ private boolean n; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.n = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.n; } // Paper - OBFHELPER - public BlockPosition exitPortalLocation; - public EnumDragonRespawn respawnPhase; - private int q; -@@ -83,6 +83,10 @@ public class EnderDragonBattle { - this.bossBattle = (BossBattleServer) (new BossBattleServer(new ChatMessage("entity.minecraft.ender_dragon"), BossBattle.BarColor.PINK, BossBattle.BarStyle.PROGRESS)).setPlayMusic(true).c(true); - this.gateways = Lists.newArrayList(); - this.n = true; -+ // Paper start -+ setScanForLegacyFight(worldserver.paperConfig.scanForLegacyEnderDragon); -+ if (!scanForLegacyFight()) dragonKilled = true; -+ // Paper end - this.world = worldserver; - if (nbttagcompound.hasKeyOfType("DragonKilled", 99)) { - if (nbttagcompound.b("Dragon")) { diff --git a/Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch b/Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch deleted file mode 100644 index 8856ce729b3a..000000000000 --- a/Spigot-Server-Patches/0232-Implement-World.getEntity-UUID-API.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 3 Jul 2018 16:08:14 +0200 -Subject: [PATCH] Implement World.getEntity(UUID) API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1fce5548544f00fd79839a23e05ec5690f6f0621..a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1304,6 +1304,15 @@ public class CraftWorld implements World { - return list; - } - -+ // Paper start - getEntity by UUID API -+ @Override -+ public Entity getEntity(UUID uuid) { -+ Validate.notNull(uuid, "UUID cannot be null"); -+ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); -+ return entity == null ? null : entity.getBukkitEntity(); -+ } -+ // Paper end -+ - @Override - public void save() { - org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch b/Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch deleted file mode 100644 index 8caa3f043e16..000000000000 --- a/Spigot-Server-Patches/0233-InventoryCloseEvent-Reason-API.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 3 Jul 2018 21:56:23 -0400 -Subject: [PATCH] InventoryCloseEvent Reason API - -Allows you to determine why an inventory was closed, enabling plugin developers -to "confirm" things based on if it was player triggered close or not. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index de7167ddf7b36ef266e511187789f99244401c21..b581a6d3ec06498a4c6db92eb50c5d2b28038131 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -547,7 +547,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -720,7 +720,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper - } - - net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure -@@ -1293,7 +1293,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return OptionalInt.empty(); - } else { - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - this.nextContainerCounter(); -@@ -1353,7 +1353,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - // this.nextContainerCounter(); // CraftBukkit - moved up -@@ -1417,7 +1417,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void closeInventory() { -- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit -+ // Paper start -+ closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit -+ // Paper end - this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); - this.o(); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index b73315df7dae243dd76e44d586dfc1d8f9017a56..eb19b6fc87bfd4e500ea7836c1010a80b36abab2 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1125,7 +1125,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - for (TileEntity tileentity : chunk.getTileEntities().values()) { - if (tileentity instanceof net.minecraft.world.IInventory) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.IInventory) tileentity).getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } -@@ -1183,7 +1183,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // Spigot Start - if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - // Spigot End -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d4862a3a7f523c13c452e7b67072261556162437..5c637fc653482e931fa6d0f5d0394d0b923b5ff8 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -190,6 +190,7 @@ import org.bukkit.event.inventory.ClickType; - import org.bukkit.event.inventory.CraftItemEvent; - import org.bukkit.event.inventory.InventoryAction; - import org.bukkit.event.inventory.InventoryClickEvent; -+import org.bukkit.event.inventory.InventoryCloseEvent; // Paper - import org.bukkit.event.inventory.InventoryCreativeEvent; - import org.bukkit.event.inventory.InventoryType.SlotType; - import org.bukkit.event.inventory.SmithItemEvent; -@@ -2310,10 +2311,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInCloseWindow packetplayinclosewindow) { -+ // Paper start -+ handleContainerClose(packetplayinclosewindow, InventoryCloseEvent.Reason.PLAYER); -+ } -+ public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow, InventoryCloseEvent.Reason reason) { -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); - - if (this.player.isFrozen()) return; // CraftBukkit -- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit -+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper - - this.player.o(); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index bd8bcc3891b29d31742bcfd6080a3972e4a9bee7..80934fc662b33b1c88dd7a3033792d612a7c7930 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -494,7 +494,7 @@ public abstract class PlayerList { - // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it - // See SPIGOT-5799, SPIGOT-6145 - if (entityplayer.activeContainer != entityplayer.defaultContainer) { -- entityplayer.closeInventory(); -+ entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3c49d7acd4ad0717886adf6c469e8a49a58e859b..b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -252,7 +252,7 @@ public abstract class EntityHuman extends EntityLiving { - this.et(); - super.tick(); - if (!this.world.isClientSide && this.activeContainer != null && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -447,6 +447,13 @@ public abstract class EntityHuman extends EntityLiving { - return 20; - } - -+ // Paper start - unused code, but to keep signatures aligned -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ closeInventory(); -+ this.activeContainer = this.defaultContainer; -+ } -+ // Paper end -+ - public void closeInventory() { - this.activeContainer = this.defaultContainer; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index db7ad5a94d449f58a5749115776e61f448ff2f52..e8f8a07f256e01c5792199bf47f3cc1f0f3d1610 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -373,7 +373,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (((EntityPlayer) getHandle()).playerConnection == null) return; - if (getHandle().activeContainer != getHandle().defaultContainer) { - // fire INVENTORY_CLOSE if one already open -- ((EntityPlayer) getHandle()).playerConnection.a(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId)); -+ ((EntityPlayer) getHandle()).playerConnection.handleContainerClose(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - EntityPlayer player = (EntityPlayer) getHandle(); - Container container; -@@ -443,8 +443,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - @Override - public void closeInventory() { -- getHandle().closeInventory(); -+ // Paper start -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); - } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ getHandle().closeInventory(reason); -+ } -+ // Paper end - - @Override - public boolean isBlocking() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 2abd5157b0964fc02994ca7a9317d2fb5539dc1c..ee3fbf0789b4841a113727397ba6809b2600ff83 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -898,7 +898,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - // Close any foreign inventory - if (getHandle().activeContainer != getHandle().defaultContainer) { -- getHandle().closeInventory(); -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - } - - // Check if the fromWorld and toWorld are the same. -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index e068896b1b8aab8bba8acd641bf0479c89ad3321..69bcd6dcfc62ab7b5666b8e185efa07a9adbc179 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1184,7 +1184,7 @@ public class CraftEventFactory { - - public static Container callInventoryOpenEvent(EntityPlayer player, Container container, boolean cancelled) { - if (player.activeContainer != player.defaultContainer) { // fire INVENTORY_CLOSE if one already open -- player.playerConnection.a(new PacketPlayInCloseWindow(player.activeContainer.windowId)); -+ player.playerConnection.handleContainerClose(new PacketPlayInCloseWindow(player.activeContainer.windowId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - CraftServer server = player.world.getServer(); -@@ -1350,8 +1350,18 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ /** -+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason -+ * @param human -+ */ -+ @Deprecated - public static void handleInventoryCloseEvent(EntityHuman human) { -- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView()); -+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public static void handleInventoryCloseEvent(EntityHuman human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // Paper end -+ InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView(), reason); // Paper - human.world.getServer().getPluginManager().callEvent(event); - human.activeContainer.transferTo(human.defaultContainer, human.getBukkitEntity()); - } diff --git a/Spigot-Server-Patches/0234-Vex-getSummoner-API.patch b/Spigot-Server-Patches/0234-Vex-getSummoner-API.patch deleted file mode 100644 index c70d5e9bb31f..000000000000 --- a/Spigot-Server-Patches/0234-Vex-getSummoner-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 15:30:22 -0400 -Subject: [PATCH] Vex#getSummoner API - -Get's the NPC that summoned this Vex - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 3acf36a500424808cd91dc607df1ffbe23720c16..3b74ade60b3b0ae0e908866cb4ac11acd75620ff 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -124,6 +124,7 @@ public class EntityVex extends EntityMonster { - - } - -+ public EntityInsentient getOwner() { return eK(); } // Paper - OBFHELPER - public EntityInsentient eK() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index ccaccffbf5eb18108760d1da09c4c1b2f33ebc42..962d6017f6acc47ebe4b754ccd9b97a1fc97cc58 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -16,6 +16,13 @@ public class CraftVex extends CraftMonster implements Vex { - return (EntityVex) super.getHandle(); - } - -+ // Paper start -+ public org.bukkit.entity.Mob getSummoner() { -+ net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); -+ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; -+ } -+ // Paper end -+ - @Override - public String toString() { - return "CraftVex"; diff --git a/Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch deleted file mode 100644 index 619604e5afcd..000000000000 --- a/Spigot-Server-Patches/0235-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 13 Jul 2018 14:54:43 +0200 -Subject: [PATCH] Refresh player inventory when cancelling - PlayerInteractEntityEvent - -When interacting with entities with an item, the client will assume -the interaction is successful, and update the held item on the -client. However, if the interaction is cancelled on the server side, -the client will still mistakenly remove/replace the item in hand. - -Examples for this are milking cows with a bucket or dyeing sheep. -The bucket is replaced with milk and the dye removed from inventory. - -Refresh the player inventory when PlayerInteractEntityEvent is -cancelled to avoid this problem. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 5c637fc653482e931fa6d0f5d0394d0b923b5ff8..19763a27ad54866b7d1f6e2cfccd6bbe6e54637e 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2223,6 +2223,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (event.isCancelled()) { -+ this.player.updateInventory(this.player.activeContainer); // Paper - Refresh player inventory - return; - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch b/Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch deleted file mode 100644 index 7640438b07fd..000000000000 --- a/Spigot-Server-Patches/0236-Don-t-change-the-Entity-Random-seed-for-squids.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:05:00 -0400 -Subject: [PATCH] Don't change the Entity Random seed for squids - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 7ce5e2597b34d3a4d2a79d73c15e893c064fc88c..1f5f3e0d209426b97e32b82dd15176b800f85816 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -48,7 +48,7 @@ public class EntitySquid extends EntityWaterAnimal { - - public EntitySquid(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.random.setSeed((long) this.getId()); -+ //this.random.setSeed((long) this.getId()); // Paper - this.bu = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; - } - diff --git a/Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch b/Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch deleted file mode 100644 index e2a6edf92cd4..000000000000 --- a/Spigot-Server-Patches/0237-Re-add-vanilla-entity-warnings-for-duplicates.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:08:05 -0400 -Subject: [PATCH] Re-add vanilla entity warnings for duplicates - -These are a critical sign that somethin went wrong, and you've lost some data.... - -We should kind of know about these things you know. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index eb19b6fc87bfd4e500ea7836c1010a80b36abab2..d6a4ec132cadf8134a21f625f4ca978d37c643d0 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1077,7 +1077,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit -+ WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper - return true; - } - } diff --git a/Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch deleted file mode 100644 index aded79d749ed..000000000000 --- a/Spigot-Server-Patches/0238-Avoid-item-merge-if-stack-size-above-max-stack-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 16 Jul 2018 12:42:20 +0200 -Subject: [PATCH] Avoid item merge if stack size above max stack size - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index de11fd9772f30ac72c3ca52ec4efc3fef4091425..4cfe3475fa913cd46116f13ea8ed9caf5372a41a 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -209,6 +209,10 @@ public class EntityItem extends Entity { - - private void mergeNearby() { - if (this.z()) { -+ // Paper start - avoid item merge if stack size above max stack size -+ ItemStack stack = getItemStack(); -+ if (stack.getCount() >= stack.getMaxStackSize()) return; -+ // Paper end - // Spigot start - double radius = world.spigotConfig.itemMerge; - List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(radius, radius, radius), (entityitem) -> { diff --git a/Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch b/Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch deleted file mode 100644 index 39cafbddfce6..000000000000 --- a/Spigot-Server-Patches/0239-Use-asynchronous-Log4j-2-loggers.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 17 Jul 2018 16:42:17 +0200 -Subject: [PATCH] Use asynchronous Log4j 2 loggers - - -diff --git a/pom.xml b/pom.xml -index 6b2eac7aac7e9a343472cc033b34cbe3e3a82e32..dd5f7dba3610b63aa16088a94bf3b459d496cb3c 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -88,6 +88,13 @@ - log4j-iostreams - compile - -+ -+ -+ com.lmax -+ disruptor -+ 3.4.2 -+ runtime -+ - - org.ow2.asm - asm -diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..db652a1f7abc80bc751fd94925abaec58ab1a563 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -@@ -0,0 +1,17 @@ -+package com.destroystokyo.paper.log; -+ -+import org.apache.logging.log4j.Level; -+import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; -+import org.apache.logging.log4j.core.async.EventRoute; -+ -+public final class LogFullPolicy implements AsyncQueueFullPolicy { -+ -+ /* -+ * Prevents log calls being logged out of order when the log queue is full. -+ */ -+ -+ @Override -+ public EventRoute getRoute(final long backgroundThreadId, final Level level) { -+ return EventRoute.ENQUEUE; -+ } -+} -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -index 0694b21465fb9e4164e71862ff24b62241b191f2..30efeb5faf8e7faccf1b252fa0ed6a9fc31c40a7 100644 ---- a/src/main/resources/log4j2.component.properties -+++ b/src/main/resources/log4j2.component.properties -@@ -1 +1,3 @@ -+Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -+log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" - log4j.skipJansi=true diff --git a/Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch b/Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch deleted file mode 100644 index a507bf2bac55..000000000000 --- a/Spigot-Server-Patches/0240-add-more-information-to-Entity.toString.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:13:28 -0400 -Subject: [PATCH] add more information to Entity.toString() - -UUID, ticks lived, valid, dead - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 828f238e8f3b1a98310532e07c72161582c91c5b..bd9cd050c72792c3d5a2094991b21e3a998b2cd9 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2522,7 +2522,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public String toString() { -- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getDisplayName().getString(), this.id, this.world == null ? "~NULL~" : this.world.toString(), this.locX(), this.locY(), this.locZ()); -+ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getDisplayName().getString(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.toString(), Double.valueOf(this.locX()), Double.valueOf(this.locY()), Double.valueOf(this.locZ()), chunkX, chunkZ, this.ticksLived, this.valid, this.dead}); // Paper - add more information - } - - public boolean isInvulnerable(DamageSource damagesource) { diff --git a/Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch deleted file mode 100644 index 7a68817fbe15..000000000000 --- a/Spigot-Server-Patches/0241-Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 08:25:40 -0400 -Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues - -Add -Ddebug.entities=true to your JVM flags to gain more information - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d1e45dfb99074ec027d4f943391a024c726d93b2..66c808244bba70f827d8f15a96814251d352a046 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1147,6 +1147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = new PlayerChunkMap.EntityTracker(entity, i, j, entitytypes.isDeltaTracking()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.track(this.world.getPlayers()); - if (entity instanceof EntityPlayer) { -@@ -1188,7 +1189,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.a(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void g() { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d6a4ec132cadf8134a21f625f4ca978d37c643d0..650015f08ef4defe7510ff2f5cbd25364b733515 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -197,6 +197,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ private static Throwable getAddToWorldStackTrace(Entity entity) { -+ return new Throwable(entity + " Added to world at " + new java.util.Date()); -+ } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -@@ -1038,8 +1041,28 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper -+ // Paper start -+ if (entity.valid) { -+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -+ -+ if (DEBUG_ENTITIES) { -+ Throwable thr = entity.addedToWorldStack; -+ if (thr == null) { -+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); -+ } else { -+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); -+ } -+ } -+ return true; -+ } -+ // Paper end - if (entity.dead) { -+ // Paper start -+ if (DEBUG_ENTITIES) { -+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; - } else if (this.isUUIDTaken(entity)) { -@@ -1237,7 +1260,24 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (DEBUG_ENTITIES) { -+ entity.addedToWorldStack = getAddToWorldStackTrace(entity); -+ } -+ -+ Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (old != null && old.getId() != entity.getId() && old.valid) { -+ Logger logger = LogManager.getLogger(); -+ logger.error("Overwrote an existing entity " + old + " with " + entity); -+ if (DEBUG_ENTITIES) { -+ if (old.addedToWorldStack != null) { -+ old.addedToWorldStack.printStackTrace(); -+ } else { -+ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); -+ } -+ entity.addedToWorldStack.printStackTrace(); -+ } -+ } -+ - this.getChunkProvider().addEntity(entity); - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index bd9cd050c72792c3d5a2094991b21e3a998b2cd9..c88eea18e2e219f242c53ffb4e28cfc6d7bf318a 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -161,6 +162,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -+ PlayerChunkMap.EntityTracker tracker; // Paper -+ public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(world.getServer(), this); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index a9e7da1c848a6fe08fc112e445ceec1b7715d682..0d375af209e9768f430e08bd7a4bde1863b14da5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -121,6 +121,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean pvpMode; - public boolean keepSpawnInMemory = true; - public org.bukkit.generator.ChunkGenerator generator; -+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; diff --git a/Spigot-Server-Patches/0242-EnderDragon-Events.patch b/Spigot-Server-Patches/0242-EnderDragon-Events.patch deleted file mode 100644 index 2ac7798d520f..000000000000 --- a/Spigot-Server-Patches/0242-EnderDragon-Events.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:27 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index 5adbd9fe858aad9c775a10254eb53b34719a9bd6..91de4e6c1d478e001c8672d34b4ffe57f6cba0a6 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -80,7 +80,11 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - this.d.setDuration(200); - this.d.setParticle(Particles.DRAGON_BREATH); - this.d.addEffect(new MobEffect(MobEffects.HARM)); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.a.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.d.getBukkitEntity()).callEvent()) { // Paper - this.a.world.addEntity(this.d); -+ } else { -+ this.removeAreaEffect(); -+ } - } - - } -@@ -91,8 +95,8 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - ++this.c; - } - -- @Override -- public void e() { -+ public final void removeAreaEffect() { this.e(); } // Paper - OBFHELPER -+ @Override public void e() { - if (this.d != null) { - this.d.die(); - this.d = null; -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -index db3cef26c8d5cdf740bb151a5525d8740a0e8bbd..1a5d5d39d3090acc3914e40e8d30c4a09789dbc9 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -@@ -81,7 +81,9 @@ public class DragonControllerStrafe extends AbstractDragonController { - EntityDragonFireball entitydragonfireball = new EntityDragonFireball(this.a.world, this.a, d9, d10, d11); - - entitydragonfireball.setPositionRotation(d6, d7, d8, 0.0F, 0.0F); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) a.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper - this.a.world.addEntity(entitydragonfireball); -+ else entitydragonfireball.die(); // Paper - this.c = 0; - if (this.d != null) { - while (!this.d.c()) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -index 59b5484731a5f71005c3efa56cbe40012d9641b5..27853f510e15e40c66da2cb4905c43f5e8f99d3d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -@@ -58,8 +58,10 @@ public class EntityDragonFireball extends EntityFireball { - } - } - -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(EntityLiving::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper - this.world.triggerEffect(2006, this.getChunkCoordinates(), this.isSilent() ? -1 : 1); - this.world.addEntity(entityareaeffectcloud); -+ } else entityareaeffectcloud.die(); // Paper - this.die(); - } - diff --git a/Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch b/Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch deleted file mode 100644 index 684680a7edd8..000000000000 --- a/Spigot-Server-Patches/0243-PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:59 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index a2950faa48021782f10db0673d12d178443f7ccc..79e9be800385b94c4493bd8970620d76bfbd65ae 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -45,11 +45,16 @@ public class ItemFireworks extends Item { - // Paper start - final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); - entityfireworks.spawningEntity = entityhuman.getUniqueID(); -- world.addEntity(entityfireworks); -- // Paper end -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityfireworks)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -+ // Paper end - } - - return InteractionResultWrapper.a(entityhuman.b(enumhand), world.s_()); diff --git a/Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch b/Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch deleted file mode 100644 index 9d4fb270ac26..000000000000 --- a/Spigot-Server-Patches/0244-Improve-BlockPosition-inlining.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Improve BlockPosition inlining - -Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. -If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. -But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. - -This scenario also occurs with BlockPos and MutableBlockPos. -The variables in BlockPos are final, so MutableBlockPos can't modify them. -MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. - -This approach with utility methods that operate on MutableBlockPos and BlockPos. -Specific examples are BlockPosition.up(), and World.isValidLocation(). -It makes these simple methods much slower than they need to be. - -This should result in an across the board speedup in anything that accesses blocks or does logic with positions. - -This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. -They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 4b56683336fdab06804efdc8ca1f7c130b77291f..a44bcdb053877a6281e566ffe03ef72ffd50ca08 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -41,7 +41,7 @@ public class BaseBlockPosition implements Comparable { - this(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -- public boolean equals(Object object) { -+ public final boolean equals(Object object) { // Paper - if (this == object) { - return true; - } else if (!(object instanceof BaseBlockPosition)) { -@@ -53,7 +53,7 @@ public class BaseBlockPosition implements Comparable { - } - } - -- public int hashCode() { -+ public final int hashCode() { // Paper - return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - } - -@@ -61,15 +61,15 @@ public class BaseBlockPosition implements Comparable { - return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); - } - -- public int getX() { -+ public final int getX() { // Paper - return this.a; - } - -- public int getY() { -+ public final int getY() { // Paper - return this.b; - } - -- public int getZ() { -+ public final int getZ() { // Paper - return this.e; - } - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 9fb6db18c5c1f39b5a564c0f5f70498825defa97..370b2c4460d6b52b5ef7da89f5ebf7ef50deb582 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -88,6 +88,7 @@ public class BlockPosition extends BaseBlockPosition { - return a(this.getX(), this.getY(), this.getZ()); - } - -+ public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { - long l = 0L; - diff --git a/Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch b/Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch deleted file mode 100644 index 028620de8b04..000000000000 --- a/Spigot-Server-Patches/0245-Optimize-RegistryID.c.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 23 Jul 2018 13:08:19 -0400 -Subject: [PATCH] Optimize RegistryID.c() - -This is a frequent hotspot for world loading/saving. - -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index 6150f7a5c5004ac79414ab22dbaa3439dc8afdb4..a59dbfa01743137702b122f73c778452e63115b5 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -15,12 +15,14 @@ public class RegistryID implements Registry { - private K[] d; - private int e; - private int f; -+ private java.util.BitSet usedIds; // Paper - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); - this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; - this.d = (K[]) (new Object[i]); // Paper - decompile fix -+ this.usedIds = new java.util.BitSet(); // Paper - } - - // Paper start - decompile fix -@@ -52,9 +54,14 @@ public class RegistryID implements Registry { - } - - private int c() { -+ // Paper start -+ /* - while (this.e < this.d.length && this.d[this.e] != null) { - ++this.e; - } -+ */ -+ this.e = this.usedIds.nextClearBit(0); -+ // Paper end - - return this.e; - } -@@ -68,6 +75,7 @@ public class RegistryID implements Registry { - this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - - for (int j = 0; j < ak.length; ++j) { - if (ak[j] != null) { -@@ -93,6 +101,7 @@ public class RegistryID implements Registry { - this.b[k] = k0; - this.c[k] = i; - this.d[i] = k0; -+ this.usedIds.set(i); // Paper - ++this.f; - if (i == this.e) { - ++this.e; -@@ -157,6 +166,7 @@ public class RegistryID implements Registry { - Arrays.fill(this.d, (Object) null); - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - } - - public int b() { diff --git a/Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch deleted file mode 100644 index d24d23f2ac2b..000000000000 --- a/Spigot-Server-Patches/0246-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 12:57:39 +0200 -Subject: [PATCH] Option to prevent armor stands from doing entity lookups - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4813f62d1e382d5ac6971b2244df3f13c80d1950..3562950df4868b1393790b1a1ff1fe0dc589c155 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -379,4 +379,9 @@ public class PaperWorldConfig { - private void scanForLegacyEnderDragon() { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } -+ -+ public boolean armorStandEntityLookups = true; -+ private void armorStandEntityLookups() { -+ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 57e0ea95df34fab22d6c5868ab839d56a3fa85fc..829013f57128cc6c92a45098c6883f2305cf4ea5 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -356,6 +356,7 @@ public class EntityArmorStand extends EntityLiving { - - @Override - protected void collideNearby() { -+ if (!world.paperConfig.armorStandEntityLookups) return; // Paper - List list = this.world.getEntities(this, this.getBoundingBox(), EntityArmorStand.br); - - for (int i = 0; i < list.size(); ++i) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0d375af209e9768f430e08bd7a4bde1863b14da5..8c7263f9dbb00cf6484e7f70b8d97639bab0cefc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -37,6 +37,7 @@ import net.minecraft.world.DifficultyDamageScaler; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.decoration.EntityArmorStand; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CraftingManager; -@@ -854,6 +855,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Paper end - } - } -+ // Paper start - Prevent armor stands from doing entity lookups -+ @Override -+ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisAlignedBB) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; -+ return GeneratorAccess.super.getCubes(entity, axisAlignedBB); -+ } -+ // Paper end - - public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Explosion.Effect explosion_effect) { - return this.createExplosion(entity, (DamageSource) null, (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect); diff --git a/Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch b/Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch deleted file mode 100644 index 0ef9663c1b25..000000000000 --- a/Spigot-Server-Patches/0247-Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 14:22:26 +0200 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c88eea18e2e219f242c53ffb4e28cfc6d7bf318a..3a46a5001cda7402a97ac8552650cf64e7881fad 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -184,7 +184,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private static double e = 1.0D; - private final EntityTypes f; - private int id; -- public boolean i; -+ public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER - public final List passengers; - protected int j; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 8f14e1ebefe172e056a04bd7b6f55b9bbb1e7b2e..b44b18341331e5176e0f1851aa60cc425ccbd439 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -4,6 +4,7 @@ import java.util.Iterator; - import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; -@@ -158,8 +159,14 @@ public abstract class IProjectile extends Entity { - protected boolean a(Entity entity) { - if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { - Entity entity1 = this.getShooter(); -- -+ // Paper start - Cancel hit for vanished players -+ if (entity1 instanceof EntityPlayer && entity instanceof EntityPlayer) { -+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); -+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); -+ if (!shooter.canSee(collided)) return false; -+ } - return entity1 == null || this.d || !entity1.isSameVehicle(entity); -+ // Paper end - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java -index ec12bea9de910824927ba31628b49f6713f31a29..59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBlock.java -+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java -@@ -177,7 +177,8 @@ public class ItemBlock extends Item { - EntityHuman entityhuman = blockactioncontext.getEntity(); - VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a((Entity) entityhuman); - // CraftBukkit start - store default return -- boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && blockactioncontext.getWorld().a(iblockdata, blockactioncontext.getClickPosition(), voxelshapecollision); -+ World world = blockactioncontext.getWorld(); // Paper -+ boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && world.checkEntityCollision(iblockdata, entityhuman, voxelshapecollision, blockactioncontext.getClickPosition(), true); // Paper - org.bukkit.entity.Player player = (blockactioncontext.getEntity() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getEntity().getBukkitEntity() : null; - - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(blockactioncontext.getWorld(), blockactioncontext.getClickPosition()), player, CraftBlockData.fromData(iblockdata), defaultReturn); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 8c7263f9dbb00cf6484e7f70b8d97639bab0cefc..07c5cdd00930a55fd412ef95f71f55ee908189a1 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -27,6 +27,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -65,6 +66,10 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldDataMutable; - import net.minecraft.world.phys.AxisAlignedBB; -+import net.minecraft.world.phys.shapes.OperatorBoolean; -+import net.minecraft.world.phys.shapes.VoxelShape; -+import net.minecraft.world.phys.shapes.VoxelShapeCollision; -+import net.minecraft.world.phys.shapes.VoxelShapes; - import net.minecraft.world.scores.Scoreboard; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -232,6 +237,46 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - -+ // Paper start -+ // ret true if no collision -+ public final boolean checkEntityCollision(IBlockData data, Entity source, VoxelShapeCollision voxelshapedcollision, -+ BlockPosition position, boolean checkCanSee) { -+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) -+ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ List entities = this.getEntities(null, voxelshape.getBoundingBox()); -+ for (int i = 0, len = entities.size(); i < len; ++i) { -+ Entity entity = entities.get(i); -+ -+ if (checkCanSee && source instanceof EntityPlayer && entity instanceof EntityPlayer -+ && !((EntityPlayer) source).getBukkitEntity().canSee(((EntityPlayer) entity).getBukkitEntity())) { -+ continue; -+ } -+ -+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); -+ // elide the last check since vanilla calls with entity = null -+ // only we care about the source for the canSee check -+ if (entity.dead || !entity.blocksEntitySpawning()) { -+ continue; -+ } -+ -+ if (VoxelShapes.applyOperation(voxelshape, VoxelShapes.of(entity.getBoundingBox()), OperatorBoolean.AND)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - @Override - public boolean s_() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 2902117fd2803741b053a04fda7f4414fb8593cb..10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -505,6 +505,7 @@ public abstract class BlockBase { - return this.a != null ? this.a.b : this.b(iblockaccess, blockposition, VoxelShapeCollision.a()); - } - -+ public final VoxelShape getCollisionShape(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { return this.b(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER - public VoxelShape b(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { - return this.getBlock().c(this.p(), iblockaccess, blockposition, voxelshapecollision); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -index 1b82349b96b3ec9490d06d1c1d1cbf2b1578d313..887016224c16f8a38c10a98eb0e2ae6cb353a153 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -@@ -54,6 +54,7 @@ public abstract class VoxelShape { - return this.a.a(); - } - -+ public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER - public VoxelShape a(double d0, double d1, double d2) { - return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index fdd9e37a8c90fc3311e515355af0a0593efbdacc..cf32a4f63e8e59535c02a3f9c57f98833a2b0e83 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -45,6 +45,7 @@ public final class VoxelShapes { - return a(new AxisAlignedBB(d0, d1, d2, d3, d4, d5)); - } - -+ public static final VoxelShape of(AxisAlignedBB axisAlignedbb) { return VoxelShapes.a(axisAlignedbb); } // Paper - OBFHELPER - public static VoxelShape a(AxisAlignedBB axisalignedbb) { - int i = a(axisalignedbb.minX, axisalignedbb.maxX); - int j = a(axisalignedbb.minY, axisalignedbb.maxY); -@@ -139,6 +140,7 @@ public final class VoxelShapes { - } - } - -+ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { - if (operatorboolean.apply(false, false)) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 69bcd6dcfc62ab7b5666b8e185efa07a9adbc179..6d08487ff25b474b2372de37ea77aa0eb997d89a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1220,6 +1220,14 @@ public class CraftEventFactory { - Projectile projectile = (Projectile) entity.getBukkitEntity(); - org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); - com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); -+ -+ if (projectile.getShooter() instanceof Player && collided instanceof Player) { -+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { -+ event.setCancelled(true); -+ return event; -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } diff --git a/Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch deleted file mode 100644 index a5f5fb4d8d0b..000000000000 --- a/Spigot-Server-Patches/0248-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:18:31 -0400 -Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it - saves - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 7918dd4ad3e8cbb905b3929062a70fb7961b7d68..f56ff8e727c74870229d4d146b13534863f620d6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -560,6 +560,7 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ this.markDirty(); // Paper - } - - @Override -@@ -588,6 +589,7 @@ public class Chunk implements IChunkAccess { - return; - } - entityCounts.decrement(entity.getMinecraftKeyString()); -+ this.markDirty(); // Paper - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch b/Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch deleted file mode 100644 index 71c72d329eaa..000000000000 --- a/Spigot-Server-Patches/0249-Add-some-Debug-to-Chunk-Entity-slices.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:44:23 -0400 -Subject: [PATCH] Add some Debug to Chunk Entity slices - -If we detect unexpected state, log and try to recover - -This should hopefully avoid duplicate entities ever being created -if the entity was to end up in 2 different chunk slices - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 3a46a5001cda7402a97ac8552650cf64e7881fad..102c2bb98a99cdbfcdf1297341dbba91434ee0e3 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -157,6 +157,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - }; -+ public List entitySlice = null; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index f56ff8e727c74870229d4d146b13534863f620d6..e4accac8f2e8daa58f9b0c279ffcad9347448bb0 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -26,6 +26,8 @@ import net.minecraft.ReportedException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; -@@ -551,6 +553,25 @@ public class Chunk implements IChunkAccess { - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } -+ // Paper - remove from any old list if its in one -+ List nextSlice = this.entitySlices[k]; // the next list to be added to -+ List currentSlice = entity.entitySlice; -+ if (nextSlice == currentSlice) { -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); -+ return; // ??? silly plugins -+ } -+ if (currentSlice != null && currentSlice.contains(entity)) { -+ // Still in an old chunk... -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); -+ Chunk chunk = entity.getCurrentChunk(); -+ if (chunk != null) { -+ chunk.removeEntity(entity); -+ } else { -+ removeEntity(entity); -+ } -+ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice -+ } -+ // Paper end - - if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; -@@ -560,6 +581,7 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } - -@@ -585,6 +607,10 @@ public class Chunk implements IChunkAccess { - - // Paper start - if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (entitySlices[i] == entity.entitySlice) { -+ entity.entitySlice = null; -+ entity.inChunk = false; -+ } - if (!this.entitySlices[i].remove(entity)) { - return; - } diff --git a/Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch b/Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch deleted file mode 100644 index 96ea01f30ac7..000000000000 --- a/Spigot-Server-Patches/0250-SkeletonHorse-Additions.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:31 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index dfcfdb31ca9531913d705aaaf85fb67399cfdc8c..4776a47566aac487dc77fd6b4b9b42b95974e31a 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -25,6 +25,7 @@ public final class IEntitySelector { - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -+ public static Predicate notSpectator() { return g; } // Paper - OBFHELPER - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -index 0ddb676a2d1c38c97cd7750c1594fd6468156d0a..da5365372e89b847d626e52c5541544467f14702 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -@@ -26,7 +26,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - - private final PathfinderGoalHorseTrap bw = new PathfinderGoalHorseTrap(this); - private boolean bx; -- private int by; -+ private int by; public int getTrapTime() { return this.by; } // Paper - OBFHELPER - - public EntityHorseSkeleton(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -145,10 +145,12 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - return 0.96F; - } - -+ public boolean isTrap() { return this.eM(); } // Paper - OBFHELPER - public boolean eM() { - return this.bx; - } - -+ public void setTrap(boolean trap) { this.t(trap); } // Paper - OBFHELPER - public void t(boolean flag) { - if (flag != this.bx) { - this.bx = flag; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -index 9b6a4f93dca6eeddad43d5f5675c551fb3fd2fdb..cf250cc6b7a77a7af742eab0b89cff2bc17fc5e4 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -@@ -15,9 +15,14 @@ import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.level.World; - -+import org.bukkit.entity.HumanEntity; -+ -+import java.util.List; -+ - public class PathfinderGoalHorseTrap extends PathfinderGoal { - - private final EntityHorseSkeleton a; -+ private List eligiblePlayers; // Paper - - public PathfinderGoalHorseTrap(EntityHorseSkeleton entityhorseskeleton) { - this.a = entityhorseskeleton; -@@ -25,12 +30,13 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal { - - @Override - public boolean a() { -- return this.a.world.isPlayerNearby(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D); -+ return !(eligiblePlayers = this.a.world.findNearbyBukkitPlayers(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D, false)).isEmpty(); // Paper - } - - @Override - public void e() { - WorldServer worldserver = (WorldServer) this.a.world; -+ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.a.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper - DifficultyDamageScaler difficultydamagescaler = worldserver.getDamageScaler(this.a.getChunkCoordinates()); - - this.a.t(false); -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 6d5d4c3df65995b9a13b66d070ba08d553cc98a2..8fdc4b22e8c99d653bd213fe64339c133b46b4e9 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -1,6 +1,9 @@ - package net.minecraft.world.level; - -+import com.google.common.collect.ImmutableList; - import com.google.common.collect.Lists; -+import org.bukkit.entity.HumanEntity; -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -115,6 +118,28 @@ public interface IEntityAccess { - return entityhuman; - } - -+ // Paper start -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { -+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? IEntitySelector.notSpectator() : IEntitySelector.canAITarget()); -+ } -+ -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { -+ ImmutableList.Builder builder = ImmutableList.builder(); -+ -+ for (EntityHuman human : this.getPlayers()) { -+ if (predicate == null || predicate.test(human)) { -+ double distanceSquared = human.getDistanceSquared(x, y, z); -+ -+ if (radius < 0.0D || distanceSquared < radius * radius) { -+ builder.add(human.getBukkitEntity()); -+ } -+ } -+ } -+ -+ return builder.build(); -+ } -+ // Paper end -+ - @Nullable - default EntityHuman findNearbyPlayer(Entity entity, double d0) { - return this.a(entity.locX(), entity.locY(), entity.locZ(), d0, false); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index 4aec5fdb6b0379b0797969ff3c8f8a9629a18bfb..7366d56cefad45883f353ea5fb16b41f87006ec1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -@@ -26,4 +26,26 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo - public Variant getVariant() { - return Variant.SKELETON_HORSE; - } -+ -+ // Paper start -+ @Override -+ public EntityHorseSkeleton getHandle() { -+ return (EntityHorseSkeleton) super.getHandle(); -+ } -+ -+ @Override -+ public int getTrapTime() { -+ return getHandle().getTrapTime(); -+ } -+ -+ @Override -+ public boolean isTrap() { -+ return getHandle().isTrap(); -+ } -+ -+ @Override -+ public void setTrap(boolean trap) { -+ getHandle().setTrap(trap); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch b/Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch deleted file mode 100644 index f9e9f4cd9f35..000000000000 --- a/Spigot-Server-Patches/0251-Prevent-Saving-Bad-entities-to-chunks.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 26 Jul 2018 00:11:12 -0400 -Subject: [PATCH] Prevent Saving Bad entities to chunks - -See https://github.com/PaperMC/Paper/issues/1223 - -Minecraft is saving invalid entities to the chunk files. - -Avoid saving bad data, and also make improvements to handle -loading these chunks. Any invalid entity will be instant killed, -so lets avoid adding it to the world... - -This lets us be safer about the dupe UUID resolver too, as now -we can ignore instant killed entities and avoid risk of duplicating -an invalid entity. - -This should reduce log occurrences of dupe uuid messages. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 650015f08ef4defe7510ff2f5cbd25364b733515..e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1157,6 +1157,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - List[] aentityslice = chunk.getEntitySlices(); // Spigot - int i = aentityslice.length; - -+ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - Iterator iterator = entityslice.iterator(); -@@ -1169,11 +1170,25 @@ public class WorldServer extends World implements GeneratorAccessSeed { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); - } - -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ if (!entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toMoveChunks.add(entity); -+ continue; -+ } -+ // Paper end -+ - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ -+ if (entity.dead) iterator.remove(); // Paper - don't save dead entities during unload - } - } - } -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ for (Entity entity : toMoveChunks) { -+ this.chunkCheck(entity); -+ } -+ // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index f301c7ba4b17b92c6cf2fcee6da1e67081dad4fa..69bc9dc18bab157851d8080a672504598e8572a8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -26,6 +26,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; - import net.minecraft.nbt.NBTTagShort; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -@@ -349,6 +350,7 @@ public class ChunkRegionLoader { - nbttagcompound1.set("TileEntities", nbttaglist1); - NBTTagList nbttaglist2 = new NBTTagList(); - -+ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper - if (ichunkaccess.getChunkStatus().getType() == ChunkStatus.Type.LEVELCHUNK) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -366,13 +368,28 @@ public class ChunkRegionLoader { - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); -- -+ // Paper start -+ if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toUpdate.add(entity); -+ continue; -+ } -+ if (entity.dead || hasPlayerPassenger(entity)) { -+ continue; -+ } -+ // Paper end - if (entity.d(nbttagcompound4)) { - chunk.d(true); - nbttaglist2.add(nbttagcompound4); - } - } - } -+ -+ // Paper start - move entities to the correct chunk -+ for (Entity entity : toUpdate) { -+ worldserver.chunkCheck(entity); -+ } -+ // Paper end -+ - } else { - ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - -@@ -431,6 +448,19 @@ public class ChunkRegionLoader { - nbttagcompound1.set("Structures", a(chunkcoordintpair, ichunkaccess.h(), ichunkaccess.v())); - return nbttagcompound; - } -+ // Paper start - this is saved with the player -+ private static boolean hasPlayerPassenger(Entity entity) { -+ for (Entity passenger : entity.passengers) { -+ if (passenger instanceof EntityPlayer) { -+ return true; -+ } -+ if (hasPlayerPassenger(passenger)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { diff --git a/Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch b/Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch deleted file mode 100644 index ab3543b44f7d..000000000000 --- a/Spigot-Server-Patches/0252-Don-t-call-getItemMeta-on-hasItemMeta.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Thu, 26 Jul 2018 14:10:23 +0200 -Subject: [PATCH] Don't call getItemMeta on hasItemMeta - -Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. - -We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. - -Returns true if getDamage() == 0 or has damage tag or other tag is set. -Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 315addab147dfecf4aa88d32d154cefe850d0a78..09d7a86b5f6cffdf6664ad657dd4f8dd8eabdd70 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -570,7 +570,7 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean hasItemMeta() { -- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); -+ return hasItemMeta(handle) && (handle.getDamage() != 0 || (handle.getTag() != null && handle.getTag().map.size() >= (handle.getTag().hasKey(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta - } - - static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 42f577ed3508ba5a380648461e149f16ce97c9bd..b85a0a4c4f134dd6012d9141244ecf97b4300b65 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -96,6 +96,34 @@ public class ItemMetaTest extends AbstractTestingBase { - assertThat(itemMeta.hasConflictingEnchant(null), is(false)); - } - -+ // Paper start -+ private void testItemMeta(ItemStack stack) { -+ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 2); -+ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(java.util.Collections.singletonList("Lore")); -+ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(null); -+ } -+ -+ @Test -+ public void testHasItemMeta() { -+ ItemStack itemStack = new ItemStack(Material.SHEARS); -+ -+ testItemMeta(itemStack); -+ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); -+ } -+ // Paper end -+ - @Test - public void testConflictingStoredEnchantment() { - EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch b/Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch deleted file mode 100644 index e45940928ca6..000000000000 --- a/Spigot-Server-Patches/0253-Ignore-Dead-Entities-in-entityList-iteration.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Jul 2018 12:18:27 -0400 -Subject: [PATCH] Ignore Dead Entities in entityList iteration - -A spigot change delays removal of entities from the entity list. -This causes a change in behavior from Vanilla where getEntities type -methods will return dead entities that they shouldn't otherwise be doing. - -This will ensure that dead entities are skipped from iteration since -they shouldn't of been in the list in the first place. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 6943524c2dd8b12691b8ac5b08daee823ce50c3d..b67bd98cca4a06bc0ebaed577195dffc3b3251ec 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -209,6 +209,7 @@ public class PaperCommand extends Command { - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { - MinecraftKey key = e.getMinecraftKey(); -+ if (e.shouldBeRemoved) return; // Paper - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e39f1ea4eefb0d8e0ca379b116b3699c13bb3f35..9151d84e2f6fb316525c74466589178769fbc8ef 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1309,6 +1309,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added - new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - -@@ -1321,6 +1322,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.removeEntityFromChunk(entity); - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ entity.shouldBeRemoved = true; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 102c2bb98a99cdbfcdf1297341dbba91434ee0e3..046b191e771ed9be337e095214a67febd768e5f6 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -276,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -+ public boolean shouldBeRemoved; // Paper - - public float getBukkitYaw() { - return this.yaw; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index e4accac8f2e8daa58f9b0c279ffcad9347448bb0..79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -863,6 +863,7 @@ public class Chunk implements IChunkAccess { - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity1 = (Entity) list1.get(i1); -+ if (entity1.shouldBeRemoved) continue; // Paper - - if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { - if (predicate == null || predicate.test(entity1)) { -@@ -900,6 +901,7 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error -+ if (entity.shouldBeRemoved) continue; // Paper - - if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { - list.add(entity); -@@ -922,6 +924,7 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error -+ if (t0.shouldBeRemoved) continue; // Paper - - if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check - list.add(t0); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a2b3f5106edc8328ba7edd65dedd56e0dc8d33d2..e7103b8021141071712759b1056eccb5e3da93b7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1040,6 +1040,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1059,6 +1060,7 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -1085,6 +1087,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { -@@ -1108,6 +1111,7 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { diff --git a/Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch b/Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch deleted file mode 100644 index 55ff4fad2230..000000000000 --- a/Spigot-Server-Patches/0254-Implement-Expanded-ArmorStand-API.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:25:46 -0400 -Subject: [PATCH] Implement Expanded ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 829013f57128cc6c92a45098c6883f2305cf4ea5..e97d25339b37a70f91022dcb021bbe82fb8f5eda 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -430,6 +430,7 @@ public class EntityArmorStand extends EntityLiving { - return enumitemslot; - } - -+ public final boolean isSlotDisabled(EnumItemSlot slot) { return this.d(slot); } // Paper - OBFHELPER - private boolean d(EnumItemSlot enumitemslot) { - return (this.disabledSlots & 1 << enumitemslot.getSlotFlag()) != 0 || enumitemslot.a() == EnumItemSlot.Function.HAND && !this.hasArms(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 6f922e4cbb095439fcd76ee0d0c08bc4160b8107..103f935d9b7a2cbe9639528c587d8ac2e5f14d07 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.core.Vector3f; -+import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.decoration.EntityArmorStand; - import org.bukkit.craftbukkit.CraftEquipmentSlot; - import org.bukkit.craftbukkit.CraftServer; -@@ -239,5 +240,78 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setCanMove(boolean move) { - getHandle().canMove = move; - } -+ -+ @Override -+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ return getHandle().getEquipment(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); -+ } -+ -+ @Override -+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ getEquipment().setItemInMainHand(item); -+ return; -+ case OFF_HAND: -+ getEquipment().setItemInOffHand(item); -+ return; -+ case FEET: -+ setBoots(item); -+ return; -+ case LEGS: -+ setLeggings(item); -+ return; -+ case CHEST: -+ setChestplate(item); -+ return; -+ case HEAD: -+ setHelmet(item); -+ return; -+ } -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ -+ @Override -+ public java.util.Set getDisabledSlots() { -+ java.util.Set disabled = new java.util.HashSet<>(); -+ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { -+ if (this.isSlotDisabled(slot)) { -+ disabled.add(slot); -+ } -+ } -+ return disabled; -+ } -+ -+ @Override -+ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ int disabled = 0; -+ for (org.bukkit.inventory.EquipmentSlot slot : slots) { -+ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; -+ EnumItemSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); -+ disabled += (1 << nmsSlot.getSlotFlag()) + (1 << (nmsSlot.getSlotFlag() + 8)) + (1 << (nmsSlot.getSlotFlag() + 16)); -+ } -+ getHandle().disabledSlots = disabled; -+ } -+ -+ @Override -+ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ java.util.Collections.addAll(disabled, slots); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0255-AnvilDamageEvent.patch b/Spigot-Server-Patches/0255-AnvilDamageEvent.patch deleted file mode 100644 index 3862e6017ef3..000000000000 --- a/Spigot-Server-Patches/0255-AnvilDamageEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:37:03 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index 9658c8206b5bab07838284935e9d5e0879e405f2..ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -80,7 +80,16 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - - if (!entityhuman.abilities.canInstantlyBuild && iblockdata.a((Tag) TagsBlock.ANVIL) && entityhuman.getRandom().nextFloat() < 0.12F) { - IBlockData iblockdata1 = BlockAnvil.c(iblockdata); -- -+ // Paper start -+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); -+ if (!event.callEvent()) { -+ return; -+ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { -+ iblockdata1 = null; -+ } else { -+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().set(BlockAnvil.FACING, iblockdata.get(BlockAnvil.FACING)); -+ } -+ // Paper end - if (iblockdata1 == null) { - world.a(blockposition, false); - world.triggerEffect(1029, blockposition, 0); diff --git a/Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch b/Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch deleted file mode 100644 index e848d18de037..000000000000 --- a/Spigot-Server-Patches/0256-Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 16 Jul 2018 00:05:05 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 97ef4c65c8cc569a99d9697f56bd44d32b151328..51993191e01f55e16667c25b8b57d6a6ddaf493b 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.event.entity.EntityExplodeEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; - // CraftBukkit end -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class EntityEnderDragon extends EntityInsentient implements IMonster { - -@@ -515,6 +516,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - }); - craftBlock.getNMS().dropNaturally((WorldServer) world, blockposition, ItemStack.b); - } -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSource().getBukkitEntity()).callEvent()) -+ continue; -+ // Paper end - nmsBlock.wasExploded(world, blockposition, explosionSource); - - this.world.a(blockposition, false); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index c22fad0038fdb0769e23db782e3341206fbd80f9..5ef38414d87fbce453e3ab11579c89a8ff089ae0 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; - import com.google.common.collect.ImmutableMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - import java.util.Map; - import java.util.Random; - import java.util.function.Function; -@@ -11,6 +12,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; - import net.minecraft.world.level.GameRules; -@@ -289,7 +291,7 @@ public class BlockFire extends BlockFireAbstract { - - world.setTypeAndData(blockposition, this.a(world, blockposition, l), 3); - } else { -- world.a(blockposition, false); -+ if(iblockdata.getBlock() != Blocks.TNT) world.a(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down - } - - Block block = iblockdata.getBlock(); -@@ -297,6 +299,13 @@ public class BlockFire extends BlockFireAbstract { - if (block instanceof BlockTNT) { - BlockTNT blocktnt = (BlockTNT) block; - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { -+ return; -+ } -+ world.setAir(blockposition, false); -+ // Paper end - BlockTNT.a(world, blockposition); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTNT.java b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -index b5d40898bb4a10b3170cd1f42f1a44de539d53c3..71c46d5042f7e4585b364682cd5464edccdf43f6 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTNT.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.properties.BlockProperties; - import net.minecraft.world.level.block.state.properties.BlockStateBoolean; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class BlockTNT extends Block { - -@@ -36,6 +37,11 @@ public class BlockTNT extends Block { - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock())) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -46,6 +52,11 @@ public class BlockTNT extends Block { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -64,6 +75,12 @@ public class BlockTNT extends Block { - @Override - public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { - if (!world.isClientSide) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) -+ return; -+ // Paper end - EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, explosion.getSource()); - - entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); -@@ -92,6 +109,11 @@ public class BlockTNT extends Block { - if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { - return super.interact(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); - } else { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, entityhuman.getBukkitEntity()).callEvent()) -+ return EnumInteractionResult.FAIL; -+ // Paper end - a(world, blockposition, (EntityLiving) entityhuman); - world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 11); - if (!entityhuman.isCreative()) { -@@ -121,6 +143,13 @@ public class BlockTNT extends Block { - } - // CraftBukkit end - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, iprojectile.getBukkitEntity()).callEvent()) { -+ return; -+ } -+ // Paper end -+ - a(world, blockposition, entity instanceof EntityLiving ? (EntityLiving) entity : null); - world.a(blockposition, false); - } diff --git a/Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch b/Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch deleted file mode 100644 index 2ed97a27fdc3..000000000000 --- a/Spigot-Server-Patches/0257-Break-up-and-make-tab-spam-limits-configurable.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 29 Jul 2018 05:02:15 +0100 -Subject: [PATCH] Break up and make tab spam limits configurable - -Due to the changes in 1.13, clients will send a tab completion request -for all bukkit commands in order to factor in the lack of support for -brigadier and provide backwards support in the API. - -Craftbukkit, however; has moved the chat spam limiter to also interact -with the tab completion request, which while good for avoiding abuse, -causes 1.13 clients to easilly be kicked from a server in bukkit due -to this. Removing the spam limit could cause issues for servers, however, -there is no way for servers to manipulate this without blindly cancelling -kick events, which only causes additional complications. This also causes -issues in that the tab spam limit and chat share the same field but different -limits, meaning that a player having typed a long command may be kicked from -the server. - -Splitting the field up and making it configurable allows for server owners -to take the burden of this into their own hand without having to rely on -plugins doing unsafe things. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 77a03abd59db4a43f6f2d59d4c7ef176e782f205..bd508025b771424c942fd856c31d520b6f548082 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -296,4 +296,18 @@ public class PaperConfig { - Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); - } - } -+ -+ public static int tabSpamIncrement = 1; -+ public static int tabSpamLimit = 500; -+ private static void tabSpamLimiters() { -+ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); -+ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default -+ if (version < 14) { -+ if (tabSpamIncrement == 10) { -+ set("settings.spam-limiter.tab-spam-increment", 2); -+ tabSpamIncrement = 2; -+ } -+ } -+ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 19763a27ad54866b7d1f6e2cfccd6bbe6e54637e..74942bf7641eafab85202fd6a521780ce4cc1f65 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -230,6 +230,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -+ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -365,6 +366,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; -+ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -716,7 +718,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTabComplete packetplayintabcomplete) { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start -- if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -+ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } diff --git a/Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch b/Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch deleted file mode 100644 index 7d88f6f19e7d..000000000000 --- a/Spigot-Server-Patches/0258-Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:35 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 9151d84e2f6fb316525c74466589178769fbc8ef..ecb4cb5df868673e5aa2eec3fdd8618dbea09655 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1657,15 +1657,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -- public BlockPosition getSpawn() { -- BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -- -- if (!this.getWorldBorder().a(blockposition)) { -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -- } -- -- return blockposition; -- } -+ // Paper - moved up to World -+ //public BlockPosition getSpawn() { -+ // BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ // -+ // if (!this.getWorldBorder().a(blockposition)) { -+ // blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ // } -+ // -+ // return blockposition; -+ //} -+ // Paper end - - public float v() { - return this.worldData.d(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -index ef48ae4d398a1dd5bc67262ccdb5d8fc6bb2769c..1b43688ad232620410aa924cef02b54630ab1313 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -@@ -88,7 +88,7 @@ public class EntityCow extends EntityAnimal { - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { - // CraftBukkit start - Got milk? -- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET); -+ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand - - if (event.isCancelled()) { - return EnumInteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java -index 4bcac8defeaa146713cce43e04a51c1c9afddb1f..d126f668828e0788e369294c0b376ef52b344f2c 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBucket.java -+++ b/src/main/java/net/minecraft/world/item/ItemBucket.java -@@ -71,7 +71,7 @@ public class ItemBucket extends Item { - if (iblockdata.getBlock() instanceof IFluidSource) { - // CraftBukkit start - FluidType dummyFluid = ((IFluidSource) iblockdata.getBlock()).removeFluid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); -- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a()); -+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a(), enumhand); // Paper - add enumhand - - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) -@@ -99,7 +99,7 @@ public class ItemBucket extends Item { - iblockdata = world.getType(blockposition); - BlockPosition blockposition2 = iblockdata.getBlock() instanceof IFluidContainer && this.fluidType == FluidTypes.WATER ? blockposition : blockposition1; - -- if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit -+ if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, enumhand)) { // CraftBukkit // Paper - add enumhand - this.a(world, itemstack, blockposition2); - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.y.a((EntityPlayer) entityhuman, blockposition2, itemstack); -@@ -124,10 +124,12 @@ public class ItemBucket extends Item { - public void a(World world, ItemStack itemstack, BlockPosition blockposition) {} - - public boolean a(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock) { -- return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null); -+ // Paper start - add enumHand -+ return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); - } - -- public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack) { -+ public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { -+ // Paper end - // CraftBukkit end - if (!(this.fluidType instanceof FluidTypeFlowing)) { - return false; -@@ -140,7 +142,7 @@ public class ItemBucket extends Item { - - // CraftBukkit start - if (flag1 && entityhuman != null) { -- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack); -+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-4238: needed when looking through entity - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 -@@ -149,7 +151,7 @@ public class ItemBucket extends Item { - } - // CraftBukkit end - if (!flag1) { -- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack); // CraftBukkit -+ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand - } else if (world.getDimensionManager().isNether() && this.fluidType.a((Tag) TagsFluid.WATER)) { - int i = blockposition.getX(); - int j = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 07c5cdd00930a55fd412ef95f71f55ee908189a1..88b1a0235bfc0b41ae1855f8900632e425730d1c 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -277,6 +277,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // Paper end - -+ // Paper start - moved up from WorldServer -+ public BlockPosition getSpawn() { -+ BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ -+ if (!this.getWorldBorder().a(blockposition)) { -+ blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ } -+ -+ return blockposition; -+ } -+ // Paper end - @Override - public boolean s_() { - return this.isClientSide; -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 6d08487ff25b474b2372de37ea77aa0eb997d89a..877a0ea25f3cea970fa3827b12efc1a44bdcdf9c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -231,7 +231,7 @@ public class CraftEventFactory { - public static Entity entityDamage; // For use in EntityDamageByEntityEvent - - // helper methods -- private static boolean canBuild(WorldServer world, Player player, int x, int z) { -+ private static boolean canBuild(World world, Player player, int x, int z) { - int spawnSize = Bukkit.getServer().getSpawnRadius(); - - if (world.getDimensionKey() != World.OVERWORLD) return true; -@@ -421,6 +421,20 @@ public class CraftEventFactory { - } - - private static PlayerEvent getPlayerBucketEvent(boolean isFilling, WorldServer world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { -+ // Paper start - add enumHand -+ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); -+ } -+ -+ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, EnumHand enumHand) { -+ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); -+ } -+ -+ public static PlayerBucketFillEvent callPlayerBucketFillEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, EnumHand enumHand) { -+ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); -+ } -+ -+ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, EnumHand enumHand) { -+ // Paper end - Player player = (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); - Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); -@@ -433,10 +447,10 @@ public class CraftEventFactory { - - PlayerEvent event; - if (isFilling) { -- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } else { -- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } - diff --git a/Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch b/Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch deleted file mode 100644 index 7c85de629003..000000000000 --- a/Spigot-Server-Patches/0259-MC-135506-Experience-should-save-as-Integers.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 3 Aug 2018 00:04:54 -0400 -Subject: [PATCH] MC-135506: Experience should save as Integers - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 3387a19044b3ee2a1ef549c328c8bc354a5b6d23..a7551e95185895a290be70d501496279eaf884ae 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -218,7 +218,7 @@ public class EntityExperienceOrb extends Entity { - public void saveData(NBTTagCompound nbttagcompound) { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); -- nbttagcompound.setShort("Value", (short) this.value); -+ nbttagcompound.setInt("Value", this.value); // Paper - save as Integer - this.savePaperNBT(nbttagcompound); // Paper - } - -@@ -226,7 +226,7 @@ public class EntityExperienceOrb extends Entity { - public void loadData(NBTTagCompound nbttagcompound) { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); -- this.value = nbttagcompound.getShort("Value"); -+ this.value = nbttagcompound.getInt("Value"); // Paper - load as Integer - this.loadPaperNBT(nbttagcompound); // Paper - } - diff --git a/Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch b/Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch deleted file mode 100644 index 93f74c95cebd..000000000000 --- a/Spigot-Server-Patches/0260-Fix-client-rendering-skulls-from-same-user.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Nov 2016 00:40:42 -0500 -Subject: [PATCH] Fix client rendering skulls from same user - -See: https://github.com/PaperMC/Paper/issues/1304 - -Changes the UUID sent to client to be based on either -the texture payload, or random. - -This allows the client to render multiple skull textures from the same user, -for when different skins were used when skull was made. - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index df459918c14589155a574730205cb35d463b8079..5a1187b001004afe22d208bc5d7c288e796e16a6 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -37,6 +37,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -@@ -311,9 +312,18 @@ public class PacketDataSerializer extends ByteBuf { - if (item.usesDurability() || item.n()) { - // Spigot start - filter - itemstack = itemstack.cloneItemStack(); -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - // Spigot end - nbttagcompound = itemstack.getTag(); -+ // Paper start -+ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) { -+ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner"); -+ if (owner.hasUUID("Id")) { -+ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); -+ TileEntitySkull.sanitizeUUID(owner); -+ } -+ } -+ // Paper end - } - - this.a(nbttagcompound); -@@ -333,7 +343,16 @@ public class PacketDataSerializer extends ByteBuf { - itemstack.setTag(this.l()); - // CraftBukkit start - if (itemstack.getTag() != null) { -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ owner.map.put("Id", itemstack.tag.map.get("SkullOwnerOrig")); -+ itemstack.tag.remove("SkullOwnerOrig"); -+ } -+ } -+ // Paper end -+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - } - // CraftBukkit end - return itemstack; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index b6b55d5baa5e8a6b69a3e4865c06bc8a4d61a4f3..152118729b1a95dcae05d32aa4289034ba394226 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -15,6 +15,7 @@ import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -69,6 +70,7 @@ public class PacketPlayOutMapChunk implements Packet { - - if (this.f() || (i & 1 << j) != 0) { - NBTTagCompound nbttagcompound = tileentity.b(); -+ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - - this.g.add(nbttagcompound); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2ac8b6ac38bdca26cddfb8652f13b0be0c4000fe..24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -114,7 +114,7 @@ public final class ItemStack { - private int g; - @Deprecated - private Item item; -- private NBTTagCompound tag; -+ public NBTTagCompound tag; // Paper private -> public - private boolean j; - private Entity k; - private ShapeDetectorBlock l; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 22217f24b4a87f10b6d5a3e37d23a1164af84ace..4f7c014fa609a39cac651ccc6d3397d7edb77d8d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -9,6 +9,7 @@ import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; - import net.minecraft.server.players.UserCache; - import net.minecraft.util.UtilColor; -@@ -154,9 +155,37 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa - @Nullable - @Override - public PacketPlayOutTileEntityData getUpdatePacket() { -- return new PacketPlayOutTileEntityData(this.position, 4, this.b()); -+ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.b())); // Paper - } - -+ // Paper start -+ public static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { -+ NBTTagCompound owner = cmp.getCompound("Owner"); -+ if (!owner.isEmpty()) { -+ sanitizeUUID(owner); -+ } -+ return cmp; -+ } -+ -+ public static void sanitizeUUID(NBTTagCompound owner) { -+ NBTTagCompound properties = owner.getCompound("Properties"); -+ NBTTagList list = null; -+ if (!properties.isEmpty()) { -+ list = properties.getList("textures", 10); -+ } -+ -+ if (list != null && !list.isEmpty()) { -+ String textures = ((NBTTagCompound)list.get(0)).getString("Value"); -+ if (textures != null && textures.length() > 3) { -+ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); -+ owner.setUUID("Id", uuid); -+ return; -+ } -+ } -+ owner.setUUID("Id", UUID.randomUUID()); -+ } -+ // Paper end -+ - @Override - public NBTTagCompound b() { - return this.save(new NBTTagCompound()); diff --git a/Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch b/Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch deleted file mode 100644 index 0d0602c19e01..000000000000 --- a/Spigot-Server-Patches/0261-Add-Early-Warning-Feature-to-WatchDog.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Wed, 8 Aug 2018 15:30:52 -0400 -Subject: [PATCH] Add Early Warning Feature to WatchDog - -Detect when the server has been hung for a long duration, and start printing -thread dumps at an interval until the point of crash. - -This will help diagnose what was going on in that time before the crash. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index bd508025b771424c942fd856c31d520b6f548082..62621562137cba4804f0465c58d25ca2786328e5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; - import org.spigotmc.SpigotConfig; -+import org.spigotmc.WatchdogThread; - - public class PaperConfig { - -@@ -297,6 +298,14 @@ public class PaperConfig { - } - } - -+ public static int watchdogPrintEarlyWarningEvery = 5000; -+ public static int watchdogPrintEarlyWarningDelay = 10000; -+ private static void watchdogEarlyWarning() { -+ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); -+ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); -+ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); -+ } -+ - public static int tabSpamIncrement = 1; - public static int tabSpamLimit = 500; - private static void tabSpamLimiters() { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 925dd2dc2b4af5596c9dc891f756bad66baadbea..540250a9610e2ee51685b655a7d6c0809bba64fd 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1019,6 +1019,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ // Paper start -+ Logger log = Bukkit.getServer().getLogger(); -+ long currentTime = monotonicMillis(); -+ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) - { -- Logger log = Bukkit.getServer().getLogger(); -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ // Don't spam early warning dumps -+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -+ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ lastEarlyWarning = currentTime; -+ if (isLongTimeout) { -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); -@@ -93,29 +108,46 @@ public class WatchdogThread extends Thread - } - } - // Paper end -+ } else -+ { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); -+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); -+ } -+ // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // -+ // Paper start - Only print full dump on long timeouts -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) - { - dumpThread( thread, log ); - } -+ } else { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); -+ } -+ -+ - log.log( Level.SEVERE, "------------------------------" ); - -+ if ( isLongTimeout ) -+ { - if ( restart && !MinecraftServer.getServer().hasStopped() ) - { - RestartCommand.restart(); - } - break; -+ } // Paper end - } - - try - { -- sleep( 10000 ); -+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout - } catch ( InterruptedException ex ) - { - interrupt(); diff --git a/Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch b/Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch deleted file mode 100644 index cce5f2ddd264..000000000000 --- a/Spigot-Server-Patches/0262-Make-EnderDragon-implement-Mob.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:11:49 -0400 -Subject: [PATCH] Make EnderDragon implement Mob - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -index 3550eb81b66cad3cdfa41ddb5bb554b541cbbfe1..b537732070c784a97a96ccb77c211646b00580cc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -@@ -1,17 +1,18 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.EntityInsentient; // Paper - import net.minecraft.world.entity.EntityLiving; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.ComplexLivingEntity; - --public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { -- public CraftComplexLivingEntity(CraftServer server, EntityLiving entity) { -+public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper -+ public CraftComplexLivingEntity(CraftServer server, EntityInsentient entity) { // Paper - super(server, entity); - } - - @Override -- public EntityLiving getHandle() { -- return (EntityLiving) entity; -+ public EntityInsentient getHandle() { // Paper -+ return (EntityInsentient) entity; // Paper - } - - @Override diff --git a/Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch b/Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch deleted file mode 100644 index 8582eff151bc..000000000000 --- a/Spigot-Server-Patches/0263-Use-ConcurrentHashMap-in-JsonList.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: egg82 -Date: Tue, 7 Aug 2018 01:24:23 -0600 -Subject: [PATCH] Use ConcurrentHashMap in JsonList - -This is specifically aimed at fixing #471 - -Using a ConcurrentHashMap because thread safety -The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove -Even without considering the use-case the benefits are still negligable - -Original ideas for the system included an expiration policy and/or handler -The simpler solution was to use a computeIfPresent in the get method -This will simultaneously have an O(1) lookup time and automatically expire any values -Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful -Meaning the original function expired values unrelated to the current value without actually having any explicit need to - -The h method was heavily modified to be much more efficient in its processing -Also instead of being called on every get, it's now called just before a save -This will eliminate stale values being flushed to disk - -Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 -The point of this is readability, but does have a side-benefit of a small microptimization - -Finally, added a couple obfhelpers for the modified code - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index 52256f72b00d3b868ef1a60e15a3836197c769d9..cd35b833d3047a38be980ee550641e87bd3b9b01 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -12,6 +12,8 @@ import java.io.BufferedReader; - import java.io.BufferedWriter; - import java.io.File; - import java.io.IOException; -+import java.lang.reflect.ParameterizedType; // Paper -+import java.lang.reflect.Type; // Paper - import java.nio.charset.StandardCharsets; - import java.util.Collection; - import java.util.Iterator; -@@ -28,7 +30,22 @@ public abstract class JsonList> { - protected static final Logger LOGGER = LogManager.getLogger(); - private static final Gson b = (new GsonBuilder()).setPrettyPrinting().create(); - private final File c; -- private final Map d = Maps.newHashMap(); -+ // Paper - replace HashMap is ConcurrentHashMap -+ private final Map d = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.d; } // Paper - OBFHELPER -+ private boolean e = true; -+ private static final ParameterizedType f = new ParameterizedType() { -+ public Type[] getActualTypeArguments() { -+ return new Type[]{JsonListEntry.class}; -+ } -+ -+ public Type getRawType() { -+ return List.class; -+ } -+ -+ public Type getOwnerType() { -+ return null; -+ } -+ }; - - public JsonList(File file) { - this.c = file; -@@ -51,8 +68,13 @@ public abstract class JsonList> { - - @Nullable - public V get(K k0) { -- this.g(); -- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ // Paper start -+ // this.g(); -+ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> { -+ return v.hasExpired() ? null : v; -+ }); -+ // Paper end - } - - public void remove(K k0) { -@@ -81,9 +103,11 @@ public abstract class JsonList> { - // CraftBukkit end - - public boolean isEmpty() { -- return this.d.size() < 1; -+ // return this.d.size() < 1; // Paper -+ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic - } - -+ protected final String getMappingKey(K k0) { return a(k0); } // Paper - OBFHELPER - protected String a(K k0) { - return k0.toString(); - } -@@ -92,8 +116,9 @@ public abstract class JsonList> { - return this.d.containsKey(this.a(k0)); - } - -+ private void removeStaleEntries() { g(); } // Paper - OBFHELPER - private void g() { -- List list = Lists.newArrayList(); -+ /*List list = Lists.newArrayList(); - Iterator iterator = this.d.values().iterator(); - - while (iterator.hasNext()) { -@@ -110,8 +135,10 @@ public abstract class JsonList> { - K k0 = (K) iterator.next(); // CraftBukkit - decompile error - - this.d.remove(this.a(k0)); -- } -+ }*/ - -+ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired); -+ // Paper end - } - - protected abstract JsonListEntry a(JsonObject jsonobject); -@@ -121,6 +148,7 @@ public abstract class JsonList> { - } - - public void save() throws IOException { -+ this.removeStaleEntries(); // Paper - remove expired values before saving - JsonArray jsonarray = new JsonArray(); - - this.d.values().stream().map((jsonlistentry) -> { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 80934fc662b33b1c88dd7a3033792d612a7c7930..2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -618,7 +618,7 @@ public abstract class PlayerList { - } else if (!this.isWhitelisted(gameprofile, event)) { // Paper - //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper - //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted -- } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { -+ } else if (getIPBans().isBanned(socketaddress) && getIPBans().get(socketaddress) != null && !getIPBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans - IpBanEntry ipbanentry = this.l.get(socketaddress); - - chatmessage = new ChatMessage("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); diff --git a/Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch b/Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch deleted file mode 100644 index eead0924bc2a..000000000000 --- a/Spigot-Server-Patches/0264-Use-a-Queue-for-Queueing-Commands.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Aug 2018 02:33:39 -0400 -Subject: [PATCH] Use a Queue for Queueing Commands - -Lists are bad as Queues mmmkay. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index a0804c4df6f047cf913ae70970219617052e853f..2d42b863b3fd83d1ee0532d1fcb63861641ec47b 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -75,7 +75,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - - private static final Logger LOGGER = LogManager.getLogger(); - private static final Pattern k = Pattern.compile("^[a-fA-F0-9]{40}$"); -- private final List serverCommandQueue = Collections.synchronizedList(Lists.newArrayList()); -+ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue - private RemoteStatusListener remoteStatusListener; - public final RemoteControlCommandListener remoteControlCommandListener; - private RemoteControlListener remoteControlListener; -@@ -434,8 +434,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - - public void handleCommandQueue() { - MinecraftTimings.serverCommandTimer.startTiming(); // Spigot -- while (!this.serverCommandQueue.isEmpty()) { -- ServerCommand servercommand = (ServerCommand) this.serverCommandQueue.remove(0); -+ // Paper start - use proper queue -+ ServerCommand servercommand; -+ while ((servercommand = this.serverCommandQueue.poll()) != null) { -+ // Paper end - - // CraftBukkit start - ServerCommand for preprocessing - ServerCommandEvent event = new ServerCommandEvent(console, servercommand.command); diff --git a/Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index 2e0e968f6ba3..000000000000 --- a/Spigot-Server-Patches/0265-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:16:34 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 32e4e59767587455272e685dfd23f945ba05f976..a8e94f69faec93661dc6ae2efeec44b8bfd2e965 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -3,8 +3,10 @@ package org.bukkit.craftbukkit; - import com.google.common.base.Preconditions; - import com.google.common.base.Predicates; - import java.lang.ref.WeakReference; -+import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.List; - import java.util.function.Predicate; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; -@@ -130,9 +132,16 @@ public class CraftChunk implements Chunk { - - @Override - public BlockState[] getTileEntities() { -+ // Paper start -+ return getTileEntities(true); -+ } -+ -+ @Override -+ public BlockState[] getTileEntities(boolean useSnapshot) { - if (!isLoaded()) { - getWorld().getChunkAt(x, z); // Transient load for this tick - } -+ // Paper end - int index = 0; - net.minecraft.world.level.chunk.Chunk chunk = getHandle(); - -@@ -144,11 +153,33 @@ public class CraftChunk implements Chunk { - } - - BlockPosition position = (BlockPosition) obj; -- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); -+ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper -+ } -+ -+ return entities; -+ } -+ -+ // Paper start -+ @Override -+ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { -+ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); -+ if (!isLoaded()) { -+ getWorld().getChunkAt(x, z); // Transient load for this tick -+ } -+ net.minecraft.world.level.chunk.Chunk chunk = getHandle(); -+ -+ List entities = new ArrayList<>(); -+ -+ for (BlockPosition position : chunk.tileEntities.keySet()) { -+ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ if (blockPredicate.test(block)) { -+ entities.add(block.getState(useSnapshot)); -+ } - } - - return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch b/Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index 788112651fd9..000000000000 --- a/Spigot-Server-Patches/0266-Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 15 Aug 2018 01:26:09 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3562950df4868b1393790b1a1ff1fe0dc589c155..5ab0e7183e48134b7a0f736462516b1a8a333b04 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -384,4 +384,10 @@ public class PaperWorldConfig { - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); - } -+ -+ public boolean armorStandTick = true; -+ private void armorStandTick() { -+ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); -+ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index e97d25339b37a70f91022dcb021bbe82fb8f5eda..8d35240405d7f7245f3c7b0b611973d58fa4384f 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -81,9 +81,16 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f leftLegPose; - public Vector3f rightLegPose; - public boolean canMove = true; // Paper -+ // Paper start - Allow ArmorStands not to tick -+ public boolean canTick = true; -+ public boolean canTickSetByAPI = false; -+ private boolean noTickPoseDirty = false; -+ private boolean noTickEquipmentDirty = false; -+ // Paper end - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking - this.handItems = NonNullList.a(2, ItemStack.b); - this.armorItems = NonNullList.a(4, ItemStack.b); - this.headPose = EntityArmorStand.bj; -@@ -179,6 +186,7 @@ public class EntityArmorStand extends EntityLiving { - this.armorItems.set(enumitemslot.b(), itemstack); - } - -+ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled - } - - @Override -@@ -259,6 +267,7 @@ public class EntityArmorStand extends EntityLiving { - } - - nbttagcompound.set("Pose", this.B()); -+ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting - } - - @Override -@@ -290,6 +299,12 @@ public class EntityArmorStand extends EntityLiving { - this.setBasePlate(nbttagcompound.getBoolean("NoBasePlate")); - this.setMarker(nbttagcompound.getBoolean("Marker")); - this.noclip = !this.A(); -+ // Paper start - persist no tick -+ if (nbttagcompound.hasKey("Paper.CanTickOverride")) { -+ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride"); -+ this.canTickSetByAPI = true; -+ } -+ // Paper end - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose"); - - this.g(nbttagcompound1); -@@ -645,7 +660,29 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void tick() { -+ // Paper start -+ if (!this.canTick) { -+ if (this.noTickPoseDirty) { -+ this.noTickPoseDirty = false; -+ this.updatePose(); -+ } -+ -+ if (this.noTickEquipmentDirty) { -+ this.noTickEquipmentDirty = false; -+ this.updateEquipment(); -+ } -+ -+ return; -+ } -+ // Paper end -+ - super.tick(); -+ // Paper start - Split into separate method -+ updatePose(); -+ } -+ -+ public void updatePose() { -+ // Paper end - Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c); - - if (!this.headPose.equals(vector3f)) { -@@ -768,29 +805,36 @@ public class EntityArmorStand extends EntityLiving { - public void setHeadPose(Vector3f vector3f) { - this.headPose = vector3f; - this.datawatcher.set(EntityArmorStand.c, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setBodyPose(Vector3f vector3f) { - this.bodyPose = vector3f; - this.datawatcher.set(EntityArmorStand.d, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftArmPose(Vector3f vector3f) { - this.leftArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.e, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setRightArmPose(Vector3f vector3f) { - this.rightArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.f, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.g, vector3f); -+ - } - - public void setRightLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.bh, vector3f); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 103f935d9b7a2cbe9639528c587d8ac2e5f14d07..348993f3839f984be65daaf87f3510865e8e4670 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -313,5 +313,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { - return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); - } -+ -+ @Override -+ public boolean canTick() { -+ return this.getHandle().canTick; -+ } -+ -+ @Override -+ public void setCanTick(final boolean tick) { -+ this.getHandle().canTick = tick; -+ this.getHandle().canTickSetByAPI = true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch b/Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch deleted file mode 100644 index d248d915c63d..000000000000 --- a/Spigot-Server-Patches/0267-Optimize-BlockPosition-helper-methods.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Aug 2018 12:05:12 -0700 -Subject: [PATCH] Optimize BlockPosition helper methods - -Resolves #1338 - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 370b2c4460d6b52b5ef7da89f5ebf7ef50deb582..4c9ec211470f95d538d1d95c74796190edf99b87 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -121,58 +121,75 @@ public class BlockPosition extends BaseBlockPosition { - - @Override - public BlockPosition up() { -- return this.shift(EnumDirection.UP); -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition up(int i) { -- return this.shift(EnumDirection.UP, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() + i, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down() { -- return this.shift(EnumDirection.DOWN); -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down(int i) { -- return this.shift(EnumDirection.DOWN, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition north() { -- return this.shift(EnumDirection.NORTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition - } - - public BlockPosition north(int i) { -- return this.shift(EnumDirection.NORTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() - i); // Paper - Optimize BlockPosition - } - - public BlockPosition south() { -- return this.shift(EnumDirection.SOUTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition - } - - public BlockPosition south(int i) { -- return this.shift(EnumDirection.SOUTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() + i); // Paper - Optimize BlockPosition - } - - public BlockPosition west() { -- return this.shift(EnumDirection.WEST); -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition west(int i) { -- return this.shift(EnumDirection.WEST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() - i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east() { -- return this.shift(EnumDirection.EAST); -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east(int i) { -- return this.shift(EnumDirection.EAST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() + i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition shift(EnumDirection enumdirection) { -- return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ // Paper Start - Optimize BlockPosition -+ switch(enumdirection) { -+ case UP: -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); -+ case DOWN: -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); -+ case NORTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); -+ case SOUTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); -+ case WEST: -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); -+ case EAST: -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); -+ default: -+ return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ } -+ // Paper End - } - - @Override diff --git a/Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range.patch b/Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range.patch deleted file mode 100644 index 9574b666a3eb..000000000000 --- a/Spigot-Server-Patches/0268-Restore-vanlla-default-mob-spawn-range.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Aug 2018 12:43:16 -0400 -Subject: [PATCH] Restore vanlla default mob-spawn-range - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0efcbab8f8806aeb8dd8bd6384e5a7cee375d100..34ee684901906fc2ef5f0d09680d2686b813e52b 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -165,7 +165,7 @@ public class SpigotWorldConfig - public byte mobSpawnRange; - private void mobSpawnRange() - { -- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); -+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla - log( "Mob Spawn Range: " + mobSpawnRange ); - } - diff --git a/Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch b/Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch deleted file mode 100644 index c9e838ba63b9..000000000000 --- a/Spigot-Server-Patches/0269-Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:42 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 01d5b0db9a34d88172e8c7c84c4e1d0b2562217c..40e39e382092b1a8f831da0cea1557a781c98600 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -45,6 +45,14 @@ import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.storage.loot.LootTables; - import net.minecraft.world.phys.Vec3D; - -+// Paper start -+import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; -+import com.destroystokyo.paper.event.entity.SlimeSwimEvent; -+import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; -+import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Slime; -+// Paper end - // CraftBukkit start - import java.util.ArrayList; - import java.util.List; -@@ -105,6 +113,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.canWander", this.canWander); // Paper - nbttagcompound.setInt("Size", this.getSize() - 1); - nbttagcompound.setBoolean("wasOnGround", this.bp); - } -@@ -119,6 +128,11 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - this.setSize(i + 1, false); - super.loadData(nbttagcompound); -+ // Paper start - check exists before loading or this will be loaded as false -+ if (nbttagcompound.hasKey("Paper.canWander")) { -+ this.canWander = nbttagcompound.getBoolean("Paper.canWander"); -+ } -+ // Paper end - this.bp = nbttagcompound.getBoolean("wasOnGround"); - } - -@@ -398,7 +412,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return !this.a.isPassenger(); -+ return !this.a.isPassenger() && this.a.canWander && new SlimeWanderEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -419,7 +433,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeSwimEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -445,14 +459,18 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander; // Paper - add canWander - } - - @Override - public void e() { - if (--this.c <= 0) { - this.c = 40 + this.a.getRandom().nextInt(60); -- this.b = (float) this.a.getRandom().nextInt(360); -+ // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((Slime) this.a.getBukkitEntity(), (float) this.a.getRandom().nextInt(360)); -+ if (!this.a.canWander || !event.callEvent()) return; -+ this.b = event.getNewYaw(); -+ // Paper end - } - - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.b, false); -@@ -473,7 +491,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean a() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -486,7 +512,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean b() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : --this.b > 0)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return --this.b > 0 && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -494,6 +528,13 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.a.a((Entity) this.a.getGoalTarget(), 10.0F, 10.0F); - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.a.yaw, this.a.eL()); - } -+ -+ // Paper start - clear timer and target when goal resets -+ public void d() { -+ this.b = 0; -+ this.a.setGoalTarget(null); -+ } -+ // Paper end - } - - static class ControllerMoveSlime extends ControllerMove { -@@ -552,4 +593,15 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - } - } -+ -+ // Paper start -+ private boolean canWander = true; -+ public boolean canWander() { -+ return canWander; -+ } -+ -+ public void setWander(boolean canWander) { -+ this.canWander = canWander; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index aa0ac8d8493dc79dda3fed2ff4d80c5b7a7e3df6..cf5c6030105e56813f526e710e5db0c59d88c99e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -35,4 +35,14 @@ public class CraftSlime extends CraftMob implements Slime { - public EntityType getType() { - return EntityType.SLIME; - } -+ -+ // Paper start -+ public boolean canWander() { -+ return getHandle().canWander(); -+ } -+ -+ public void setWander(boolean canWander) { -+ getHandle().setWander(canWander); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch b/Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch deleted file mode 100644 index 55ef5bbfa178..000000000000 --- a/Spigot-Server-Patches/0270-Configurable-speed-for-water-flowing-over-lava.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 8 Aug 2018 16:33:21 -0600 -Subject: [PATCH] Configurable speed for water flowing over lava - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ab0e7183e48134b7a0f736462516b1a8a333b04..f280dbff4a09bc611a9ca565c6d697d08801f53b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -390,4 +390,10 @@ public class PaperWorldConfig { - this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); - log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); - } -+ -+ public int waterOverLavaFlowSpeed; -+ private void waterOverLavaFlowSpeed() { -+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); -+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFluids.java b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -index 0654c77ab059dea2ad06cb16d07950e153d3f15d..0ed8d938b8fafdb03e01a00a201ba3f8597ac6e9 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFluids.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -@@ -23,6 +23,7 @@ import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.material.FluidType; - import net.minecraft.world.level.material.FluidTypeFlowing; - import net.minecraft.world.level.material.FluidTypes; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.level.pathfinder.PathMode; - import net.minecraft.world.level.storage.loot.LootTableInfo; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -100,11 +101,28 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } - -+ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava -+ public int getFlowSpeed(World world, BlockPosition blockposition) { -+ if (this.material == Material.WATER) { -+ if ( -+ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA -+ ) { -+ return world.paperConfig.waterOverLavaFlowSpeed; -+ } -+ } -+ return this.b.a(world); -+ } -+ // Paper end -+ -+ - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - if (iblockdata.getFluid().isSource() || iblockdata1.getFluid().isSource()) { -@@ -117,7 +135,7 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } diff --git a/Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch b/Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch deleted file mode 100644 index 727414b2747d..000000000000 --- a/Spigot-Server-Patches/0271-Optimize-CraftBlockData-Creation.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 23 Aug 2018 11:45:32 -0400 -Subject: [PATCH] Optimize CraftBlockData Creation - -Avoids a hashmap lookup by cacheing a reference to the CraftBlockData -and cloning it when one is needed. - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 10f4015b8c36e4e27cf7d0745ba70b8a9e60aff3..57857cc33603cf278de424b540a3d4a5943584c9 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -375,6 +375,14 @@ public abstract class BlockBase { - this.o = blockbase_info.t; - this.p = blockbase_info.u; - } -+ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time -+ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; -+ -+ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { -+ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); -+ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); -+ } -+ // Paper end - - public void a() { - if (!this.getBlock().o()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 76fd1fea386d0e65c63c529dba772f01d9888407..ed88da727feddc319a650fb35710d16727f6dbd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -509,7 +509,17 @@ public class CraftBlockData implements BlockData { - return craft; - } - -+ // Paper start - optimize creating BlockData to not need a map lookup -+ static { -+ // Initialize cached data for all IBlockData instances after registration -+ Block.REGISTRY_ID.iterator().forEachRemaining(IBlockData::createCraftBlockData); -+ } - public static CraftBlockData fromData(IBlockData data) { -+ return data.createCraftBlockData(); -+ } -+ -+ public static CraftBlockData createData(IBlockData data) { -+ // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); - } - diff --git a/Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch b/Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch deleted file mode 100644 index a37df72fa320..000000000000 --- a/Spigot-Server-Patches/0272-Optimize-RegistryMaterials.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize RegistryMaterials - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/RegistryMaterials.java b/src/main/java/net/minecraft/core/RegistryMaterials.java -index f3f6ed83d509d228944d15fc2b2b4cb85b05e366..18f78a5cb03dd9c8349c28b99d013752e32c9167 100644 ---- a/src/main/java/net/minecraft/core/RegistryMaterials.java -+++ b/src/main/java/net/minecraft/core/RegistryMaterials.java -@@ -30,6 +30,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.RegistryDataPackCodec; - import net.minecraft.resources.ResourceKey; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,7 +39,7 @@ public class RegistryMaterials extends IRegistryWritable { - - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList bf = new ObjectArrayList(256); -- private final Object2IntMap bg = new Object2IntOpenCustomHashMap(SystemUtils.k()); -+ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap bh; - private final BiMap, T> bi; - private final Map bj; -@@ -49,9 +50,9 @@ public class RegistryMaterials extends IRegistryWritable { - public RegistryMaterials(ResourceKey> resourcekey, Lifecycle lifecycle) { - super(resourcekey, lifecycle); - this.bg.defaultReturnValue(-1); -- this.bh = HashBiMap.create(); -- this.bi = HashBiMap.create(); -- this.bj = Maps.newIdentityHashMap(); -+ this.bh = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bi = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bj = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.bk = lifecycle; - } - -@@ -195,7 +196,7 @@ public class RegistryMaterials extends IRegistryWritable { - this.b = collection.toArray(new Object[collection.size()]); - } - -- return SystemUtils.a(this.b, random); -+ return (T) SystemUtils.a(this.b, random); // Paper - Decompile fix - } - - public static Codec> a(ResourceKey> resourcekey, Lifecycle lifecycle, Codec codec) { -@@ -215,7 +216,7 @@ public class RegistryMaterials extends IRegistryWritable { - Iterator iterator = registrymaterials.iterator(); - - while (iterator.hasNext()) { -- T t0 = iterator.next(); -+ T t0 = (T) iterator.next(); // Paper - Decompile fix - - builder.add(new RegistryMaterials.a<>((ResourceKey) registrymaterials.c(t0).get(), registrymaterials.a(t0), t0)); - } diff --git a/Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch b/Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index dca07a67d6cf..000000000000 --- a/Spigot-Server-Patches/0273-Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:51 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 6053894c5250e9a1a0c4aa2d681127dfd652b34f..6c498d4345df35a411d155799ac56e47c9c48114 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -161,6 +161,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - - this.setSize(nbttagcompound.getInt("Size")); -+ // Paper start -+ if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); -+ } -+ // Paper end - } - - @Override -@@ -170,6 +175,11 @@ public class EntityPhantom extends EntityFlying implements IMonster { - nbttagcompound.setInt("AY", this.d.getY()); - nbttagcompound.setInt("AZ", this.d.getZ()); - nbttagcompound.setInt("Size", this.getSize()); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -216,6 +226,15 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return entitysize.a(f); - } - -+ // Paper start -+ java.util.UUID spawningEntity; -+ -+ public java.util.UUID getSpawningEntity() { -+ return spawningEntity; -+ } -+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ // Paper end -+ - class b extends PathfinderGoal { - - private final PathfinderTargetCondition b; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index cfc32acee1e456a0fda12a5faa4035e29d0c3d5e..96a5a6569387a25b15a06aaab3bd9d033547e875 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -4,6 +4,7 @@ import java.util.Iterator; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.stats.ServerStatisticManager; -@@ -73,8 +74,17 @@ public class MobSpawnerPhantom implements MobSpawner { - int k = 1 + random.nextInt(difficultydamagescaler.a().a() + 1); - - for (int l = 0; l < k; ++l) { -+ // Paper start -+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(worldserver, blockposition1), ((EntityPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ // Paper end - EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); -- -+ entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper - entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F); - groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); - worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 6ec7cf434b6586342da3f351466f5c7d72df290d..0cea1d8e23da3a79ef06e43752665a5401b01b4b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -35,4 +35,10 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public EntityType getType() { - return EntityType.PHANTOM; - } -+ -+ // Paper start -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().getSpawningEntity(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0274-Add-More-Creeper-API.patch b/Spigot-Server-Patches/0274-Add-More-Creeper-API.patch deleted file mode 100644 index faced7350eb7..000000000000 --- a/Spigot-Server-Patches/0274-Add-More-Creeper-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:26 -0500 -Subject: [PATCH] Add More Creeper API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index cbb973e077e04e5221bcc837f434b7093bdbcc2a..b47f71ca1f1c8bbd1a521836d9cb5d676a33ec76 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -290,7 +290,18 @@ public class EntityCreeper extends EntityMonster { - } - - public void ignite() { -- this.datawatcher.set(EntityCreeper.d, true); -+ // Paper start -+ setIgnited(true); -+ } -+ -+ public void setIgnited(boolean ignited) { -+ if (isIgnited() != ignited) { -+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); -+ if (event.callEvent()) { -+ this.datawatcher.set(EntityCreeper.d, event.isIgnited()); -+ } -+ } -+ // Paper end - } - - public boolean canCauseHeadDrop() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -index 167b8f0c742be07ee0c5d698e04d6e29addda70c..629518d4bb314a1d46e32397b6fb7b90bce94e83 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -101,4 +101,14 @@ public class CraftCreeper extends CraftMonster implements Creeper { - public EntityType getType() { - return EntityType.CREEPER; - } -+ -+ // Paper start -+ public void setIgnited(boolean ignited) { -+ getHandle().setIgnited(ignited); -+ } -+ -+ public boolean isIgnited() { -+ return getHandle().isIgnited(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch b/Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch deleted file mode 100644 index 8d4a86803ed2..000000000000 --- a/Spigot-Server-Patches/0275-Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 28 Aug 2018 23:04:15 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 4211bdfb213db0781107c67f1522e9689aa7ecfe..45634fded9916dca35a246921efb87964c860339 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -223,10 +223,16 @@ public class CraftInventory implements Inventory { - } - - private int first(ItemStack item, boolean withAmount) { -+ // Paper start -+ return first(item, withAmount, getStorageContents()); -+ } -+ -+ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { -+ // Paper end - if (item == null) { - return -1; - } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal - for (int i = 0; i < inventory.length; i++) { - if (inventory[i] == null) continue; - -@@ -349,6 +355,17 @@ public class CraftInventory implements Inventory { - - @Override - public HashMap removeItem(ItemStack... items) { -+ // Paper start -+ return removeItem(false, items); -+ } -+ -+ @Override -+ public HashMap removeItemAnySlot(ItemStack... items) { -+ return removeItem(true, items); -+ } -+ -+ private HashMap removeItem(boolean searchEntire, ItemStack... items) { -+ // Paper end - Validate.notNull(items, "Items cannot be null"); - HashMap leftover = new HashMap(); - -@@ -359,7 +376,10 @@ public class CraftInventory implements Inventory { - int toDelete = item.getAmount(); - - while (true) { -- int first = first(item, false); -+ // Paper start - Allow searching entire contents -+ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); -+ // Paper end - - // Drat! we don't have this type in the inventory - if (first == -1) { diff --git a/Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch deleted file mode 100644 index 9fbcd0bc7008..000000000000 --- a/Spigot-Server-Patches/0276-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 2 Sep 2018 19:34:33 -0700 -Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted - chunks - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e7103b8021141071712759b1056eccb5e3da93b7..880bbf09f77f59824184c1c9dd1ca3c3df09dae9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -508,7 +508,7 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper - - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ProtoChunkExtension) { diff --git a/Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch b/Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index a8ed3ec81708..000000000000 --- a/Spigot-Server-Patches/0277-Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:20:03 -0500 -Subject: [PATCH] Add ray tracing methods to LivingEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 2b10ae84ee8e9f63382d732e8c051fc47f0c5d9f..a64b2953c43138491cdab3e3e24e2e7ed969e171 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3585,6 +3585,23 @@ public abstract class EntityLiving extends Entity { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } - // Paper start -+ public MovingObjectPosition getRayTrace(int maxDistance) { -+ return getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ } -+ -+ public MovingObjectPosition getRayTrace(int maxDistance, RayTrace.FluidCollisionOption fluidCollisionOption) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = new Vec3D(locX(), locY() + getHeadHeight(), locZ()); -+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); -+ Vec3D end = new Vec3D(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); -+ RayTrace raytrace = new RayTrace(start, end, RayTrace.BlockCollisionOption.OUTLINE, fluidCollisionOption, this); -+ -+ return world.rayTrace(raytrace); -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index bd24b9865f37c34ffd63cd411ddc84abe5ab30d0..c692626b747008a5418ecabf550fc67e3b676f5b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.block.TargetBlockInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -8,6 +9,7 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; -@@ -40,6 +42,8 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -49,6 +53,7 @@ import org.bukkit.attribute.AttributeInstance; - import org.bukkit.block.Block; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; - import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; -@@ -202,6 +207,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return blocks.get(0); - } - -+ // Paper start -+ @Override -+ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()); -+ } -+ -+ @Override -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection()); -+ } -+ -+ @Override -+ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : -+ new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), -+ MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); -+ } -+ // Paper end -+ - @Override - public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { - return getLineOfSight(transparent, maxDistance, 2); diff --git a/Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch b/Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index 74caa5c1f1f6..000000000000 --- a/Spigot-Server-Patches/0278-Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:02:00 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index b6effe1037f3ae59e6faa5f5d039b6ad54bca5d4..87374174dcbf9e7ee448a1cdd9a3528557c3a2ea 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2103,6 +2103,7 @@ public abstract class EntityHuman extends EntityLiving { - this.datawatcher.set(EntityHuman.bl, nbttagcompound); - } - -+ public float getCooldownPeriod() { return this.eR(); } // Paper - OBFHELPER - public float eR() { - return (float) (1.0D / this.b(GenericAttributes.ATTACK_SPEED) * 20.0D); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee3fbf0789b4841a113727397ba6809b2600ff83..a13867ff6d188e7633a91f1e1600116286ac0cd4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2189,6 +2189,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); - } -+ -+ public float getCooldownPeriod() { -+ return getHandle().getCooldownPeriod(); -+ } -+ -+ public float getCooledAttackStrength(float adjustTicks) { -+ return getHandle().getAttackCooldown(adjustTicks); -+ } -+ -+ public void resetCooldown() { -+ getHandle().resetAttackCooldown(); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0279-Improve-death-events.patch b/Spigot-Server-Patches/0279-Improve-death-events.patch deleted file mode 100644 index 8ebe4233d1a0..000000000000 --- a/Spigot-Server-Patches/0279-Improve-death-events.patch +++ /dev/null @@ -1,425 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:39:35 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index b581a6d3ec06498a4c6db92eb50c5d2b28038131..ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -214,6 +214,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ // Paper start - cancellable death event -+ public boolean queueHealthUpdatePacket = false; -+ public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -717,6 +721,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure -+ // Paper start - cancellable death event -+ if (event.isCancelled()) { -+ // make compatible with plugins that might have already set the health in an event listener -+ if (this.getHealth() <= 0) { -+ this.setHealth((float) event.getReviveHealth()); -+ } -+ return; -+ } -+ // Paper end - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -@@ -863,8 +876,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - } -- -- return super.damageEntity(damagesource, f); -+ // Paper start - cancellable death events -+ //return super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = true; -+ boolean damaged = super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = false; -+ if (this.queuedHealthUpdatePacket != null) { -+ this.playerConnection.sendPacket(this.queuedHealthUpdatePacket); -+ this.queuedHealthUpdatePacket = null; -+ } -+ return damaged; -+ // Paper end - } - } - } -diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index f6f79ed9c38206cc6a4feb5504e854a476868aec..7d2b947b3c2b255c01241f2c4a6d7377a0a7c671 100644 ---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -@@ -203,6 +203,7 @@ public class CombatTracker { - this.h = null; - } - -+ public final void reset() { this.g(); } // Paper - OBFHELPER - public void g() { - int i = this.f ? 300 : 100; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 046b191e771ed9be337e095214a67febd768e5f6..b6b4eb9ac883cfdfab5f114767fb5cfb29445730 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1538,6 +1538,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.a(entity, kills, damageSource); } // Paper - OBFHELPER - public void a(Entity entity, int i, DamageSource damagesource) { - if (entity instanceof EntityPlayer) { - CriterionTriggers.c.a((EntityPlayer) entity, this, damagesource); -@@ -2437,6 +2438,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance = 0.0F; - } - -+ public final void onKill(WorldServer worldserver, EntityLiving entityLiving) { this.a(worldserver, entityLiving); } // Paper - OBFHELPER - public void a(WorldServer worldserver, EntityLiving entityliving) {} - - protected void l(double d0, double d1, double d2) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index a64b2953c43138491cdab3e3e24e2e7ed969e171..b3c2976a48c2349e5c22d58dd1ac64a02cd969d5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -189,7 +189,7 @@ public abstract class EntityLiving extends Entity { - protected float aL; - protected float aM; - protected float aN; -- protected int aO; -+ protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; - protected boolean jumping; - public float aR; -@@ -233,6 +233,7 @@ public abstract class EntityLiving extends Entity { - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; - public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper -+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event - - @Override - public float getBukkitYaw() { -@@ -1348,13 +1349,17 @@ public abstract class EntityLiving extends Entity { - if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { -- SoundEffect soundeffect = this.getSoundDeath(); -+ // Paper start - moved into CraftEventFactory event caller for cancellable death event -+ //SoundEffect soundeffect = this.getSoundDeath(); - -- if (flag1 && soundeffect != null) { -- this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -- } -+// if (flag1 && soundeffect != null) { -+// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -+// } -+ this.silentDeath = !flag1; // mark entity as dying silently -+ // Paper end - - this.die(damagesource); -+ this.silentDeath = false; // Paper - cancellable death event - reset to default - } - } else if (flag1) { - this.c(damagesource); -@@ -1493,6 +1498,7 @@ public abstract class EntityLiving extends Entity { - Entity entity = damagesource.getEntity(); - EntityLiving entityliving = this.getKillingEntity(); - -+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below - if (this.aO >= 0 && entityliving != null) { - entityliving.a(this, this.aO, damagesource); - } -@@ -1500,20 +1506,40 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.entityWakeup(); - } -+ */ // Paper - - this.killed = true; -- this.getCombatTracker().g(); -+ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() - if (this.world instanceof WorldServer) { - if (entity != null) { -- entity.a((WorldServer) this.world, this); -+ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill - } - -- this.d(damagesource); -+ // Paper start -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource); -+ if (deathEvent == null || !deathEvent.isCancelled()) { -+ if (this.getKillCount() >= 0 && entityliving != null) { -+ entityliving.runKillTrigger(this, this.getKillCount(), damagesource); -+ } -+ if (this.isSleeping()) { -+ this.entityWakeup(); -+ } -+ this.getCombatTracker().reset(); -+ if (entity != null) { -+ entity.onKill((WorldServer) this.world, this); -+ } -+ } else { -+ this.killed = false; -+ this.setHealth((float) deathEvent.getReviveHealth()); -+ } -+ // Paper end - this.f(entityliving); - } - -+ if (this.killed) { // Paper - this.world.broadcastEntityEffect(this, (byte) 3); - this.setPose(EntityPose.DYING); -+ } // Paper - } - } - -@@ -1521,7 +1547,7 @@ public abstract class EntityLiving extends Entity { - if (!this.world.isClientSide) { - boolean flag = false; - -- if (entityliving instanceof EntityWither) { -+ if (this.killed && entityliving instanceof EntityWither) { // Paper - if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { - BlockPosition blockposition = this.getChunkCoordinates(); - IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); -@@ -1549,7 +1575,8 @@ public abstract class EntityLiving extends Entity { - } - } - -- protected void d(DamageSource damagesource) { -+ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper - Entity entity = damagesource.getEntity(); - int i; - -@@ -1567,15 +1594,18 @@ public abstract class EntityLiving extends Entity { - this.dropDeathLoot(damagesource, i, flag); - } - // CraftBukkit start - Call death event -- CraftEventFactory.callEntityDeathEvent(this, this.drops); -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper -+ this.postDeathDropItems(deathEvent); // Paper - this.drops = new ArrayList<>(); - // CraftBukkit end - - // this.dropInventory();// CraftBukkit - moved up - this.dropExperience(); -+ return deathEvent; // Paper - } - - protected void dropInventory() {} -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled - - // CraftBukkit start - public int getExpReward() { -@@ -1660,6 +1690,7 @@ public abstract class EntityLiving extends Entity { - return SoundEffects.ENTITY_GENERIC_HURT; - } - -+ public final SoundEffect getDeathSoundEffect() { return this.getSoundDeath(); } // Paper - OBFHELPER - @Nullable - protected SoundEffect getSoundDeath() { - return SoundEffects.ENTITY_GENERIC_DEATH; -@@ -2196,10 +2227,12 @@ public abstract class EntityLiving extends Entity { - - } - -+ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER - protected float getSoundVolume() { - return 1.0F; - } - -+ public float getSoundPitch() { return dH();} // Paper - OBFHELPER - protected float dH() { - return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 77de0706aaa32b565cb1e14754e93a1c4a6e15bd..b7fa24318ef43918b6b10ff4ea8acb960527296e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -647,15 +647,25 @@ public class EntityFox extends EntityAnimal { - } - - @Override -- protected void d(DamageSource damagesource) { -- ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND); -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND).cloneItemStack(); // Paper -+ -+ // Paper start - Cancellable death event -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); -+ -+ // Below is code to drop -+ -+ if (deathEvent == null || deathEvent.isCancelled()) { -+ return deathEvent; -+ } -+ // Paper end - - if (!itemstack.isEmpty()) { - this.a(itemstack); - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - } - -- super.d(damagesource); -+ return deathEvent; // Paper - } - - public static boolean a(EntityFox entityfox, EntityLiving entityliving) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -index aa12a0c9f30cd2b8a6de75ff9822843da808ae64..3daa1780a332128bd472fa80039112f3ca9bc4e9 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -@@ -68,11 +68,19 @@ public abstract class EntityHorseChestedAbstract extends EntityHorseAbstract { - this.a((IMaterial) Blocks.CHEST); - } - -- this.setCarryingChest(false); -+ //this.setCarryingChest(false); // Paper - moved to post death logic - } - - } - -+ // Paper start -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { -+ if (this.isCarryingChest() && (event == null || !event.isCancelled())) { -+ this.setCarryingChest(false); -+ } -+ } -+ // Paper end -+ - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 8d35240405d7f7245f3c7b0b611973d58fa4384f..69361caebf0d3caa5195b519a16691705ac5e16a 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -746,7 +746,8 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void killEntity() { -- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event -+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable -+ if (event.isCancelled()) return; // Paper - make cancellable - this.die(); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a13867ff6d188e7633a91f1e1600116286ac0cd4..6c5075ef2420131aa21b403623a5dfa485ee73e5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1839,7 +1839,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void sendHealthUpdate() { -- getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ // Paper start - cancellable death event -+ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ PacketPlayOutUpdateHealth packet = new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); -+ if (this.getHandle().queueHealthUpdatePacket) { -+ this.getHandle().queuedHealthUpdatePacket = packet; -+ } else { -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ // Paper end - } - - public void injectScaledMaxHealth(Collection collection, boolean force) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 877a0ea25f3cea970fa3827b12efc1a44bdcdf9c..fbd24e10b1b966898e7e1556c5f9bd607497d970 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -18,6 +18,8 @@ import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.sounds.SoundEffect; - import net.minecraft.util.Unit; - import net.minecraft.world.EnumHand; - import net.minecraft.world.IInventory; -@@ -802,9 +804,16 @@ public class CraftEventFactory { - public static EntityDeathEvent callEntityDeathEvent(EntityLiving victim, List drops) { - CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); - EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); -+ populateFields(victim, event); // Paper - make cancellable - CraftWorld world = (CraftWorld) entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); - -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - victim.expToDrop = event.getDroppedExp(); - - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -820,8 +829,15 @@ public class CraftEventFactory { - CraftPlayer entity = victim.getBukkitEntity(); - PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); -+ populateFields(victim, event); // Paper - make cancellable - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - - victim.keepLevel = event.getKeepLevel(); - victim.newLevel = event.getNewLevel(); -@@ -838,6 +854,31 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - helper methods for making death event cancellable -+ // Add information to death event -+ private static void populateFields(EntityLiving victim, EntityDeathEvent event) { -+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); -+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); -+ SoundEffect soundEffect = victim.getDeathSoundEffect(); -+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); -+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundCategory().name())); -+ event.setDeathSoundVolume(victim.getDeathSoundVolume()); -+ event.setDeathSoundPitch(victim.getSoundPitch()); -+ } -+ -+ // Play death sound manually -+ private static void playDeathSound(EntityLiving victim, EntityDeathEvent event) { -+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { -+ EntityHuman source = victim instanceof EntityHuman ? (EntityHuman) victim : null; -+ double x = event.getEntity().getLocation().getX(); -+ double y = event.getEntity().getLocation().getY(); -+ double z = event.getEntity().getLocation().getZ(); -+ SoundEffect soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); -+ SoundCategory soundCategory = SoundCategory.valueOf(event.getDeathSoundCategory().name()); -+ victim.world.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); -+ } -+ } -+ // Paper end - /** - * Server methods - */ diff --git a/Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch b/Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch deleted file mode 100644 index d8616782440a..000000000000 --- a/Spigot-Server-Patches/0280-Allow-chests-to-be-placed-with-NBT-data.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Sep 2018 18:43:31 -0500 -Subject: [PATCH] Allow chests to be placed with NBT data - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 24db5dedf8b41b26fa990a7c7317cdb3e89e7fcd..852f9d99001b35f8c97f4445d8f605533d7f6f2f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -298,6 +298,7 @@ public final class ItemStack { - enuminteractionresult = EnumInteractionResult.FAIL; // cancel placement - // PAIL: Remove this when MC-99075 fixed - placeEvent.getPlayer().updateInventory(); -+ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot - // revert back all captured blocks - for (BlockState blockstate : blocks) { - blockstate.update(true, false); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index 51167d776c710decb0107bebcb35bdf43103772b..111f62d0e5b40e945793b8f504f2c035c0884a6a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -327,7 +327,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic - // CraftBukkit start - @Override - public boolean isFilteredNBT() { -- return true; -+ return false; // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch b/Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch deleted file mode 100644 index 34e0d63bf249..000000000000 --- a/Spigot-Server-Patches/0281-Mob-Pathfinding-API.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 13:30:00 -0400 -Subject: [PATCH] Mob Pathfinding API - -Implements Pathfinding API for mobs - -diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9a3edd114c4736b1843844c6ca49da7aea7983d1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -@@ -0,0 +1,141 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.level.pathfinder.PathEntity; -+import net.minecraft.world.level.pathfinder.PathPoint; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.ArrayList; -+import java.util.List; -+ -+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { -+ -+ private final EntityInsentient entity; -+ -+ public PaperPathfinder(EntityInsentient entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public Mob getEntity() { -+ return entity.getBukkitMob(); -+ } -+ -+ @Override -+ public void stopPathfinding() { -+ entity.getNavigation().stopPathfinding(); -+ } -+ -+ @Override -+ public boolean hasPath() { -+ return entity.getNavigation().getPathEntity() != null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult getCurrentPath() { -+ PathEntity path = entity.getNavigation().getPathEntity(); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(Location loc) { -+ Validate.notNull(loc, "Location can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(LivingEntity target) { -+ Validate.notNull(target, "Target can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Override -+ public boolean moveTo(@Nonnull PathResult path, double speed) { -+ Validate.notNull(path, "PathResult can not be null"); -+ PathEntity pathEntity = ((PaperPathResult) path).path; -+ return entity.getNavigation().setDestination(pathEntity, speed); -+ } -+ -+ @Override -+ public boolean canOpenDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); -+ } -+ -+ @Override -+ public void setCanOpenDoors(boolean canOpenDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); -+ } -+ -+ @Override -+ public boolean canPassDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); -+ } -+ -+ @Override -+ public void setCanPassDoors(boolean canPassDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); -+ } -+ -+ @Override -+ public boolean canFloat() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); -+ } -+ -+ @Override -+ public void setCanFloat(boolean canFloat) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); -+ } -+ -+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { -+ -+ private final PathEntity path; -+ PaperPathResult(PathEntity path) { -+ this.path = path; -+ } -+ -+ @Nullable -+ @Override -+ public Location getFinalPoint() { -+ PathPoint point = path.getFinalPoint(); -+ return point != null ? toLoc(point) : null; -+ } -+ -+ @Override -+ public List getPoints() { -+ List points = new ArrayList<>(); -+ for (PathPoint point : path.getPoints()) { -+ points.add(toLoc(point)); -+ } -+ return points; -+ } -+ -+ @Override -+ public int getNextPointIndex() { -+ return path.getNextIndex(); -+ } -+ -+ @Nullable -+ @Override -+ public Location getNextPoint() { -+ if (!path.hasNext()) { -+ return null; -+ } -+ return toLoc(path.getPoints().get(path.getNextIndex())); -+ } -+ } -+ -+ private Location toLoc(PathPoint point) { -+ return new Location(entity.world.getWorld(), point.getX(), point.getY(), point.getZ()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index d134333c736dc1ee1c722d680d7a9c22c1b265bd..06d05b511d623d0247d44989bee85b383a8fb52f 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -100,7 +100,7 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public final PathEntity a(double d0, double d1, double d2, int i) { -+ public final PathEntity calculateDestination(double d0, double d1, double d2) { return a(d0, d1, d2, 0); } public final PathEntity a(double d0, double d1, double d2, int i) { // Paper - OBFHELPER - return this.a(new BlockPosition(d0, d1, d2), i); - } - -@@ -125,7 +125,7 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public PathEntity a(Entity entity, int i) { -+ public final PathEntity calculateDestination(Entity entity) { return a(entity, 0); } public PathEntity a(Entity entity, int i) { - return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - -@@ -190,6 +190,7 @@ public abstract class NavigationAbstract { - return pathentity != null && this.a(pathentity, d0); - } - -+ public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER - public boolean a(@Nullable PathEntity pathentity, double d0) { - if (pathentity == null) { - this.c = null; -@@ -217,7 +218,7 @@ public abstract class NavigationAbstract { - } - } - -- @Nullable -+ @Nullable public PathEntity getPathEntity() { return k(); } @Nullable // Paper - OBFHELPER - public PathEntity k() { - return this.c; - } -@@ -341,6 +342,7 @@ public abstract class NavigationAbstract { - return !this.m(); - } - -+ public void stopPathfinding() { o(); } // Paper - OBFHELPER - public void o() { - this.c = null; - } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -index 606027de777750f6d2ab0d7f1ef387ed4f0c6092..81c3cb9da3f901d2bcf384f7113bdc5c60f9962f 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -@@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3D; - - public class PathEntity { - -- private final List a; -+ private final List a; public List getPoints() { return a; } // Paper - OBFHELPER - private PathPoint[] b = new PathPoint[0]; - private PathPoint[] c = new PathPoint[0]; -- private int e; -+ private int e; public int getNextIndex() { return this.e; } // Paper - OBFHELPER - private final BlockPosition f; - private final float g; - private final boolean h; -+ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper - - public PathEntity(List list, BlockPosition blockposition, boolean flag) { - this.a = list; -@@ -36,7 +37,7 @@ public class PathEntity { - } - - @Nullable -- public PathPoint d() { -+ public PathPoint getFinalPoint() { return d(); } @Nullable public PathPoint d() { // Paper - OBFHELPER - return !this.a.isEmpty() ? (PathPoint) this.a.get(this.a.size() - 1) : null; - } - -@@ -84,7 +85,7 @@ public class PathEntity { - return this.a(entity, this.e); - } - -- public BlockPosition g() { -+ public BlockPosition getNext() { return g(); } public BlockPosition g() { // Paper - OBFHELPER - return ((PathPoint) this.a.get(this.e)).a(); - } - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -index 43cc9430972a18cbf03a590d576ed200e3836017..c260b0ca70cb18811158761c574aee9c3166da28 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -@@ -5,9 +5,9 @@ import net.minecraft.util.MathHelper; - - public class PathPoint { - -- public final int a; -- public final int b; -- public final int c; -+ public final int a; public final int getX() { return a; } // Paper - OBFHELPER -+ public final int b; public final int getY() { return b; } // Paper - OBFHELPER -+ public final int c; public final int getZ() { return c; } // Paper - OBFHELPER - private final int m; - public int d = -1; - public float e; -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -index f2080bd50db04af6eabec4b4b757d6dadfb1a2f5..88be03bd77656235322522c3782b9f9a878b86b1 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -@@ -16,9 +16,9 @@ public abstract class PathfinderAbstract { - protected int d; - protected int e; - protected int f; -- protected boolean g; -- protected boolean h; -- protected boolean i; -+ protected boolean g; public boolean shouldPassDoors() { return g; } public void setShouldPassDoors(boolean b) { g = b; } // Paper - obfhelper -+ protected boolean h; public boolean shouldOpenDoors() { return h; } public void setShouldOpenDoors(boolean b) { h = b; } // Paper - obfhelper -+ protected boolean i; public boolean shouldFloat() { return i; } public void setShouldFloat(boolean b) { i = b; } // Paper - obfhelper - - public PathfinderAbstract() {} - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index eb275ac45def34d5bb1ed696b4f6a4d53d282ab3..28a4e90130f51fd2fda7003fde5b4d0a410e1aef 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -12,8 +12,11 @@ import org.bukkit.loot.LootTable; - public abstract class CraftMob extends CraftLivingEntity implements Mob { - public CraftMob(CraftServer server, EntityInsentient entity) { - super(server, entity); -+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - } - -+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper -+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - @Override - public void setTarget(LivingEntity target) { - EntityInsentient entity = getHandle(); diff --git a/Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch b/Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch deleted file mode 100644 index 3b7bb307af8c..000000000000 --- a/Spigot-Server-Patches/0282-Prevent-chunk-loading-from-Fluid-Flowing.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:36:16 -0400 -Subject: [PATCH] Prevent chunk loading from Fluid Flowing - - -diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -index 2f0f8a44d808875d70123a63487ce1ebe02f53a9..6bb4ec00e40795ced73648fefcd1f5027e0113cd 100644 ---- a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -+++ b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -@@ -176,7 +176,8 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) entry.getKey(); - Fluid fluid1 = (Fluid) entry.getValue(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - - if (this.a(generatoraccess, blockposition, iblockdata, enumdirection, blockposition1, iblockdata1, generatoraccess.getFluid(blockposition1), fluid1.getType())) { - // CraftBukkit start -@@ -203,7 +204,8 @@ public abstract class FluidTypeFlowing extends FluidType { - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -+ IBlockData iblockdata1 = iworldreader.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - Fluid fluid = iblockdata1.getFluid(); - - if (fluid.getType().a((FluidType) this) && this.a(enumdirection, (IBlockAccess) iworldreader, blockposition, iblockdata, blockposition1, iblockdata1)) { -@@ -320,11 +322,18 @@ public abstract class FluidTypeFlowing extends FluidType { - if (enumdirection1 != enumdirection) { - BlockPosition blockposition2 = blockposition.shift(enumdirection1); - short short0 = a(blockposition1, blockposition2); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition2); -+ // Paper start - avoid loading chunks -+ Pair pair = short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition2); -+ if (iblockdatax == null) { -+ continue; -+ } - -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - -@@ -396,11 +405,16 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); - short short0 = a(blockposition, blockposition1); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -- -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ // Paper start -+ Pair pair = (Pair) short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition1); -+ if (iblockdatax == null) continue; -+ -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - Fluid fluid1 = this.a(iworldreader, blockposition1, iblockdata1); diff --git a/Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch deleted file mode 100644 index 22d4952f48b0..000000000000 --- a/Spigot-Server-Patches/0283-Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:55 +0300 -Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -index 7e53d8b787c42f8592140f7de8974bc63e5149b2..d72b800e5f03422d0b2518980b1955ec7d2b08e8 100644 ---- a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -+++ b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -@@ -57,7 +57,7 @@ public class ArgumentBlock { - private final boolean j; - private final Map, Comparable> k = Maps.newLinkedHashMap(); // CraftBukkit - stable - private final Map l = Maps.newHashMap(); -- private MinecraftKey m = new MinecraftKey(""); -+ private MinecraftKey m = new MinecraftKey(""); public final MinecraftKey getBlockKey() { return this.m; } // Paper - OBFHELPER - private BlockStateList n; - private IBlockData o; - @Nullable -@@ -86,11 +86,13 @@ public class ArgumentBlock { - return this.p; - } - -+ public final @Nullable MinecraftKey getTagKey() { return d(); } // Paper - OBFHELPER - @Nullable - public MinecraftKey d() { - return this.q; - } - -+ public final ArgumentBlock parse(boolean parseTile) throws CommandSyntaxException { return this.a(parseTile); } // Paper - OBFHELPER - public ArgumentBlock a(boolean flag) throws CommandSyntaxException { - this.s = this::l; - if (this.i.canRead() && this.i.peek() == '#') { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 7f790c484fec77e1d1f1dc6abe0daa19d009ae46..8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -39,12 +39,14 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import net.minecraft.commands.arguments.blocks.ArgumentBlock; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.item.ItemBlock; - import org.apache.commons.codec.binary.Base64; -@@ -84,6 +86,12 @@ import org.bukkit.persistence.PersistentDataContainer; - import static org.spigotmc.ValidateUtils.*; - // Spigot end - -+// Paper start -+import com.destroystokyo.paper.Namespaced; -+import com.destroystokyo.paper.NamespacedTag; -+import java.util.Collections; -+// Paper end -+ - /** - * Children must include the following: - * -@@ -267,6 +275,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Specific(Specific.To.NBT) - static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); - static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); -+ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); -+ // Paper end - - // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 - private String displayName; -@@ -280,6 +292,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private int hideFlag; - private boolean unbreakable; - private int damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ private Set placeableKeys = Sets.newHashSet(); -+ private Set destroyableKeys = Sets.newHashSet(); -+ // Paper end - - private static final Set HANDLED_TAGS = Sets.newHashSet(); - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); -@@ -317,6 +333,15 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.hideFlag = meta.hideFlag; - this.unbreakable = meta.unbreakable; - this.damage = meta.damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (meta.hasPlaceableKeys()) { -+ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); -+ } -+ -+ if (meta.hasDestroyableKeys()) { -+ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); -+ } -+ // Paper end - this.unhandledTags.putAll(meta.unhandledTags); - this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); - -@@ -380,6 +405,31 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); - } - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (tag.hasKey(CAN_DESTROY.NBT)) { -+ NBTTagList list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(namespaced); -+ } -+ } -+ -+ if (tag.hasKey(CAN_PLACE_ON.NBT)) { -+ NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(namespaced); -+ } -+ } -+ // Paper end - - Set keys = tag.getKeys(); - for (String key : keys) { -@@ -518,6 +568,34 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); -+ if (canPlaceOnSerialized != null) { -+ for (Object canPlaceOnElement : canPlaceOnSerialized) { -+ String canPlaceOnRaw = (String) canPlaceOnElement; -+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(value); -+ } -+ } -+ -+ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); -+ if (canDestroySerialized != null) { -+ for (Object canDestroyElement : canDestroySerialized) { -+ String canDestroyRaw = (String) canDestroyElement; -+ Namespaced value = this.deserializeNamespaced(canDestroyRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(value); -+ } -+ } -+ // Paper end -+ - String internal = SerializableMeta.getString(map, "internal", true); - if (internal != null) { - ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); -@@ -646,6 +724,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (hasDamage()) { - itemTag.setInt(DAMAGE.NBT, damage); - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List items = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List items = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_DESTROY.NBT, createNonComponentStringList(items)); -+ } -+ // Paper end - - for (Map.Entry e : unhandledTags.entrySet()) { - itemTag.set(e.getKey(), e.getValue()); -@@ -662,6 +757,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ static NBTTagList createNonComponentStringList(List list) { -+ if (list == null || list.isEmpty()) { -+ return null; -+ } -+ -+ NBTTagList tagList = new NBTTagList(); -+ for (String value : list) { -+ tagList.add(NBTTagString.a(value)); // Paper - NBTTagString.of(String str) -+ } -+ -+ return tagList; -+ } -+ // Paper end -+ - NBTTagList createStringList(List list) { - if (list == null) { - return null; -@@ -745,7 +855,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Overridden - boolean isEmpty() { -- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); -+ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values - } - - // Paper start -@@ -1169,7 +1279,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hideFlag == that.hideFlag) - && (this.isUnbreakable() == that.isUnbreakable()) - && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -- && (this.version == that.version); -+ && (this.version == that.version) -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) -+ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); -+ // Paper end - } - - /** -@@ -1204,6 +1318,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (hasDamage() ? this.damage : 0); - hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); - hash = 61 * hash + version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); -+ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); -+ // Paper end - return hash; - } - -@@ -1228,6 +1346,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.unbreakable = this.unbreakable; - clone.damage = this.damage; - clone.version = this.version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (this.placeableKeys != null) { -+ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); -+ } -+ if (this.destroyableKeys != null) { -+ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); -+ } -+ // Paper end - return clone; - } catch (CloneNotSupportedException e) { - throw new Error(e); -@@ -1285,6 +1411,24 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(DAMAGE.BUKKIT, damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List cerealPlaceable = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List cerealDestroyable = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); -+ } -+ // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); - if (!internalTags.isEmpty()) { -@@ -1449,6 +1593,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaArmorStand.SHOW_ARMS.NBT, - CraftMetaArmorStand.SMALL.NBT, - CraftMetaArmorStand.MARKER.NBT, -+ CAN_DESTROY.NBT, -+ CAN_PLACE_ON.NBT, - // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, -@@ -1476,4 +1622,147 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - // Paper end - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanDestroy() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanDestroy(Set canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanPlaceOn() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanPlaceOn(Set canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); -+ } -+ -+ @Override -+ public Set getDestroyableKeys() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); -+ } -+ -+ @Override -+ public void setDestroyableKeys(Collection canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.destroyableKeys.clear(); -+ this.destroyableKeys.addAll(canDestroy); -+ } -+ -+ @Override -+ public Set getPlaceableKeys() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); -+ } -+ -+ @Override -+ public void setPlaceableKeys(Collection canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.placeableKeys.clear(); -+ this.placeableKeys.addAll(canPlaceOn); -+ } -+ -+ @Override -+ public boolean hasPlaceableKeys() { -+ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); -+ } -+ -+ @Override -+ public boolean hasDestroyableKeys() { -+ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); -+ } -+ -+ @Deprecated -+ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { -+ if (beingSet.stream().anyMatch(Material::isLegacy)) { -+ throw new IllegalArgumentException("Set must not contain any legacy materials!"); -+ } -+ -+ toUpdate.clear(); -+ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); -+ } -+ -+ @Deprecated -+ private Set legacyGetMatsFromKeys(Collection names) { -+ Set mats = Sets.newHashSet(); -+ for (Namespaced key : names) { -+ if (!(key instanceof org.bukkit.NamespacedKey)) { -+ continue; -+ } -+ -+ Material material = Material.matchMaterial(key.toString(), false); -+ if (material != null) { -+ mats.add(material); -+ } -+ } -+ -+ return mats; -+ } -+ -+ private @Nullable Namespaced deserializeNamespaced(String raw) { -+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; -+ ArgumentBlock blockParser = new ArgumentBlock(new com.mojang.brigadier.StringReader(raw), true); -+ try { -+ blockParser = blockParser.parse(false); -+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { -+ e.printStackTrace(); -+ return null; -+ } -+ -+ MinecraftKey key; -+ if (isTag) { -+ key = blockParser.getTagKey(); -+ } else { -+ key = blockParser.getBlockKey(); -+ } -+ -+ if (key == null) { -+ return null; -+ } -+ -+ // don't DC the player if something slips through somehow -+ Namespaced resource = null; -+ try { -+ if (isTag) { -+ resource = new NamespacedTag(key.getNamespace(), key.getKey()); -+ } else { -+ resource = CraftNamespacedKey.fromMinecraft(key); -+ } -+ } catch (IllegalArgumentException ex) { -+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); -+ ex.printStackTrace(); -+ } -+ -+ return resource; -+ } -+ -+ private @Nonnull String serializeNamespaced(Namespaced resource) { -+ return resource.toString(); -+ } -+ -+ // not a fan of this -+ private boolean ofAcceptableType(Collection namespacedResources) { -+ -+ for (Namespaced resource : namespacedResources) { -+ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch deleted file mode 100644 index 29f93fd83f38..000000000000 --- a/Spigot-Server-Patches/0284-Prevent-Mob-AI-Rules-from-Loading-Chunks.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:56:36 -0400 -Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -index b5c7b39a49afae1089a293b9b06bdd94deed1f64..61a62c093b24c43064f116630d85096159e082d3 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -@@ -30,11 +30,13 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - private final Block g; - private final EntityInsentient entity; - private int i; -+ private World world; // Paper - - public PathfinderGoalRemoveBlock(Block block, EntityCreature entitycreature, double d0, int i) { - super(entitycreature, d0, 24, i); - this.g = block; - this.entity = entitycreature; -+ this.world = entitycreature.world; // Paper - } - - @Override -@@ -132,7 +134,9 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Nullable - private BlockPosition a(BlockPosition blockposition, IBlockAccess iblockaccess) { -- if (iblockaccess.getType(blockposition).a(this.g)) { -+ Block block = world.getBlockIfLoaded(blockposition); // Paper -+ if (block == null) return null; // Paper -+ if (block.a(this.g)) { // Paper - return blockposition; - } else { - BlockPosition[] ablockposition = new BlockPosition[]{blockposition.down(), blockposition.west(), blockposition.east(), blockposition.north(), blockposition.south(), blockposition.down().down()}; -@@ -142,7 +146,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - for (int j = 0; j < i; ++j) { - BlockPosition blockposition1 = ablockposition1[j]; - -- if (iblockaccess.getType(blockposition1).a(this.g)) { -+ if (iblockaccess.getBlockIfLoaded(blockposition1).a(this.g)) { // Paper - return blockposition1; - } - } -@@ -153,7 +157,7 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Override - protected boolean a(IWorldReader iworldreader, BlockPosition blockposition) { -- IChunkAccess ichunkaccess = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = iworldreader.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a(this.g) && ichunkaccess.getType(blockposition.up()).isAir() && ichunkaccess.getType(blockposition.up(2)).isAir(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -index 129ea3857969ddb99e15ae817ee3eec67b4c3ccf..f9c40c8223109a9a40e7e7523c8f1f2e5aeddba1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -+++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -@@ -13,6 +13,7 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntityCreature; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; - import net.minecraft.world.level.IBlockAccess; -+import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.pathfinder.PathType; - import net.minecraft.world.level.pathfinder.PathfinderNormal; - import net.minecraft.world.phys.Vec3D; -@@ -128,6 +129,7 @@ public class RandomPositionGenerator { - } - - blockposition2 = new BlockPosition((double) k1 + entitycreature.locX(), (double) l1 + entitycreature.locY(), (double) i2 + entitycreature.locZ()); -+ if (!entitycreature.world.isLoaded(blockposition2)) continue; // Paper - if (blockposition2.getY() >= 0 && blockposition2.getY() <= entitycreature.world.getBuildHeight() && (!flag3 || entitycreature.a(blockposition2)) && (!flag2 || navigationabstract.a(blockposition2))) { - if (flag1) { - blockposition2 = a(blockposition2, random.nextInt(l + 1) + i1, entitycreature.world.getBuildHeight(), (blockposition3) -> { -@@ -135,7 +137,8 @@ public class RandomPositionGenerator { - }); - } - -- if (flag || !entitycreature.world.getFluid(blockposition2).a((Tag) TagsFluid.WATER)) { -+ Fluid fluid = entitycreature.world.getFluidIfLoaded(blockposition2); // Paper -+ if (flag || (fluid != null && !fluid.a((Tag) TagsFluid.WATER))) { // Paper - PathType pathtype = PathfinderNormal.a((IBlockAccess) entitycreature.world, blockposition2.i()); - - if (entitycreature.a(pathtype) == 0.0F) { diff --git a/Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch b/Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch deleted file mode 100644 index 7a2091505298..000000000000 --- a/Spigot-Server-Patches/0285-Prevent-mob-spawning-from-loading-generating-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:12:57 -0400 -Subject: [PATCH] Prevent mob spawning from loading/generating chunks - -also prevents if out of world border bounds - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 1969d1002b3182338614a2be0519fcdc385b7a44..5307488fa48ffa91446dd4457de1ce6a8f61da61 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -176,9 +176,9 @@ public final class SpawnerCreature { - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); -- IBlockData iblockdata = ichunkaccess.getType(blockposition); -+ IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn - -- if (!iblockdata.isOccluding(ichunkaccess, blockposition)) { -+ if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - int j = 0; - int k = 0; -@@ -207,7 +207,7 @@ public final class SpawnerCreature { - if (entityhuman != null) { - double d2 = entityhuman.h(d0, (double) i, d1); - -- if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2)) { -+ if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { - biomesettingsmobs_c = a(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPosition) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { diff --git a/Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch deleted file mode 100644 index 681fbbbb312c..000000000000 --- a/Spigot-Server-Patches/0286-Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:47:01 -0400 -Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning - -Uses an EnumMap as well as a Set paired List for O(1) contains calls. - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -index 5adaf5fdaaec25220878213df2c0839ccf025d63..233ae33b5cbf1aafc7d2632149ccb84c0b243162 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -@@ -30,18 +30,27 @@ public class BiomeSettingsMobs { - }, (enumcreaturetype) -> { - return ImmutableList.of(); - })), ImmutableMap.of(), false); -+ // Paper start- decompile error workaround -+ private static class bProxy extends BiomeSettingsMobs.b { -+ private bProxy(double d0, double d1) { -+ super(d0, d1); -+ } -+ } -+ private static class cProxy extends BiomeSettingsMobs.c { -+ public cProxy(EntityTypes entitytypes, int i, int j, int k) { -+ super(entitytypes, i, j, k); -+ } -+ }; -+ // Paper end - public static final MapCodec c = RecordCodecBuilder.mapCodec((instance) -> { -- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { -+ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder - return biomesettingsmobs.d; - }); -- Codec codec = EnumCreatureType.g; -- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); -- Logger logger = BiomeSettingsMobs.LOGGER; -+ // Paper - remove unused vars - -- logger.getClass(); -- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(SystemUtils.a("Spawn data: ", logger::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { -+ return instance.group(recordcodecbuilder, Codec.simpleMap(EnumCreatureType.g, cProxy.b.listOf().promotePartial(SystemUtils.a("Spawn data: ", BiomeSettingsMobs.LOGGER::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER - return biomesettingsmobs.e; -- }), Codec.simpleMap(IRegistry.ENTITY_TYPE, BiomeSettingsMobs.b.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { -+ }), Codec.simpleMap(IRegistry.ENTITY_TYPE, bProxy.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy - return biomesettingsmobs.f; - }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(BiomeSettingsMobs::b)).apply(instance, BiomeSettingsMobs::new); - }); -@@ -76,11 +85,43 @@ public class BiomeSettingsMobs { - - public static class a { - -- private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { -+ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it -+ public static class MobList extends java.util.ArrayList { -+ java.util.Set biomes = new java.util.HashSet<>(); -+ -+ @Override -+ public boolean contains(Object o) { -+ return biomes.contains(o); -+ } -+ -+ @Override -+ public boolean add(BiomeSettingsMobs.c BiomeSettingsMobs) { -+ biomes.add(BiomeSettingsMobs); -+ return super.add(BiomeSettingsMobs); -+ } -+ -+ @Override -+ public BiomeSettingsMobs.c remove(int index) { -+ BiomeSettingsMobs.c removed = super.remove(index); -+ if (removed != null) { -+ biomes.remove(removed); -+ } -+ return removed; -+ } -+ -+ @Override -+ public void clear() { -+ biomes.clear(); -+ super.clear(); -+ } -+ } -+ // use toImmutableEnumMap collector -+ private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { - return enumcreaturetype; - }, (enumcreaturetype) -> { -- return Lists.newArrayList(); -+ return new MobList(); // Use MobList instead of ArrayList - })); -+ // Paper end - private final Map, BiomeSettingsMobs.b> b = Maps.newLinkedHashMap(); - private float c = 0.1F; - private boolean d; diff --git a/Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch b/Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index 110e0093a45f..000000000000 --- a/Spigot-Server-Patches/0287-Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:21 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -Fixed an issue where a furnace's cook-speed multiplier rounds down -to the nearest Integer when updating its current cook time. - -Modified by: Eric Su - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index deaa4c136c23dc6c258cc1ce68523b3c007c80f9..e630e8d3e115d2a0177849ad8258a2304b9d3e9d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -40,6 +40,7 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start -+import java.util.List; - import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.craftbukkit.inventory.CraftItemStack; -@@ -58,6 +59,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - protected NonNullList items; - public int burnTime; - private int ticksForCurrentFuel; -+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API - public int cookTime; - public int cookTimeTotal; - protected final IContainerProperties b; -@@ -258,6 +260,11 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.n.put(new MinecraftKey(s), nbttagcompound1.getInt(s)); - } - -+ // Paper start - cook speed API -+ if (nbttagcompound.hasKey("Paper.CookSpeedMultiplier")) { -+ this.cookSpeedMultiplier = nbttagcompound.getDouble("Paper.CookSpeedMultiplier"); -+ } -+ // Paper end - } - - @Override -@@ -266,6 +273,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - nbttagcompound.setShort("BurnTime", (short) this.burnTime); - nbttagcompound.setShort("CookTime", (short) this.cookTime); - nbttagcompound.setShort("CookTimeTotal", (short) this.cookTimeTotal); -+ nbttagcompound.setDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API - ContainerUtil.a(nbttagcompound, this.items); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - -@@ -326,7 +334,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - - if (this.isBurning() && this.canBurn(irecipe)) { - ++this.cookTime; -- if (this.cookTime == this.cookTimeTotal) { -+ if (this.cookTime >= this.cookTimeTotal) { // Paper - cook speed multiplier API - this.cookTime = 0; - this.cookTimeTotal = this.getRecipeCookingTime(); - this.burn(irecipe); -@@ -426,9 +434,13 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } - } - -- protected int getRecipeCookingTime() { -- return (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier -+ public int getRecipeCookingTime() { -+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ -+ int cookTime = (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); - } -+ // Paper end - - public static boolean isFuel(ItemStack itemstack) { - return f().containsKey(itemstack.getItem()); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -index 760fe719f2f8836c41f6a49d8a795703b2474390..86ad5f78eecc01863897838cb1f311f5dd3d996d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -@@ -63,4 +63,20 @@ public abstract class CraftFurnace extends CraftCon - public void setCookTimeTotal(int cookTimeTotal) { - this.getSnapshot().cookTimeTotal = cookTimeTotal; - } -+ -+ // Paper start - cook speed multiplier API -+ @Override -+ public double getCookSpeedMultiplier() { -+ return this.getSnapshot().cookSpeedMultiplier; -+ } -+ -+ @Override -+ public void setCookSpeedMultiplier(double multiplier) { -+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); -+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); -+ T snapshot = this.getSnapshot(); -+ snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookTimeTotal = snapshot.getRecipeCookingTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch b/Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch deleted file mode 100644 index df8c61a8595b..000000000000 --- a/Spigot-Server-Patches/0288-PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:53:23 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index d4b8126f12fdf7d9b4f882d3ed7d8da544ed9e8a..867478484c0ba4ff467b96e458689937299b981d 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -132,11 +132,11 @@ public abstract class MobSpawnerAbstract { - - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); - if (type != null) { -- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( - MCUtil.toLocation(world, d3, d4, d5), - type, -- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ MCUtil.toLocation(world, blockposition) - ); - if (!event.callEvent()) { - flag = true; diff --git a/Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch b/Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch deleted file mode 100644 index 21a0e7b36dc3..000000000000 --- a/Spigot-Server-Patches/0289-Catch-JsonParseException-in-Entity-and-TE-names.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 22 Sep 2018 15:56:59 -0400 -Subject: [PATCH] Catch JsonParseException in Entity and TE names - -As a result, data that no longer parses correctly will not crash the server -instead just logging the exception and continuing (and in most cases should -fix the data) - -Player data is fixed pretty much immediately but some block data (like -Shulkers) may need to be changed in order for it to re-save properly - -No more crashing though. - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index cd7dc7d90efddb8a1bb50cd964b43d18cf9c83d1..35d1444c5b75d9a3a6cface5dd70aea0a08ac89d 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -7,6 +7,8 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -514,4 +516,19 @@ public final class MCUtil { - return null; - } - } -+ -+ @Nullable -+ public static IChatBaseComponent getBaseComponentFromNbt(String key, NBTTagCompound compound) { -+ if (!compound.hasKey(key)) { -+ return null; -+ } -+ String string = compound.getString(key); -+ try { -+ return IChatBaseComponent.ChatSerializer.jsonToComponent(string); -+ } catch (com.google.gson.JsonParseException e) { -+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); -+ } -+ -+ return null; -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 94adf4d3b3a367e2a7fa383f1da6fb3b02b35c85..3fcdff3649c725580456dfc965d6c83bd5afe3da 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -12,6 +12,7 @@ import net.minecraft.commands.ICommandListener; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; -@@ -72,7 +73,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - this.command = nbttagcompound.getString("Command"); - this.successCount = nbttagcompound.getInt("SuccessCount"); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.setName(IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"))); -+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound)); // Paper - Catch ParseException - } - - if (nbttagcompound.hasKeyOfType("TrackOutput", 1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -index fd8d39d04f39ea8aa389deb66ca0ddaa3e282c40..45958ffedca64e08e347ae65033700c0d798beb5 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.ItemStack; -@@ -70,7 +71,7 @@ public class TileEntityBanner extends TileEntity implements INamableTileEntity { - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - super.load(iblockdata, nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.a = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.a = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - if (this.hasWorld()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -index 19739ad1fb01c767288da2667a48909e4c1c36cc..fb7a1a854efcf42f0351ef521aff67d5fcc4ab27 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -@@ -4,6 +4,7 @@ import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.ChestLock; -@@ -30,7 +31,7 @@ public abstract class TileEntityContainer extends TileEntity implements IInvento - super.load(iblockdata, nbttagcompound); - this.chestLock = ChestLock.b(nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.customName = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - } diff --git a/Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch b/Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch deleted file mode 100644 index e69ce43f71f6..000000000000 --- a/Spigot-Server-Patches/0290-Honor-EntityAgeable.ageLock.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Sep 2018 20:59:53 -0500 -Subject: [PATCH] Honor EntityAgeable.ageLock - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAgeable.java b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -index ea356ff0f91083195899cc2bb84b2fde504163b4..850135582c41893823c43a78a016c7791755b8b5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAgeable.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -@@ -82,6 +82,7 @@ public abstract class EntityAgeable extends EntityCreature { - } - - public void setAge(int i, boolean flag) { -+ if (ageLocked) return; // Paper - GH-1459 - int j = this.getAge(); - int k = j; - diff --git a/Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch b/Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch deleted file mode 100644 index 0d8105088d98..000000000000 --- a/Spigot-Server-Patches/0291-Configurable-connection-throttle-kick-message.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 2 Oct 2018 09:57:50 +0100 -Subject: [PATCH] Configurable connection throttle kick message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 62621562137cba4804f0465c58d25ca2786328e5..7178b37f7978c7e9031a22726005c5099fd78fe0 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -281,6 +281,11 @@ public class PaperConfig { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } - -+ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; -+ private static void connectionThrottleKickMessage() { -+ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 24486bc7290ec6ef1e00a94e289ca35b804ab172..3d5381a6737876d3d7de40cacef900ab7ad27e27 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage("Connection throttled! Please wait before reconnecting."); -+ ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; diff --git a/Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch b/Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch deleted file mode 100644 index 06025aa8c5e4..000000000000 --- a/Spigot-Server-Patches/0292-Hook-into-CB-plugin-rewrites.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 3 Oct 2018 20:09:18 -0400 -Subject: [PATCH] Hook into CB plugin rewrites - -Allows us to do fun stuff like rewrite the OBC util fastutil location to -our own relocation. Also lets us rewrite NMS calls for when we're -debugging in an IDE pre-relocate. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 45cbdcfc131bbc0e2bf23cc30a572df72eecd51c..49e5a86c223f1b28ce7da6ced276b2f880777856 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -6,7 +6,9 @@ import java.io.FileOutputStream; - import java.io.InputStream; - import java.util.Arrays; - import java.util.Enumeration; -+import java.util.HashMap; - import java.util.HashSet; -+import java.util.Map; - import java.util.Set; - import java.util.jar.JarEntry; - import java.util.jar.JarFile; -@@ -20,10 +22,15 @@ import org.bukkit.plugin.AuthorNagException; - import org.objectweb.asm.ClassReader; - import org.objectweb.asm.ClassVisitor; - import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.FieldVisitor; -+import org.objectweb.asm.Handle; -+import org.objectweb.asm.Label; - import org.objectweb.asm.MethodVisitor; - import org.objectweb.asm.Opcodes; - import org.objectweb.asm.Type; - -+import javax.annotation.Nonnull; -+ - /** - * This file is imported from Commodore. - * -@@ -46,6 +53,42 @@ public class Commodore - "org/bukkit/inventory/ItemStack (I)V setTypeId" - ) ); - -+ // Paper start - Plugin rewrites -+ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); -+ private static Map initReplacementsMap() -+ { -+ Map getAndRemove = new HashMap<>(); -+ // Be wary of maven shade's relocations -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location -+ -+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) -+ { -+ // unversion incoming calls for pre-relocate debug work -+ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; -+ -+ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ } -+ -+ return getAndRemove; -+ } -+ -+ @Nonnull -+ private static String getOriginalOrRewrite(@Nonnull String original) -+ { -+ String rewrite = null; -+ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) -+ { -+ if ( original.contains( entry.getKey() ) ) -+ { -+ rewrite = original.replace( entry.getValue(), "" ); -+ } -+ } -+ -+ return rewrite != null ? rewrite : original; -+ } -+ // Paper end -+ - public static void main(String[] args) - { - OptionParser parser = new OptionParser(); -@@ -130,15 +173,86 @@ public class Commodore - - cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) - { -+ // Paper start - Rewrite plugins -+ @Override -+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ if ( signature != null ) { -+ signature = getOriginalOrRewrite( signature ); -+ } -+ -+ return super.visitField( access, name, desc, signature, value) ; -+ } -+ // Paper end -+ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { - return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) - { -+ // Paper start - Plugin rewrites -+ @Override -+ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) -+ { -+ // Paper start - Rewrite plugins -+ name = getOriginalOrRewrite( name ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ -+ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); -+ } -+ -+ @Override -+ public void visitTypeInsn(int opcode, String type) -+ { -+ type = getOriginalOrRewrite( type ); -+ -+ super.visitTypeInsn( opcode, type ); -+ } -+ -+ @Override -+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { -+ for ( int i = 0; i < local.length; i++ ) -+ { -+ if ( !( local[i] instanceof String ) ) { continue; } -+ -+ local[i] = getOriginalOrRewrite( (String) local[i] ); -+ } -+ -+ for ( int i = 0; i < stack.length; i++ ) -+ { -+ if ( !( stack[i] instanceof String ) ) { continue; } -+ -+ stack[i] = getOriginalOrRewrite( (String) stack[i] ); -+ } -+ -+ super.visitFrame( type, nLocal, local, nStack, stack ); -+ } -+ -+ @Override -+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) -+ { -+ descriptor = getOriginalOrRewrite( descriptor ); -+ -+ super.visitLocalVariable( name, descriptor, signature, start, end, index ); -+ } -+ // Paper end - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) - { -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ - if ( owner.equals( "org/bukkit/block/Biome" ) ) - { - switch ( name ) -@@ -270,6 +384,14 @@ public class Commodore - return; - } - -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner) ; -+ if (desc != null) -+ { -+ desc = getOriginalOrRewrite(desc); -+ } -+ // Paper end -+ - if ( modern ) - { - if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch b/Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index d97a31a735c9..000000000000 --- a/Spigot-Server-Patches/0293-Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:44 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 3b74ade60b3b0ae0e908866cb4ac11acd75620ff..9645d052069957311478a1ceca42ad52f7a9aa0b 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -165,6 +165,7 @@ public class EntityVex extends EntityMonster { - this.a(1, flag); - } - -+ public void setOwner(EntityInsentient entityinsentient) { a(entityinsentient); } // Paper - OBFHELPER - public void a(EntityInsentient entityinsentient) { - this.c = entityinsentient; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 962d6017f6acc47ebe4b754ccd9b97a1fc97cc58..30e2c169388b09b94d801be7543e75ea0bd56fcd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -21,6 +21,10 @@ public class CraftVex extends CraftMonster implements Vex { - net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); - return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; - } -+ -+ public void setSummoner(org.bukkit.entity.Mob summoner) { -+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/0294-Add-sun-related-API.patch b/Spigot-Server-Patches/0294-Add-sun-related-API.patch deleted file mode 100644 index bf9961871d7b..000000000000 --- a/Spigot-Server-Patches/0294-Add-sun-related-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:21 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 41566398f5eee6cf93376f2e2200728bb6d2181c..db72b685f4a4b95f345f1d34f9eeb83b8731120a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -1597,6 +1597,7 @@ public abstract class EntityInsentient extends EntityLiving { - - } - -+ public boolean isInDaylight() { return this.eG(); } // Paper - OBFHELPER - protected boolean eG() { - if (this.world.isDay() && !this.world.isClientSide) { - float f = this.aR(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 880bbf09f77f59824184c1c9dd1ca3c3df09dae9..95b4774b7696fa9711d7169d06a23c70364bfdb2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -865,6 +865,13 @@ public class CraftWorld implements World { - } - } - -+ // Paper start -+ @Override -+ public boolean isDayTime() { -+ return getHandle().isDay(); -+ } -+ // Paper end -+ - @Override - public long getGameTime() { - return world.worldData.getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 28a4e90130f51fd2fda7003fde5b4d0a410e1aef..06cbe63ef04e0de824ac0b9d545b6da1f53701b3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -78,4 +78,11 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public long getSeed() { - return getHandle().lootTableSeed; - } -+ -+ // Paper start -+ @Override -+ public boolean isInDaylight() { -+ return getHandle().isInDaylight(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0295-Turtle-API.patch b/Spigot-Server-Patches/0295-Turtle-API.patch deleted file mode 100644 index 5d55bbc3f4ad..000000000000 --- a/Spigot-Server-Patches/0295-Turtle-API.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 29 Sep 2018 16:08:23 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 62276550627bfe453794a2b3101426fe05a585ff..6a156a488bc073b3b60f4d1081e3f2ab65ba9e96 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -14,7 +14,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - protected int c; - protected int d; - private int g; -- protected BlockPosition e; -+ protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index bf224c97854daa379c61affff6a0ac9524c2c35d..09a6310af6712d36c20167256b60dc3235e76021 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -93,7 +94,7 @@ public class EntityTurtle extends EntityAnimal { - this.datawatcher.set(EntityTurtle.bp, blockposition); - } - -- private BlockPosition getHomePos() { -+ public BlockPosition getHomePos() { // Paper - public - return (BlockPosition) this.datawatcher.get(EntityTurtle.bp); - } - -@@ -109,31 +110,37 @@ public class EntityTurtle extends EntityAnimal { - return (Boolean) this.datawatcher.get(EntityTurtle.bq); - } - -- private void setHasEgg(boolean flag) { -+ public void setHasEgg(boolean flag) { // Paper - this.datawatcher.set(EntityTurtle.bq, flag); - } - -+ public final boolean isDigging() { return this.eL(); } // Paper - OBFHELPER - public boolean eL() { - return (Boolean) this.datawatcher.get(EntityTurtle.br); - } - -+ public final void setDigging(boolean digging) { this.u(digging); } // Paper - OBFHELPER - private void u(boolean flag) { - this.bv = flag ? 1 : 0; - this.datawatcher.set(EntityTurtle.br, flag); - } - -+ public final boolean isGoingHome() { return this.eU(); } // Paper - OBFHELPER - private boolean eU() { - return (Boolean) this.datawatcher.get(EntityTurtle.bt); - } - -+ public final void setGoingHome(boolean goingHome) { this.v(goingHome); } // Paper - OBFHELPER - private void v(boolean flag) { - this.datawatcher.set(EntityTurtle.bt, flag); - } - -+ public final boolean isTravelling() { return this.eV(); } // Paper - OBFHELPER - private boolean eV() { - return (Boolean) this.datawatcher.get(EntityTurtle.bu); - } - -+ public final void setTravelling(boolean travelling) { this.w(travelling); } // Paper - OBFHELPER - private void w(boolean flag) { - this.datawatcher.set(EntityTurtle.bu, flag); - } -@@ -500,14 +507,17 @@ public class EntityTurtle extends EntityAnimal { - - if (!this.g.isInWater() && this.l()) { - if (this.g.bv < 1) { -- this.g.u(true); -+ this.g.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.getTargetPosition())).callEvent()); // Paper - } else if (this.g.bv > 200) { - World world = this.g.world; - - // CraftBukkit start -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1)).isCancelled()) { -+ // Paper start -+ int eggCount = this.g.random.nextInt(4) + 1; -+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.e.up()), eggCount); -+ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount())).isCancelled()) { - world.playSound((EntityHuman) null, blockposition, SoundEffects.ENTITY_TURTLE_LAY_EGG, SoundCategory.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); -- world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1), 3); -+ world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount()), 3); - } - // CraftBukkit end - this.g.setHasEgg(false); -@@ -636,7 +646,7 @@ public class EntityTurtle extends EntityAnimal { - - @Override - public boolean a() { -- return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))); -+ return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index b46bb75926c14ab54ea309a400eb57405b11ce27..31f1a6b2b9a432cdd25826ced884424eeb50df97 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -@@ -25,4 +25,36 @@ public class CraftTurtle extends CraftAnimals implements Turtle { - public EntityType getType() { - return EntityType.TURTLE; - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.Location getHome() { -+ return net.minecraft.server.MCUtil.toLocation(getHandle().world, getHandle().getHomePos()); -+ } -+ -+ @Override -+ public void setHome(org.bukkit.Location location) { -+ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); -+ } -+ -+ @Override -+ public boolean isGoingHome() { -+ return getHandle().isGoingHome(); -+ } -+ -+ @Override -+ public boolean isDigging() { -+ return getHandle().isDigging(); -+ } -+ -+ @Override -+ public boolean hasEgg() { -+ return getHandle().hasEgg(); -+ } -+ -+ @Override -+ public void setHasEgg(boolean hasEgg) { -+ getHandle().setHasEgg(hasEgg); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch deleted file mode 100644 index ab9d26a52315..000000000000 --- a/Spigot-Server-Patches/0296-MC-50319-Check-other-worlds-for-shooter-of-projectil.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 17 Oct 2018 19:17:27 -0400 -Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles - -Say a player shoots an arrow through a nether portal, the game -would lose the shooter for determining things such as Player Kills, -because the entity is in another world. - -If the projectile fails to find the shooter in the current world, check -other worlds. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index b44b18341331e5176e0f1851aa60cc425ccbd439..29834a3613c7701d46e879d170779eb7e6f664e1 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -45,7 +45,18 @@ public abstract class IProjectile extends Entity { - - @Nullable - public Entity getShooter() { -- return this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) -+ Entity entity = this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ if (entity == null) { -+ for (WorldServer world : world.getMinecraftServer().getWorlds()) { -+ entity = world.getEntity(this.shooter); -+ if (entity != null) { -+ break; -+ } -+ } -+ } -+ return entity; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch b/Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch deleted file mode 100644 index 632d99cd370e..000000000000 --- a/Spigot-Server-Patches/0297-Call-player-spectator-target-events-and-improve-impl.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:32:19 -0500 -Subject: [PATCH] Call player spectator target events and improve - implementation - -Use a proper teleport for teleporting to entities in different -worlds. - -Implementation improvements authored by Spottedleaf -Validate that the target entity is valid and deny spectate -requests from frozen players. - -Also, make sure the entity is spawned to the client before -sending the camera packet. If the entity isn't spawned clientside -when it receives the camera packet, then the client will not -spectate the target entity. - -Co-authored-by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index ae9e0f55ddc194aaef1e57e81863569d9bc7b8f3..f5be9554e1fd01a35b926196b30fd64f1567a799 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1820,15 +1820,59 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return (Entity) (this.spectatedEntity == null ? this : this.spectatedEntity); - } - -- public void setSpectatorTarget(Entity entity) { -+ public void setSpectatorTarget(Entity newSpectatorTarget) { -+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation - Entity entity1 = this.getSpecatorTarget(); - -- this.spectatedEntity = (Entity) (entity == null ? this : entity); -- if (entity1 != this.spectatedEntity) { -- this.playerConnection.sendPacket(new PacketPlayOutCamera(this.spectatedEntity)); -- this.playerConnection.a(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ if (newSpectatorTarget == null) { -+ newSpectatorTarget = this; - } - -+ if (entity1 == newSpectatorTarget) return; // new spec target is the current spec target -+ -+ if (newSpectatorTarget == this) { -+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); -+ -+ if (!playerStopSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } else { -+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), newSpectatorTarget.getBukkitEntity()); -+ -+ if (!playerStartSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } -+ // Validate -+ if (newSpectatorTarget != this) { -+ if (newSpectatorTarget.dead || newSpectatorTarget.shouldBeRemoved || !newSpectatorTarget.valid || newSpectatorTarget.world == null) { -+ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ if (this.isFrozen()) { -+ // use debug: clients might maliciously spam this -+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ } -+ -+ this.spectatedEntity = newSpectatorTarget; // only set after validating state -+ -+ if (newSpectatorTarget != this) { -+ // Make sure we're in the right place -+ this.ejectPassengers(); // teleport can fail if we have passengers... -+ this.getBukkitEntity().teleport(new Location(newSpectatorTarget.getWorld().getWorld(), newSpectatorTarget.locX(), newSpectatorTarget.locY(), newSpectatorTarget.locZ(), this.yaw, this.pitch), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport -+ -+ // Make sure we're tracking the entity before sending -+ PlayerChunkMap.EntityTracker tracker = ((WorldServer)newSpectatorTarget.world).getChunkProvider().playerChunkMap.trackedEntities.get(newSpectatorTarget.getId()); -+ if (tracker != null) { // dumb plugins... -+ tracker.updatePlayer(this); -+ } -+ } else { -+ this.playerConnection.teleport(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ } -+ this.playerConnection.sendPacket(new PacketPlayOutCamera(newSpectatorTarget)); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 74942bf7641eafab85202fd6a521780ce4cc1f65..5ea1354fb9d1c570603fc6814198639a741a9e34 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1355,6 +1355,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - // CraftBukkit start - Delegate to teleport(Location) -+ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { - this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); - } diff --git a/Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch b/Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch deleted file mode 100644 index 906a88165670..000000000000 --- a/Spigot-Server-Patches/0298-Add-Velocity-IP-Forwarding-Support.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 8 Oct 2018 14:36:14 -0400 -Subject: [PATCH] Add Velocity IP Forwarding Support - -While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users -have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. -Further, the BungeeCord IP forwarding protocol still retains essentially its original -form, when there is brand new support for custom login plugin messages in 1.13. - -Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity -of messages, is packed into a binary format that is smaller than BungeeCord's -forwarding, and is integrated into the Minecraft login process by using the 1.13 -login plugin message packet. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7178b37f7978c7e9031a22726005c5099fd78fe0..3139c194f9b1bc3510d51a81f13ae43d00a3dc29 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -8,6 +8,7 @@ import java.io.IOException; - import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Method; - import java.lang.reflect.Modifier; -+import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -@@ -252,7 +253,7 @@ public class PaperConfig { - } - - public static boolean isProxyOnlineMode() { -- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); - } - - public static int packetInSpamThreshold = 300; -@@ -324,4 +325,18 @@ public class PaperConfig { - } - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } -+ -+ public static boolean velocitySupport; -+ public static boolean velocityOnlineMode; -+ public static byte[] velocitySecretKey; -+ private static void velocitySupport() { -+ velocitySupport = getBoolean("settings.velocity-support.enabled", false); -+ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); -+ String secret = getString("settings.velocity-support.secret", ""); -+ if (velocitySupport && secret.isEmpty()) { -+ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); -+ } else { -+ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e6afaa41df086b1eb3950ce870c91dd5bf5a663b ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -@@ -0,0 +1,67 @@ -+package com.destroystokyo.paper.proxy; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.net.InetAddresses; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.resources.MinecraftKey; -+ -+import java.net.InetAddress; -+import java.security.InvalidKeyException; -+import java.security.MessageDigest; -+import java.security.NoSuchAlgorithmException; -+ -+import javax.crypto.Mac; -+import javax.crypto.spec.SecretKeySpec; -+ -+public class VelocityProxy { -+ private static final int SUPPORTED_FORWARDING_VERSION = 1; -+ public static final MinecraftKey PLAYER_INFO_CHANNEL = new MinecraftKey("velocity", "player_info"); -+ -+ public static boolean checkIntegrity(final PacketDataSerializer buf) { -+ final byte[] signature = new byte[32]; -+ buf.readBytes(signature); -+ -+ final byte[] data = new byte[buf.readableBytes()]; -+ buf.getBytes(buf.readerIndex(), data); -+ -+ try { -+ final Mac mac = Mac.getInstance("HmacSHA256"); -+ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); -+ final byte[] mySignature = mac.doFinal(data); -+ if (!MessageDigest.isEqual(signature, mySignature)) { -+ return false; -+ } -+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { -+ throw new AssertionError(e); -+ } -+ -+ int version = buf.readVarInt(); -+ if (version != SUPPORTED_FORWARDING_VERSION) { -+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); -+ } -+ -+ return true; -+ } -+ -+ public static InetAddress readAddress(final PacketDataSerializer buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); -+ } -+ -+ public static GameProfile createProfile(final PacketDataSerializer buf) { -+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); -+ readProperties(buf, profile); -+ return profile; -+ } -+ -+ private static void readProperties(final PacketDataSerializer buf, final GameProfile profile) { -+ final int properties = buf.readVarInt(); -+ for (int i1 = 0; i1 < properties; i1++) { -+ final String name = buf.readUTF(Short.MAX_VALUE); -+ final String value = buf.readUTF(Short.MAX_VALUE); -+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; -+ profile.getProperties().put(name, new Property(name, value, signature)); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 5a1187b001004afe22d208bc5d7c288e796e16a6..579eb1260c7266cd41025cff177de4fb00ac0cec 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -192,6 +192,7 @@ public class PacketDataSerializer extends ByteBuf { - return this.d(oenum.ordinal()); - } - -+ public int readVarInt() { return i(); } // Paper - OBFHELPER - public int i() { - int i = 0; - int j = 0; -@@ -232,6 +233,7 @@ public class PacketDataSerializer extends ByteBuf { - return this; - } - -+ public UUID readUUID() { return k(); } // Paper - OBFHELPER - public UUID k() { - return new UUID(this.readLong(), this.readLong()); - } -@@ -359,6 +361,7 @@ public class PacketDataSerializer extends ByteBuf { - } - } - -+ public String readUTF(int maxLength) { return this.e(maxLength); } // Paper - OBFHELPER - public String e(int i) { - int j = this.i(); - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -index c1bac2d07e5107c1346f246f5d5d929c73912bfd..c47c2d774a1990ad5007bbdc7bd3a81b3f3817e3 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -@@ -6,8 +6,8 @@ import net.minecraft.network.protocol.Packet; - - public class PacketLoginInCustomPayload implements Packet { - -- private int a; -- private PacketDataSerializer b; -+ private int a; public int getId() { return a; } // Paper - OBFHELPER -+ private PacketDataSerializer b; public PacketDataSerializer getBuf() { return b; } // Paper - OBFHELPER - - public PacketLoginInCustomPayload() {} - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -index eb970c1e954cb0aa83aa12e83c471778809e69b2..2d8c917509f10a96fc82404908b452cb385c7c60 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -@@ -13,6 +13,14 @@ public class PacketLoginOutCustomPayload implements Packet { -+ try { -+ new LoginHandler().fireEvents(); -+ } catch (Exception ex) { -+ disconnect("Failed to verify username!"); -+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); -+ } -+ }); -+ return; -+ } -+ // Paper end - this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response")); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 72e2c6f731c1d2cb0eafedef7317b35a45b55dd7..54fa963faab3289d014299a38099eb72ff541065 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -685,7 +685,7 @@ public final class CraftServer implements Server { - @Override - public long getConnectionThrottle() { - // Spigot Start - Automatically set connection throttle for bungee configurations -- if (org.spigotmc.SpigotConfig.bungee) { -+ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support - return -1; - } else { - return this.configuration.getInt("settings.connection-throttle"); diff --git a/Spigot-Server-Patches/0299-Add-more-Witch-API.patch b/Spigot-Server-Patches/0299-Add-more-Witch-API.patch deleted file mode 100644 index fe9e372e326b..000000000000 --- a/Spigot-Server-Patches/0299-Add-more-Witch-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 14:10:46 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index c6d79125e7dd982fc528ce61144005194cbaa323..63fb08e7b4290353e5148d1acb58f091dc5b08be 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -1,5 +1,11 @@ - package net.minecraft.world.entity.monster; - -+// Paper start -+import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.entity.Witch; -+// Paper end -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -49,7 +55,7 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - private static final UUID b = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); - private static final AttributeModifier bo = new AttributeModifier(EntityWitch.b, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); - private static final DataWatcherObject bp = DataWatcher.a(EntityWitch.class, DataWatcherRegistry.i); -- private int bq; -+ private int bq; public int getPotionUseTimeLeft() { return bq; } public void setPotionUseTimeLeft(int timeLeft) { bq = timeLeft; } // Paper - OBFHELPER - private PathfinderGoalNearestHealableRaider br; - private PathfinderGoalNearestAttackableTargetWitch bs; - -@@ -95,10 +101,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - return SoundEffects.ENTITY_WITCH_DEATH; - } - -+ public void setDrinkingPotion(boolean drinkingPotion) { v(drinkingPotion); } // Paper - OBFHELPER - public void v(boolean flag) { - this.getDataWatcher().set(EntityWitch.bp, flag); - } - -+ public boolean isDrinkingPotion() { return m(); } // Paper - OBFHELPER - public boolean m() { - return (Boolean) this.getDataWatcher().get(EntityWitch.bp); - } -@@ -157,21 +165,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- // Paper start - ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -- this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out -+ this.setDrinkingPotion(potion); -+// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+// // Paper end -+// this.bq = this.getItemInMainHand().k(); -+// this.v(true); -+// if (!this.isSilent()) { -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+// } -+// -+// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+// -+// attributemodifiable.removeModifier(EntityWitch.bo); -+// attributemodifiable.b(EntityWitch.bo); - // Paper end -- this.bq = this.getItemInMainHand().k(); -- this.v(true); -- if (!this.isSilent()) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -- } - -- AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -- -- attributemodifiable.removeModifier(EntityWitch.bo); -- attributemodifiable.b(EntityWitch.bo); - } - } - -@@ -183,6 +194,24 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - super.movementTick(); - } - -+ // Paper start - moved to its own method -+ public void setDrinkingPotion(ItemStack potion) { -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end -+ this.bq = this.getItemInMainHand().k(); -+ this.v(true); -+ if (!this.isSilent()) { -+ this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+ } -+ -+ AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+ -+ attributemodifiable.removeModifier(EntityWitch.bo); -+ attributemodifiable.b(EntityWitch.bo); -+ } -+ // Paper end -+ - @Override - public SoundEffect eL() { - return SoundEffects.ENTITY_WITCH_CELEBRATE; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 9cc34cdb43596eff34625045f884b93da3f27ab6..3b553c2455948a4102754b2617c2301c49f476d6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -4,6 +4,13 @@ import net.minecraft.world.entity.monster.EntityWitch; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; -+// Paper start -+import com.destroystokyo.paper.entity.CraftRangedEntity; -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { -@@ -24,4 +31,28 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. - public EntityType getType() { - return EntityType.WITCH; - } -+ -+ // Paper start -+ public boolean isDrinkingPotion() { -+ return getHandle().isDrinkingPotion(); -+ } -+ -+ public int getPotionUseTimeLeft() { -+ return getHandle().getPotionUseTimeLeft(); -+ } -+ -+ @Override -+ public void setPotionUseTimeLeft(int ticks) { -+ getHandle().setPotionUseTimeLeft(ticks); -+ } -+ -+ public ItemStack getDrinkingPotion() { -+ return CraftItemStack.asCraftMirror(getHandle().getItemInMainHand()); -+ } -+ -+ public void setDrinkingPotion(ItemStack potion) { -+ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); -+ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch b/Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch deleted file mode 100644 index efb266e1a522..000000000000 --- a/Spigot-Server-Patches/0300-Check-Drowned-for-Villager-Aggression-Config.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 10 Oct 2018 21:22:44 -0500 -Subject: [PATCH] Check Drowned for Villager Aggression Config - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -index c3457fc7c0f72af79b12dc50c270ca24b7590c22..e4794760fc918cccbdc3f8d10ab21dd9b6f29e8e 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -@@ -82,7 +82,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityDrowned.class})).a(EntityPigZombie.class)); - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::i)); -- this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); -+ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); // Paper - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); - this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); - } diff --git a/Spigot-Server-Patches/0301-Here-s-Johnny.patch b/Spigot-Server-Patches/0301-Here-s-Johnny.patch deleted file mode 100644 index b9a50189c22f..000000000000 --- a/Spigot-Server-Patches/0301-Here-s-Johnny.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:22 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index c181d5f5e6108ade54fc97c665897d1db5e90719..c45dcb56af95f3e87e292b92b697a336461f01bc 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -51,7 +51,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -- private boolean bo; -+ private boolean bo; public boolean isJohnny() { return bo; } public void setJohnny(boolean johnny) { bo = johnny; } // Paper - OBFHELPER - - public EntityVindicator(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -index e793820e1ede4bd4d31e6fe12ca8189707674ffe..b128e8291f2d7652a98f1271d763e33afa5de9f7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -@@ -25,4 +25,14 @@ public class CraftVindicator extends CraftIllager implements Vindicator { - public EntityType getType() { - return EntityType.VINDICATOR; - } -+ -+ // Paper start -+ public boolean isJohnny() { -+ return getHandle().isJohnny(); -+ } -+ -+ public void setJohnny(boolean johnny) { -+ getHandle().setJohnny(johnny); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch b/Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch deleted file mode 100644 index 7bf30d725c24..000000000000 --- a/Spigot-Server-Patches/0302-Add-option-to-prevent-players-from-moving-into-unloa.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Mon, 22 Oct 2018 17:34:10 +0200 -Subject: [PATCH] Add option to prevent players from moving into unloaded - chunks #1551 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f280dbff4a09bc611a9ca565c6d697d08801f53b..fbf3ccfb347a5ba6e895339e9576629d940d1aa4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -396,4 +396,9 @@ public class PaperWorldConfig { - waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); - log("Water over lava flow speed: " + waterOverLavaFlowSpeed); - } -+ -+ public boolean preventMovingIntoUnloadedChunks = false; -+ private void preventMovingIntoUnloadedChunks() { -+ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 5ea1354fb9d1c570603fc6814198639a741a9e34..69b27924b8f12b647133fedcfb0568698d19f413 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -543,6 +543,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { -+ this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); -+ return; -+ } -+ // Paper end -+ - if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { - // CraftBukkit end - PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), d6, d7, d8); -@@ -1141,9 +1148,9 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d1 = this.player.locY(); - double d2 = this.player.locZ(); - double d3 = this.player.locY(); -- double d4 = packetplayinflying.a(this.player.locX()); -+ double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER - double d5 = packetplayinflying.b(this.player.locY()); -- double d6 = packetplayinflying.c(this.player.locZ()); -+ double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); - double d7 = d4 - this.l; -@@ -1182,6 +1189,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - } else { - speed = player.abilities.walkSpeed * 10f; - } -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); -+ return; -+ } -+ // Paper end - - if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean(GameRules.DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isGliding())) { - float f2 = this.player.isGliding() ? 300.0F : 100.0F; diff --git a/Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch b/Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch deleted file mode 100644 index 0daed6e781f7..000000000000 --- a/Spigot-Server-Patches/0303-Reset-players-airTicks-on-respawn.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GreenMeanie -Date: Sat, 20 Oct 2018 22:34:02 -0400 -Subject: [PATCH] Reset players airTicks on respawn - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f5be9554e1fd01a35b926196b30fd64f1567a799..3e7ac6699ad1f147220c286e251ce0ec1ca25035 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2162,6 +2162,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - this.setHealth(this.getMaxHealth()); -+ this.setAirTicks(this.getMaxAirTicks()); // Paper - this.fireTicks = 0; - this.fallDistance = 0; - this.foodData = new FoodMetaData(this); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b6b4eb9ac883cfdfab5f114767fb5cfb29445730..0b61d03506bd56cf7e373daacbf4fb2e29bb0a58 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2350,6 +2350,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -+ public final int getMaxAirTicks() { return bH(); } // Paper - OBFHELPER - public int bH() { - return 300; - } diff --git a/Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch deleted file mode 100644 index 01be147e2499..000000000000 --- a/Spigot-Server-Patches/0304-Don-t-sleep-after-profile-lookups-if-not-needed.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 20:25:05 -0400 -Subject: [PATCH] Don't sleep after profile lookups if not needed - -Mojang was sleeping even if we had no more requests to go after -the current one finished, resulting in 100ms lost per profile lookup - -diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -index a3ab666b5fa89aad7ee167d9aeff2f62019a4a78..8e182fdd69dba6e1c52e2f6a893534d77fb3bfaa 100644 ---- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -@@ -43,6 +43,7 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - } - - final int page = 0; -+ boolean hasRequested = false; // Paper - - for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { - int failCount = 0; -@@ -68,6 +69,12 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - LOGGER.debug("Couldn't find profile {}", name); - callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); - } -+ // Paper start -+ if (!hasRequested) { -+ hasRequested = true; -+ continue; -+ } -+ // Paper end - - try { - Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch deleted file mode 100644 index 40e98e9749ee..000000000000 --- a/Spigot-Server-Patches/0305-Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 23:14:38 -0400 -Subject: [PATCH] Improve Server Thread Pool and Thread Priorities - -Use a simple executor since Fork join is a much more complex pool -type and we are not using its capabilities. - -Set thread priorities so main thread has above normal priority over -server threads - -Allow usage of a single thread executor by not using ForkJoin so single core CPU's. - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 68ce7605bd63ea280b96db8230463d2afb0a6cb1..46d82c1548088b8305f758699388edf0d5d4d050 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -45,6 +45,7 @@ import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.DispenserRegistry; -+import net.minecraft.server.ServerWorkerThread; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.world.level.block.state.properties.IBlockState; -@@ -54,8 +55,8 @@ import org.apache.logging.log4j.Logger; - public class SystemUtils { - - private static final AtomicInteger c = new AtomicInteger(1); -- private static final ExecutorService d = a("Bootstrap"); -- private static final ExecutorService e = a("Main"); -+ private static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority -+ private static final ExecutorService e = a("Main", -1); // Paper - add -1 priority - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; - public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER -@@ -85,15 +86,18 @@ public class SystemUtils { - return Instant.now().toEpochMilli(); - } - -- private static ExecutorService a(String s) { -- int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); -- Object object; -+ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority -+ // Paper start - use simpler thread pool that allows 1 thread -+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); -+ i = Integer.getInteger("Paper.WorkerThreadCount", i); -+ ExecutorService object; - - if (i <= 0) { - object = MoreExecutors.newDirectExecutorService(); - } else { -- object = new ForkJoinPool(i, (forkjoinpool) -> { -- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { -+ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); -+ } -+ /* - protected void onTermination(Throwable throwable) { - if (throwable != null) { - SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); -@@ -109,6 +113,7 @@ public class SystemUtils { - return forkjoinworkerthread; - }, SystemUtils::a, true); - } -+ }*/ // Paper end - - return (ExecutorService) object; - } -@@ -157,6 +162,7 @@ public class SystemUtils { - }); - } - -+ public static void onThreadError(Thread thread, Throwable throwable) { a(thread, throwable); } // Paper - OBFHELPER - private static void a(Thread thread, Throwable throwable) { - c(throwable); - if (throwable instanceof CompletionException) { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 540250a9610e2ee51685b655a7d6c0809bba64fd..67748b3c57766ef297082a7ea6a255b0f42de446 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 2 Nov 2018 23:11:51 -0400 -Subject: [PATCH] Optimize World Time Updates - -Splits time updates into incremental updates as well as does -the updates per world, so that we can re-use the same packet -object for every player unless they have per-player time enabled. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 67748b3c57766ef297082a7ea6a255b0f42de446..4d44604da7c65df6d8e87b6c6c56371ca307c11f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1316,12 +1316,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 5 Nov 2018 04:23:51 +0000 -Subject: [PATCH] Restore custom InventoryHolder support - -Upstream removed the ability to consistently use a custom InventoryHolder, -However, the implementation does not use an InventoryHolder in any form -outside of custom inventories. - -We can take that knowledge and apply some expected behavior, if we're given -an inventory holder, we should use it and return a custom inventory with the -holder, otherwise, create an inventory backed by the intended inventory, as -per upstream behavior. - -This provides a "best of both worlds" scenario: plugins with InventoryHolder's -will always work as intended in the past, those without will create implementation -based inventories. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index 94d807c5d09f165c6eedd0a1c4026c2b833806a0..3e56de295be0d03dddd3e54fcd7b05d4b9c74dc4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -40,6 +40,11 @@ public final class CraftInventoryCreator { - } - - public Inventory createInventory(InventoryHolder holder, InventoryType type) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type); - } - -@@ -55,6 +60,11 @@ public final class CraftInventoryCreator { - // Paper end - - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type, title); - } - diff --git a/Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch b/Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch deleted file mode 100644 index 7e7e806b366d..000000000000 --- a/Spigot-Server-Patches/0308-Use-Vanilla-Minecart-Speeds.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Nov 2018 21:33:09 -0500 -Subject: [PATCH] Use Vanilla Minecart Speeds - -CraftBukkit changed the values on flying speed, restore back to vanilla - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 1f94cc096d95129d85a6278b1e369729df93d27d..7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -100,9 +100,9 @@ public abstract class EntityMinecartAbstract extends Entity { - private double derailedX = 0.5; - private double derailedY = 0.5; - private double derailedZ = 0.5; -- private double flyingX = 0.95; -- private double flyingY = 0.95; -- private double flyingZ = 0.95; -+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision - public double maxSpeed = 0.4D; - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch b/Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch deleted file mode 100644 index f0c682b05886..000000000000 --- a/Spigot-Server-Patches/0309-Fix-SpongeAbsortEvent-handling.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 10 Nov 2018 05:15:21 +0000 -Subject: [PATCH] Fix SpongeAbsortEvent handling - -Only process drops when the block is actually going to be removed - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 615a4418fd276cd3e0b3686d962ebaf13ef5d4be..e5c43b383a93fac76333a67b41535ab009d1dcf3 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -228,6 +228,7 @@ public class Block extends BlockBase implements IMaterial { - - } - -+ public static void dropNaturally(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { a(iblockdata, generatoraccess, blockposition, tileentity); } - public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { - if (generatoraccess instanceof WorldServer) { - a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockSponge.java b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -index ef48ad0ab68e2e050bc8aca484d850297990b78e..d80eee47390ab202eea0368571421bbc94655ab1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockSponge.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -@@ -129,8 +129,11 @@ public class BlockSponge extends Block { - // NOP - } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - TileEntity tileentity = iblockdata.getBlock().isTileEntity() ? world.getTileEntity(blockposition2) : null; -- -- a(iblockdata, world, blockposition2, tileentity); -+ // Paper start -+ if (block.getHandle().getMaterial() == Material.AIR) { -+ dropNaturally(iblockdata, world, blockposition2, tileentity); -+ } -+ // Paper end - } - } - world.setTypeAndData(blockposition2, block.getHandle(), block.getFlag()); diff --git a/Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch b/Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch deleted file mode 100644 index c76760fe81ea..000000000000 --- a/Spigot-Server-Patches/0310-Don-t-allow-digging-into-unloaded-chunks.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Nov 2018 21:01:09 +0000 -Subject: [PATCH] Don't allow digging into unloaded chunks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 14f287d30c9a141f78f6311bef02a6fc4fa17564..d86b1e528b53db809ac993aa2f1d2799d4f1a574 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -114,8 +114,8 @@ public class PlayerInteractManager { - IBlockData iblockdata; - - if (this.j) { -- iblockdata = this.world.getType(this.k); -- if (iblockdata.isAir()) { -+ iblockdata = this.world.getTypeIfLoaded(this.k); // Paper -+ if (iblockdata == null || iblockdata.isAir()) { // Paper - this.j = false; - } else { - float f = this.a(iblockdata, this.k, this.l); -@@ -126,7 +126,13 @@ public class PlayerInteractManager { - } - } - } else if (this.f) { -- iblockdata = this.world.getType(this.h); -+ // Paper start - don't want to do same logic as above, return instead -+ iblockdata = this.world.getTypeIfLoaded(this.h); -+ if (iblockdata == null) { -+ this.f = false; -+ return; -+ } -+ // Paper end - if (iblockdata.isAir()) { - this.world.a(this.player.getId(), this.h, -1); - this.m = -1; -@@ -290,10 +296,12 @@ public class PlayerInteractManager { - this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "stopped destroying")); - } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { - this.f = false; -- if (!Objects.equals(this.h, blockposition)) { -+ if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { - PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: " + this.h + " " + blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled -- this.world.a(this.player.getId(), this.h, -1); -- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, this.world.getType(this.h), packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); -+ IBlockData type = this.world.getTypeIfLoaded(this.h); // Paper - don't load unloaded chunks for stale records here -+ if (type != null) this.world.a(this.player.getId(), this.h, -1); // Paper -+ if (type != null) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, type, packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); // Paper -+ this.h = BlockPosition.ZERO; // Paper - } - - this.world.a(this.player.getId(), blockposition, -1); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 69b27924b8f12b647133fedcfb0568698d19f413..59617fceecb08edf665902f30ea7064e6333bb96 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1519,6 +1519,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - case START_DESTROY_BLOCK: - case ABORT_DESTROY_BLOCK: - case STOP_DESTROY_BLOCK: -+ // Paper start - Don't allow digging in unloaded chunks -+ if (this.player.world.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ return; -+ } -+ // Paper end - Don't allow digging in unloaded chunks - this.player.playerInteractManager.a(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.c(), this.minecraftServer.getMaxBuildHeight()); - return; - default: diff --git a/Spigot-Server-Patches/0311-Book-Size-Limits.patch b/Spigot-Server-Patches/0311-Book-Size-Limits.patch deleted file mode 100644 index 17535e762492..000000000000 --- a/Spigot-Server-Patches/0311-Book-Size-Limits.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Nov 2018 23:08:50 -0500 -Subject: [PATCH] Book Size Limits - -Puts some limits on the size of books. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 3139c194f9b1bc3510d51a81f13ae43d00a3dc29..13edb435b3fa65b4980bd7472aa5a5196f4d5b2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -339,4 +339,11 @@ public class PaperConfig { - velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); - } - } -+ -+ public static int maxBookPageSize = 2560; -+ public static double maxBookTotalSizeMultiplier = 0.98D; -+ private static void maxBookSize() { -+ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); -+ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 59617fceecb08edf665902f30ea7064e6333bb96..7158d3e3a7e2912d8d170aca4096355d43645cfa 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1001,6 +1001,52 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInBEdit packetplayinbedit) { -+ // Paper start -+ ItemStack testStack = packetplayinbedit.getBook(); -+ if (!server.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { -+ NBTTagList pageList = testStack.getTag().getList("pages", 8); -+ if (pageList.size() > 100) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ long byteTotal = 0; -+ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; -+ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); -+ long byteAllowed = maxBookPageSize; -+ for (int i = 0; i < pageList.size(); ++i) { -+ String testString = pageList.getString(i); -+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; -+ if (byteLength > 256 * 4) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ byteTotal += byteLength; -+ int length = testString.length(); -+ int multibytes = 0; -+ if (byteLength != length) { -+ for (char c : testString.toCharArray()) { -+ if (c > 127) { -+ multibytes++; -+ } -+ } -+ } -+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; -+ -+ if (multibytes > 1) { -+ // penalize MB -+ byteAllowed -= multibytes; -+ } -+ } -+ -+ if (byteTotal > byteAllowed) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ } -+ // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); diff --git a/Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch b/Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch deleted file mode 100644 index e5b7e8ae760e..000000000000 --- a/Spigot-Server-Patches/0312-Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:49:56 +0000 -Subject: [PATCH] Make the default permission message configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 13edb435b3fa65b4980bd7472aa5a5196f4d5b2b..469f78775b03cf363d88e35c69c0dc185c22547c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -19,6 +19,7 @@ import java.util.regex.Pattern; - import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; -@@ -287,6 +288,11 @@ public class PaperConfig { - connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); - } - -+ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; -+ private static void noPermissionMessage() { -+ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 54fa963faab3289d014299a38099eb72ff541065..0cfbe461c9b915c96b27f88f651a296d470b995f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2342,6 +2342,11 @@ public final class CraftServer implements Server { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } - -+ @Override -+ public String getPermissionMessage() { -+ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; -+ } -+ - @Override - public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { - return createProfile(uuid, null); diff --git a/Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch b/Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch deleted file mode 100644 index 0295326280f2..000000000000 --- a/Spigot-Server-Patches/0313-Prevent-rayTrace-from-loading-chunks.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 26 Nov 2018 19:21:58 -0500 -Subject: [PATCH] Prevent rayTrace from loading chunks - -ray tracing into an unloaded chunk should be treated as a miss -this saves a ton of lag for when AI tries to raytrace near unloaded chunks. - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index e799765ecfada1eec78beb71651e52ad355a30aa..21ce19b9caf3150535a3f84027242a93bdd0d263 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -58,7 +58,15 @@ public interface IBlockAccess { - - // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace - default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { -- IBlockData iblockdata = this.getType(blockposition); -+ // Paper start - Prevent raytrace from loading chunks -+ IBlockData iblockdata = this.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ // copied the last function parameter (listed below) -+ Vec3D vec3d = raytrace1.b().d(raytrace1.a()); -+ -+ return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); -+ } -+ // Paper end - Fluid fluid = this.getFluid(blockposition); - Vec3D vec3d = raytrace1.b(); - Vec3D vec3d1 = raytrace1.a(); diff --git a/Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch b/Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch deleted file mode 100644 index 9f62fd514e7e..000000000000 --- a/Spigot-Server-Patches/0314-Handle-Large-Packets-disconnecting-client.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Nov 2018 21:18:06 -0500 -Subject: [PATCH] Handle Large Packets disconnecting client - -If a players inventory is too big to send in a single packet, -split the inventory set into multiple packets instead. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 297820baef99e97e1216a64c527219e9ccc3e320..dc788d75a6a34fbbae990609bfbbd13ca6cdee5a 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -12,6 +12,7 @@ import io.netty.channel.epoll.EpollEventLoopGroup; - import io.netty.channel.local.LocalChannel; - import io.netty.channel.local.LocalServerChannel; - import io.netty.channel.nio.NioEventLoopGroup; -+import io.netty.handler.codec.EncoderException; // Paper - import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; -@@ -107,6 +108,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { -+ // Paper start -+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { -+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { -+ return; -+ } else { -+ throwable = throwable.getCause(); -+ } -+ } -+ // Paper end - if (throwable instanceof SkipEncodeException) { - NetworkManager.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); - } else { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 2f6da89d6b25ba5144ec15b1bf0e8ed13278e85e..037d989522d24a55eced1c462d40a6dc2a7ecfce 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -53,7 +53,31 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw throwable; - } - } -+ -+ // Paper start -+ int packetLength = bytebuf.readableBytes(); -+ if (packetLength > MAX_PACKET_SIZE) { -+ throw new PacketTooLargeException(packet, packetLength); -+ } -+ // Paper end - } - } - } -+ -+ // Paper start -+ private static int MAX_PACKET_SIZE = 2097152; -+ -+ public static class PacketTooLargeException extends RuntimeException { -+ private final Packet packet; -+ -+ PacketTooLargeException(Packet packet, int packetLength) { -+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); -+ this.packet = packet; -+ } -+ -+ public Packet getPacket() { -+ return packet; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index cd4493a023748264748d4e892815f14d8a7bd7f6..0783b0777c8d7788bbf6780b464b709bf6dc2191 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -12,6 +12,12 @@ public interface Packet { - - void a(T t0); - -+ // Paper start -+ default boolean packetTooLarge(NetworkManager manager) { -+ return false; -+ } -+ // Paper end -+ - default boolean a() { - return false; - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 152118729b1a95dcae05d32aa4289034ba394226..0059ede4ba3ff271d47dd38ea87fddc2399aa008 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -91,7 +91,7 @@ public class PacketPlayOutMapChunk implements Packet { - - int i = packetdataserializer.i(); - -- if (i > 2097152) { -+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder - throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); - } else { - this.f = new byte[i]; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -index b90e35a0099a2482f8fc2998bd079fc2fe6439e6..e540f95a370c627d3d81e0d3670049d01923559d 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -@@ -4,6 +4,7 @@ import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.item.ItemStack; -@@ -13,6 +14,15 @@ public class PacketPlayOutWindowItems implements Packet { - private int a; - private List b; - -+ //Paper start -+ @Override -+ public boolean packetTooLarge(NetworkManager manager) { -+ for (int i = 0 ; i < this.b.size() ; i++) { -+ manager.sendPacket(new PacketPlayOutSetSlot(this.a, i, this.b.get(i))); -+ } -+ return true; -+ } -+ // Paper end - public PacketPlayOutWindowItems() {} - - public PacketPlayOutWindowItems(int i, NonNullList nonnulllist) { diff --git a/Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch b/Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch deleted file mode 100644 index 9b24c3e4cbe2..000000000000 --- a/Spigot-Server-Patches/0315-force-entity-dismount-during-teleportation.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 15 Nov 2018 13:38:37 +0000 -Subject: [PATCH] force entity dismount during teleportation - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -this is going to be the best soultion all around. - -Improvements/suggestions welcome! - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3e7ac6699ad1f147220c286e251ce0ec1ca25035..e755191435e74246b309f8fe5a668dae2e499df1 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1261,11 +1261,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - Entity entity1 = this.getVehicle(); - - if (entity1 != entity && this.playerConnection != null) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0b61d03506bd56cf7e373daacbf4fb2e29bb0a58..1e5930f5ae75b82abf6ea2a50558449fb667016f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2040,12 +2040,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -- public void bf() { -+ // Paper start -+ public void bf() { stopRiding(false); } -+ public void stopRiding(boolean suppressCancellation) { -+ // Paper end - if (this.vehicle != null) { - Entity entity = this.vehicle; - - this.vehicle = null; -- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit -+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper - } - - } -@@ -2100,7 +2103,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return true; // CraftBukkit - } - -- protected boolean removePassenger(Entity entity) { // CraftBukkit -+ // Paper start -+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} -+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit -+ // Paper end - if (entity.getVehicle() == this) { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { -@@ -2110,7 +2116,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { - VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), -- (LivingEntity) entity.getBukkitEntity() -+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper - ); - // Suppress during worldgen - if (this.valid) { -@@ -2124,7 +2130,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - // Spigot start -- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); -+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper - // Suppress during worldgen - if (this.valid) { - Bukkit.getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index b3c2976a48c2349e5c22d58dd1ac64a02cd969d5..6ada2fe58966553b52a8a890088c78d5ea0dfd73 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3015,11 +3015,13 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 4) != 0; - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - suppress - if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { - this.a(entity); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 87374174dcbf9e7ee448a1cdd9a3528557c3a2ea..564dfa98c166fde509044e6e1938efb321ece53d 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1039,9 +1039,11 @@ public abstract class EntityHuman extends EntityLiving { - return -0.35D; - } - -- @Override -- public void bf() { -- super.bf(); -+ // Paper start -+ @Override public void bf() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end -+ super.stopRiding(suppressCancellation); // Paper - suppress - this.j = 0; - } - diff --git a/Spigot-Server-Patches/0316-Add-more-Zombie-API.patch b/Spigot-Server-Patches/0316-Add-more-Zombie-API.patch deleted file mode 100644 index c620328b1a4f..000000000000 --- a/Spigot-Server-Patches/0316-Add-more-Zombie-API.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:59 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 219e3b1626d68ede57b08a706d24bb6bc4b13fac..79d34b0296f88e5b4fe0351fe2483fc0128deabc 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -94,6 +94,7 @@ public class EntityZombie extends EntityMonster { - private int bt; - public int drownedConversionTime; - private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field -+ private boolean shouldBurnInDay = true; // Paper - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -262,6 +263,12 @@ public class EntityZombie extends EntityMonster { - super.movementTick(); - } - -+ // Paper start -+ public void stopDrowning() { -+ this.drownedConversionTime = -1; -+ this.getDataWatcher().set(EntityZombie.DROWN_CONVERTING, false); -+ } -+ // Paper end - public void startDrownedConversion(int i) { - this.lastTick = MinecraftServer.currentTick; // CraftBukkit - this.drownedConversionTime = i; -@@ -290,9 +297,16 @@ public class EntityZombie extends EntityMonster { - - } - -+ public boolean shouldBurnInDay() { return T_(); } // Paper - OBFHELPER - protected boolean T_() { -- return true; -+ return this.shouldBurnInDay; // Paper - use api value instead -+ } -+ -+ // Paper start -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ this.shouldBurnInDay = shouldBurnInDay; - } -+ // Paper end - - @Override - public boolean damageEntity(DamageSource damagesource, float f) { -@@ -413,6 +427,7 @@ public class EntityZombie extends EntityMonster { - nbttagcompound.setBoolean("CanBreakDoors", this.eU()); - nbttagcompound.setInt("InWaterTime", this.isInWater() ? this.bt : -1); - nbttagcompound.setInt("DrownedConversionTime", this.isDrownConverting() ? this.drownedConversionTime : -1); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper - } - - @Override -@@ -424,7 +439,11 @@ public class EntityZombie extends EntityMonster { - if (nbttagcompound.hasKeyOfType("DrownedConversionTime", 99) && nbttagcompound.getInt("DrownedConversionTime") > -1) { - this.startDrownedConversion(nbttagcompound.getInt("DrownedConversionTime")); - } -- -+ // Paper start -+ if (nbttagcompound.hasKey("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 8ba92b7edacc088d610a9ed46eb7f61ebd8101a8..42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -94,6 +94,42 @@ public class CraftZombie extends CraftMonster implements Zombie { - @Override - public void setAgeLock(boolean b) { - } -+ // Paper start -+ @Override -+ public boolean isDrowning() { -+ return getHandle().isDrownConverting(); -+ } -+ -+ @Override -+ public void startDrowning(int drownedConversionTime) { -+ getHandle().startDrownedConversion(drownedConversionTime); -+ } -+ -+ @Override -+ public void stopDrowning() { -+ getHandle().stopDrowning(); -+ } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public boolean isArmsRaised() { -+ return getHandle().isAggressive(); -+ } -+ -+ @Override -+ public void setArmsRaised(final boolean raised) { -+ getHandle().setAggressive(raised); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - - @Override - public boolean getAgeLock() { diff --git a/Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch b/Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index ddc9e05522cc..000000000000 --- a/Spigot-Server-Patches/0317-Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:28 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index dc788d75a6a34fbbae990609bfbbd13ca6cdee5a..6d40ade5a52383ed86d28d272c3dc83dbdcbd218 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -350,6 +350,26 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } - this.packetQueue.clear(); // Free up packet queue. -+ // Paper start - Add PlayerConnectionCloseEvent -+ final PacketListener packetListener = this.j(); -+ if (packetListener instanceof PlayerConnection) { -+ /* Player was logged in */ -+ final PlayerConnection playerConnection = (PlayerConnection) packetListener; -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUniqueID(), -+ playerConnection.player.getName(), ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } else if (packetListener instanceof LoginListener) { -+ /* Player is login stage */ -+ final LoginListener loginListener = (LoginListener) packetListener; -+ switch (loginListener.getLoginState()) { -+ case READY_TO_ACCEPT: -+ case DELAY_ACCEPT: -+ case ACCEPTED: -+ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), -+ ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 36f747af18347197bab7c335d5d7dfc01a5aff80..09ceac61f873ee0cb689c66a403c42677961011d 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -57,9 +57,9 @@ public class LoginListener implements PacketLoginInListener { - private final byte[] e = new byte[4]; - private final MinecraftServer server; - public final NetworkManager networkManager; -- private LoginListener.EnumProtocolState g; -+ private LoginListener.EnumProtocolState g; public final LoginListener.EnumProtocolState getLoginState() { return this.g; }; // Paper - OBFHELPER - private int h; -- private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } public GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; diff --git a/Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch b/Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch deleted file mode 100644 index 86be24f3d42d..000000000000 --- a/Spigot-Server-Patches/0318-Prevent-Enderman-from-loading-chunks.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 18 Dec 2018 02:15:08 +0000 -Subject: [PATCH] Prevent Enderman from loading chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index aa6cb15637144c9d8db1b1861e58f3f02d68357a..e993b1849beb60515c51ee4f37617faab63ca223 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -434,7 +434,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.enderman.locY() + random.nextDouble() * 3.0D); - int k = MathHelper.floor(this.enderman.locZ() - 2.0D + random.nextDouble() * 4.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - Block block = iblockdata.getBlock(); - Vec3D vec3d = new Vec3D((double) MathHelper.floor(this.enderman.locX()) + 0.5D, (double) j + 0.5D, (double) MathHelper.floor(this.enderman.locZ()) + 0.5D); - Vec3D vec3d1 = new Vec3D((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); -@@ -474,7 +475,8 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.a.locY() + random.nextDouble() * 2.0D); - int k = MathHelper.floor(this.a.locZ() - 1.0D + random.nextDouble() * 2.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata1 = world.getType(blockposition1); - IBlockData iblockdata2 = this.a.getCarried(); diff --git a/Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index aefc2dfd10cd..000000000000 --- a/Spigot-Server-Patches/0319-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Wed, 2 Jan 2019 00:35:43 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -intent to remove) and replace it with two new methods, clearly named and -documented as to their purpose. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e755191435e74246b309f8fe5a668dae2e499df1..8d88ed3d68146fbcb090847351945689518e59a9 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -214,6 +214,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ public long loginTime; // Paper - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 2299581fa889c0e8ddc6b2cc1d3551d02ff8dc2d..7515e9ddbc89de882373469cf3c46046c76af974 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -168,6 +168,7 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); - GameProfile gameprofile1 = usercache.getProfile(gameprofile.getId()); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 9b8d7b176e288fa715177196e7aff92900d8567a..1e741158bbcc0991259436bec549b32df61f0c54 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -@@ -244,6 +244,61 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa - return getData() != null; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastLogin(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastLogin")) { -+ return data.getLong("LastLogin"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ @Override -+ public long getLastSeen() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastSeen(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastSeen")) { -+ return data.getLong("LastSeen"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ private NBTTagCompound getPaperData() { -+ NBTTagCompound result = getData(); -+ -+ if (result != null) { -+ if (!result.hasKey("Paper")) { -+ result.set("Paper", new NBTTagCompound()); -+ } -+ result = result.getCompound("Paper"); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public Location getBedSpawnLocation() { - NBTTagCompound data = getData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6c5075ef2420131aa21b403623a5dfa485ee73e5..25e0d0dd7b114560896679f0314cea288d7a768c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -147,6 +147,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; - private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit -+ private long lastSaveTime; - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -1483,6 +1484,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - this.firstPlayed = firstPlayed; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ return getHandle().loginTime; -+ } -+ -+ @Override -+ public long getLastSeen() { -+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; -+ } -+ // Paper end -+ - public void readExtraData(NBTTagCompound nbttagcompound) { - hasPlayedBefore = true; - if (nbttagcompound.hasKey("bukkit")) { -@@ -1505,6 +1518,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setExtraData(NBTTagCompound nbttagcompound) { -+ this.lastSaveTime = System.currentTimeMillis(); // Paper -+ - if (!nbttagcompound.hasKey("bukkit")) { - nbttagcompound.set("bukkit", new NBTTagCompound()); - } -@@ -1519,6 +1534,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - data.setLong("firstPlayed", getFirstPlayed()); - data.setLong("lastPlayed", System.currentTimeMillis()); - data.setString("lastKnownName", handle.getName()); -+ -+ // Paper start - persist for use in offline save data -+ if (!nbttagcompound.hasKey("Paper")) { -+ nbttagcompound.set("Paper", new NBTTagCompound()); -+ } -+ -+ NBTTagCompound paper = nbttagcompound.getCompound("Paper"); -+ paper.setLong("LastLogin", handle.loginTime); -+ paper.setLong("LastSeen", System.currentTimeMillis()); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch deleted file mode 100644 index dcefdae5b465..000000000000 --- a/Spigot-Server-Patches/0320-Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: connorhartley -Date: Mon, 7 Jan 2019 14:43:48 -0600 -Subject: [PATCH] Workaround for vehicle tracking issue on disconnect - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8d88ed3d68146fbcb090847351945689518e59a9..82f49078a91b6ac471d303bc68891d80e201bd1f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1527,6 +1527,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void p() { - this.ch = true; - this.ejectPassengers(); -+ -+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. -+ if (this.isPassenger() && this.getVehicle() instanceof EntityPlayer) { -+ this.stopRiding(); -+ } -+ // Paper end -+ - if (this.isSleeping()) { - this.wakeup(true, false); - } diff --git a/Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch deleted file mode 100644 index 79adf82b5fd7..000000000000 --- a/Spigot-Server-Patches/0321-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 31 Jan 2019 16:33:36 -0500 -Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons - -There is an explicit check in the handling code for empty pistons that -prevents sticky pistons from firing the event. However when we look back -at the history we see that this check was originally added so that ONLY -sticky pistons would fire the retract event. I'm not sure why. -https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 - -Over the course of several updates, the meaning of that field appears to -have changed from "is NOT sticky" to "is sticky". So now its having the -opposite effect. Only normal pistons fire the retraction event. And like -all things in CB, it's just been carried around since. - -If we are to believe the history, the correct fix for this issue is to -flip it so it only fires for sticky pistons, but that puts us in a -bind. It's already firing for non-sticky pistons, changing it now would -likely result in breakage. Furthermore, there is little documentation as -to WHY that was ever intended to be the case. - -Instead we opt to remove the check entirely so that the event fires for -all piston types. - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 869aaae93bc83b8271644147bb569c868ab13fb8..7de86d6232eb84642fb6423a1b0a9f30d9df9f2b 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -141,7 +141,7 @@ public class BlockPiston extends BlockDirectional { - } - - // CraftBukkit start -- if (!this.sticky) { -+ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd - org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); - BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); - world.getServer().getPluginManager().callEvent(event); -@@ -149,7 +149,7 @@ public class BlockPiston extends BlockDirectional { - if (event.isCancelled()) { - return; - } -- } -+ //} // Paper - // PAIL: checkME - what happened to setTypeAndData? - // CraftBukkit end - world.playBlockAction(blockposition, this, b0, enumdirection.c()); diff --git a/Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch b/Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch deleted file mode 100644 index 64d8d081f731..000000000000 --- a/Spigot-Server-Patches/0322-Block-Entity-remove-from-being-called-on-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Feb 2019 23:33:24 -0500 -Subject: [PATCH] Block Entity#remove from being called on Players - -This doesn't result in the same behavior as other entities and causes -several problems. Anyone ever complain about the "Cannot send chat -message" thing? That's one of the issues this causes, among others. - -If a plugin developer can come up with a valid reason to call this on a -Player we will look at limiting the scope of this change. It appears to -be unintentional in the few cases we've seen so far. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 25e0d0dd7b114560896679f0314cea288d7a768c..f57ad014fb3d2ce2405bdd63db4c730458aac17a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2234,6 +2234,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void resetCooldown() { - getHandle().resetAttackCooldown(); - } -+ -+ @Override -+ public void remove() { -+ if (this.getHandle().getClass().equals(EntityPlayer.class)) { // special case for NMS plugins inheriting -+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); -+ } else { -+ super.remove(); -+ } -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0323-BlockDestroyEvent.patch b/Spigot-Server-Patches/0323-BlockDestroyEvent.patch deleted file mode 100644 index c27cd38c2753..000000000000 --- a/Spigot-Server-Patches/0323-BlockDestroyEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:20:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 88b1a0235bfc0b41ae1855f8900632e425730d1c..3b5ddc083719608e944bdefa38e1fd3909e8e200 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -26,6 +26,7 @@ import net.minecraft.core.particles.ParticleParam; - import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -@@ -559,8 +560,20 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return false; - } else { - Fluid fluid = this.getFluid(blockposition); -+ // Paper start - while the above setAir method is named same and looks very similar -+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, -+ // it doesn't imply destruction of a block that plays a sound effect / drops an item. -+ boolean playEffect = true; -+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, blockposition), fluid.getBlockData().createCraftBlockData(), flag); -+ if (!event.callEvent()) { -+ return false; -+ } -+ playEffect = event.playEffect(); -+ } -+ // Paper end - -- if (!(iblockdata.getBlock() instanceof BlockFireAbstract)) { -+ if (playEffect && !(iblockdata.getBlock() instanceof BlockFireAbstract)) { // Paper - this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata)); - } - diff --git a/Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch deleted file mode 100644 index e98607e7c32b..000000000000 --- a/Spigot-Server-Patches/0324-Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Jan 2019 00:08:15 -0500 -Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes - -Mojang implemented Shapeless different than Shaped - -This made the Bukkit RecipeChoice API not work for Shapeless. - -This reimplements vanilla logic using the same test logic as Shaped - -diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -index 9226602691ccbf39835f2dd071f171c2375b0a16..e112d149fc3a7af7f0c9a5280c94c9b03b2aba2d 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -@@ -72,16 +72,49 @@ public class ShapelessRecipes implements RecipeCrafting { - AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); - int i = 0; - -+ // Paper start -+ java.util.List providedItems = new java.util.ArrayList<>(); -+ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); -+ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); -+ // Paper end - for (int j = 0; j < inventorycrafting.getSize(); ++j) { - ItemStack itemstack = inventorycrafting.getItem(j); - - if (!itemstack.isEmpty()) { -- ++i; -- autorecipestackmanager.a(itemstack, 1); -+ // Paper start -+ itemstack = itemstack.cloneItemStack(); -+ providedItems.add(itemstack); -+ for (RecipeItemStack ingredient : ingredients) { -+ if (ingredient.test(itemstack)) { -+ matchedProvided.increment(itemstack); -+ matchedIngredients.increment(ingredient); -+ } -+ } -+ // Paper end - } - } - -- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); -+ // Paper start -+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { -+ return false; -+ } -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); -+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); -+ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); -+ -+ PROVIDED: -+ for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ RecipeItemStack ingredient = itIngredient.next(); -+ if (ingredient.test(provided)) { -+ itIngredient.remove(); -+ continue PROVIDED; -+ } -+ } -+ return false; -+ } -+ return ingredients.isEmpty(); -+ // Paper end - } - - public ItemStack a(InventoryCrafting inventorycrafting) { diff --git a/Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch b/Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch deleted file mode 100644 index d97a446a8411..000000000000 --- a/Spigot-Server-Patches/0325-Fix-sign-edit-memory-leak.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Feb 2019 00:15:28 -0500 -Subject: [PATCH] Fix sign edit memory leak - -when a player edits a sign, a reference to their Entity is never cleand up. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 7158d3e3a7e2912d8d170aca4096355d43645cfa..e54c06b1214091985d9e360592a7759ff45efc75 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2851,7 +2851,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - TileEntitySign tileentitysign = (TileEntitySign) tileentity; - -- if (!tileentitysign.d() || tileentitysign.f() != this.player) { -+ if (!tileentitysign.d() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { - PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getDisplayName().getString()); - this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit - return; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index ec550aaa4e7943af4ecdd2275f1f32c21edf770a..6d0fe58d7e574ce5189e1f7a8485060d60b466d9 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -30,6 +30,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private EntityHuman c; - private final FormattedString[] g; - private EnumColor color; -+ public java.util.UUID signEditor; // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -131,7 +132,10 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - public void a(EntityHuman entityhuman) { -- this.c = entityhuman; -+ // Paper start -+ //this.c = entityhuman; -+ signEditor = entityhuman != null ? entityhuman.getUniqueID() : null; -+ // Paper end - } - - public EntityHuman f() { diff --git a/Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch b/Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch deleted file mode 100644 index a6cd09820073..000000000000 --- a/Spigot-Server-Patches/0326-Limit-Client-Sign-length-more.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Feb 2019 22:18:40 -0500 -Subject: [PATCH] Limit Client Sign length more - -modified clients can send more data from the client -to the server and it would get stored on the sign as sent. - -Mojang has a limit of 384 which is much higher than reasonable. - -the client can barely render around 16 characters as-is, but formatting -codes can get it to be more than 16 actual length. - -Set a limit of 80 which should give an average of 16 characters 2 -sets of legacy formatting codes which should be plenty for all uses. - -This does not strip any existing data from the NBT as plugins -may use this for storing data out of the rendered area. - -it only impacts data sent from the client. - -Set -DPaper.maxSignLength=XX to change limit or -1 to disable - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index e54c06b1214091985d9e360592a7759ff45efc75..2c949e079e5de86c902b162dfdb6adffe0511448 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -256,6 +256,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { -@@ -2861,7 +2862,17 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. -+ // Paper start - cap line length - modified clients can send longer data than normal -+ String currentLine = list.get(i); -+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { -+ // This handles multibyte characters as 1 -+ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); -+ if (offset < currentLine.length()) { -+ list.set(i, currentLine = currentLine.substring(0, offset)); -+ } -+ } -+ // Paper end -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch deleted file mode 100644 index 033181274dda..000000000000 --- a/Spigot-Server-Patches/0327-Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 11:11:29 -0500 -Subject: [PATCH] Don't check ConvertSigns boolean every sign save - -property lookups arent super cheap. they synchronize, validate -and check security managers. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 6d0fe58d7e574ce5189e1f7a8485060d60b466d9..7f78f388584899b13ff983f0dc37c679bfb1507e 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -31,6 +31,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private final FormattedString[] g; - private EnumColor color; - public java.util.UUID signEditor; // Paper -+ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -51,7 +52,7 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - // CraftBukkit start -- if (Boolean.getBoolean("convertLegacySigns")) { -+ if (CONVERT_LEGACY_SIGNS) { // Paper - nbttagcompound.setBoolean("Bukkit.isConverted", true); - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch deleted file mode 100644 index 053340619faf..000000000000 --- a/Spigot-Server-Patches/0328-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 04:53:35 -0400 -Subject: [PATCH] Optimize Network Manager and add advanced packet support - -Adds ability for 1 packet to bundle other packets to follow it -Adds ability for a packet to delay sending more packets until a state is ready. - -Removes synchronization from sending packets -Removes processing packet queue off of main thread - - for the few cases where it is allowed, order is not necessary nor - should it even be happening concurrently in first place (handshaking/login/status) - -Ensures packets sent asynchronously are dispatched on main thread - -This helps ensure safety for ProtocolLib as packet listeners -are commonly accessing world state. This will allow you to schedule -a packet to be sent async, but itll be dispatched sync for packet -listeners to process. - -This should solve some deadlock risks - -Also adds Netty Channel Flush Consolidation to reduce the amount of flushing - -Also avoids spamming closed channel exception by rechecking closed state in dispatch -and then catch exceptions and close if they fire. - -Part of this commit was authored by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 6d40ade5a52383ed86d28d272c3dc83dbdcbd218..ab70eeaeca222de7de7cab1b3db14b2c4761c3c3 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -25,8 +25,15 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import net.minecraft.network.protocol.game.PacketPlayOutChat; -+import net.minecraft.network.protocol.game.PacketPlayOutKeepAlive; - import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; -+import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; -+import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.LazyInitVar; -@@ -75,6 +82,10 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; - private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); -+ // Optimize network -+ public boolean isPending = true; -+ public boolean queueImmunity = false; -+ public EnumProtocol protocol; - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -98,6 +109,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void setProtocol(EnumProtocol enumprotocol) { -+ protocol = enumprotocol; // Paper - this.channel.attr(NetworkManager.c).set(enumprotocol); - this.channel.config().setAutoRead(true); - NetworkManager.LOGGER.debug("Enabled auto read"); -@@ -168,19 +180,84 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - Validate.notNull(packetlistener, "packetListener", new Object[0]); - this.packetListener = packetlistener; - } -+ // Paper start -+ public EntityPlayer getPlayer() { -+ if (packetListener instanceof PlayerConnection) { -+ return ((PlayerConnection) packetListener).player; -+ } else { -+ return null; -+ } -+ } -+ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. -+ private static java.util.List buildExtraPackets(Packet packet) { -+ java.util.List extra = packet.getExtraPackets(); -+ if (extra == null || extra.isEmpty()) { -+ return null; -+ } -+ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); -+ buildExtraPackets0(extra, ret); -+ return ret; -+ } -+ -+ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { -+ for (Packet extra : extraPackets) { -+ into.add(extra); -+ java.util.List extraExtra = extra.getExtraPackets(); -+ if (extraExtra != null && !extraExtra.isEmpty()) { -+ buildExtraPackets0(extraExtra, into); -+ } -+ } -+ } -+ // Paper start -+ private static boolean canSendImmediate(NetworkManager networkManager, Packet packet) { -+ return networkManager.isPending || networkManager.protocol != EnumProtocol.PLAY || -+ packet instanceof PacketPlayOutKeepAlive || -+ packet instanceof PacketPlayOutChat || -+ packet instanceof PacketPlayOutTabComplete || -+ packet instanceof PacketPlayOutTitle || -+ packet instanceof PacketPlayOutBoss; -+ } -+ // Paper end -+ } -+ // Paper end - - public void sendPacket(Packet packet) { - this.sendPacket(packet, (GenericFutureListener) null); - } - - public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { -- if (this.isConnected()) { -- this.p(); -- this.b(packet, genericfuturelistener); -- } else { -- this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ // Paper start - handle oversized packets better -+ boolean connected = this.isConnected(); -+ if (!connected && !preparing) { -+ return; // Do nothing -+ } -+ packet.onPacketDispatch(getPlayer()); -+ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && -+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) -+ ))) { -+ this.dispatchPacket(packet, genericfuturelistener); -+ return; - } -+ // write the packets to the queue, then flush - antixray hooks there already -+ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); -+ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); -+ if (!hasExtraPackets) { -+ this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ } else { -+ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); -+ packets.add(new NetworkManager.QueuedPacket(packet, null)); // delay the future listener until the end of the extra packets -+ -+ for (int i = 0, len = extraPackets.size(); i < len;) { -+ Packet extra = extraPackets.get(i); -+ boolean end = ++i == len; -+ packets.add(new NetworkManager.QueuedPacket(extra, end ? genericfuturelistener : null)); // append listener to the end -+ } - -+ this.packetQueue.addAll(packets); // atomic -+ } -+ this.sendPacketQueue(); -+ // Paper end - } - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -194,51 +271,116 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); - } - -+ EntityPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (genericfuturelistener != null) { - channelfuture.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - -+ - if (genericfuturelistener != null) { - channelfuture1.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); - } - - } - -- private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER -- private void p() { -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.packetQueue; -- -+ // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean -+ if (!isConnected()) { -+ return true; -+ } -+ if (MCUtil.isMainThread()) { -+ return processQueue(); -+ } else if (isPending) { -+ // Should only happen during login/status stages - synchronized (this.packetQueue) { -- NetworkManager.QueuedPacket networkmanager_queuedpacket; -- -- while ((networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.packetQueue.poll()) != null) { -- this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); -- } -+ return this.processQueue(); -+ } -+ } -+ return false; -+ } -+ private boolean processQueue() { -+ if (this.packetQueue.isEmpty()) return true; -+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore -+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue -+ java.util.Iterator iterator = this.packetQueue.iterator(); -+ while (iterator.hasNext()) { -+ NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek -+ -+ // Fix NPE (Spigot bug caused by handleDisconnection()) -+ if (queued == null) { -+ return true; -+ } - -+ Packet packet = queued.getPacket(); -+ if (!packet.isReady()) { -+ return false; -+ } else { -+ iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); - } - } -+ return true; - } -+ // Paper end - - public void a() { - this.p(); -@@ -271,9 +413,21 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - return this.socketAddress; - } - -+ // Paper start -+ public void clearPacketQueue() { -+ EntityPlayer player = getPlayer(); -+ packetQueue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); -+ if (packet.hasFinishListener()) { -+ packet.onPacketDispatchFinish(player, null); -+ } -+ }); -+ packetQueue.clear(); -+ } // Paper end - public void close(IChatBaseComponent ichatbasecomponent) { - // Spigot Start - this.preparing = false; -+ clearPacketQueue(); // Paper - // Spigot End - if (this.channel.isOpen()) { - this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -341,7 +495,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public void handleDisconnection() { - if (this.channel != null && !this.channel.isOpen()) { - if (this.o) { -- NetworkManager.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message - } else { - this.o = true; - if (this.k() != null) { -@@ -349,7 +503,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } else if (this.j() != null) { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } -- this.packetQueue.clear(); // Free up packet queue. -+ clearPacketQueue(); // Paper - // Paper start - Add PlayerConnectionCloseEvent - final PacketListener packetListener = this.j(); - if (packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 0783b0777c8d7788bbf6780b464b709bf6dc2191..b644c91cecd8a347319dfe8c8923fd05919a9795 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -@@ -13,6 +14,20 @@ public interface Packet { - void a(T t0); - - // Paper start -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ * @param future Can be null if packet was cancelled -+ */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default boolean hasFinishListener() { return false; } -+ default boolean isReady() { return true; } -+ default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { - return false; - } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index d992cb5cd827e0fe655809e1088939cdad9c2301..dc362724ea0cc1b2f9d9ceffff483217b4356c40 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -54,10 +55,12 @@ public class ServerConnection { - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - NetworkManager manager = null; - while ((manager = pending.poll()) != null) { - connectedChannels.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -92,6 +95,7 @@ public class ServerConnection { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND)); - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); diff --git a/Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch b/Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index ee9073137cd3..000000000000 --- a/Spigot-Server-Patches/0329-Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0059ede4ba3ff271d47dd38ea87fddc2399aa008..a7d10d124021f3427f23fcd533f885367b64515c 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -34,7 +34,15 @@ public class PacketPlayOutMapChunk implements Packet { - private boolean h; - - public PacketPlayOutMapChunk() {} -+ // Paper start -+ private final java.util.List extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public PacketPlayOutMapChunk(Chunk chunk, int i) { - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - -@@ -61,6 +69,7 @@ public class PacketPlayOutMapChunk implements Packet { - this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); -+ int totalTileEntities = 0; // Paper - - while (iterator.hasNext()) { - entry = (Entry) iterator.next(); -@@ -69,6 +78,15 @@ public class PacketPlayOutMapChunk implements Packet { - int j = blockposition.getY() >> 4; - - if (this.f() || (i & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - NBTTagCompound nbttagcompound = tileentity.b(); - if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch deleted file mode 100644 index fe3dd5e8b27a..000000000000 --- a/Spigot-Server-Patches/0330-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 16:12:35 -0500 -Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency - -mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) - -some things checked PlayerList, some checked object. This moves -everything to the Whitelist object. - -https://github.com/PaperMC/Paper/issues/1880 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7515e9ddbc89de882373469cf3c46046c76af974..1a4ae92065f729ec521752bb87df8343d747f566 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; -@@ -1016,9 +1017,9 @@ public abstract class PlayerList { - } - public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { - boolean isOp = this.operators.d(gameprofile); -- boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ boolean isWhitelisted = !this.getHasWhitelist() || isOp || this.whitelist.d(gameprofile); - final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.getHasWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); - event.callEvent(); - if (!event.isWhitelisted()) { - if (loginEvent != null) { diff --git a/Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch deleted file mode 100644 index 30e7bd3924ac..000000000000 --- a/Spigot-Server-Patches/0331-Set-Zombie-last-tick-at-start-of-drowning-process.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Mon, 4 Mar 2019 02:23:28 -0500 -Subject: [PATCH] Set Zombie last tick at start of drowning process - -Fixes GH-1887 - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 79d34b0296f88e5b4fe0351fe2483fc0128deabc..f406826945dd752e6528743a0c8cad3cfdfc4a95 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -223,6 +223,7 @@ public class EntityZombie extends EntityMonster { - ++this.bt; - if (this.bt >= 600) { - this.startDrownedConversion(300); -+ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 - } - } else { - this.bt = -1; diff --git a/Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch b/Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch deleted file mode 100644 index 56fb7e5bc7aa..000000000000 --- a/Spigot-Server-Patches/0332-Allow-Saving-of-Oversized-Chunks.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Feb 2019 01:08:19 -0500 -Subject: [PATCH] Allow Saving of Oversized Chunks - -The Minecraft World Region File format has a hard cap of 1MB per chunk. -This is due to the fact that the header of the file format only allocates -a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. - -This limit can be reached fairly easily with books, resulting in the chunk being unable -to save to the world. Worse off, is that nothing printed when this occured, and silently -performed a chunk rollback on next load. - -This leads to security risk with duplication and is being actively exploited. - -This patch catches the too large scenario, falls back and moves any large Entity -or Tile Entity into a new compound, and this compound is saved into a different file. - -On Chunk Load, we check for oversized status, and if so, we load the extra file and -merge the Entities and Tile Entities from the oversized chunk back into the level to -then be loaded as normal. - -Once a chunk is returned back to normal size, the oversized flag will clear, and no -extra data file will exist. - -This fix maintains compatability with all existing Anvil Region Format tools as it -does not alter the save format. They will just not know about the extra entities. - -This fix also maintains compatability if someone switches server jars to one without -this fix, as the data will remain in the oversized file. Once the server returns -to a jar with this fix, the data will be restored. - -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 850d3a7bb8ae4c43c0e2f737cfe69261f338b026..20410a5853e34c90c872f5e9592d50c4727e914d 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -132,6 +132,7 @@ public class NBTCompressedStreamTools { - - } - -+ public static NBTTagCompound readNBT(DataInput datainput) throws IOException { return a(datainput); } // Paper - OBFHELPER - public static NBTTagCompound a(DataInput datainput) throws IOException { - return a(datainput, NBTReadLimiter.a); - } -@@ -152,6 +153,7 @@ public class NBTCompressedStreamTools { - } - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { a(nbttagcompound, dataoutput); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { - a((NBTBase) nbttagcompound, dataoutput); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 4bf3e0cb4602d33a2e00c502b1dd212032b22a8f..00cef1c0bc19976a000389e57a1af5d93690c0e7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; - import java.nio.file.StandardOpenOption; -+import java.util.zip.InflaterInputStream; // Paper -+ - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.nbt.NBTCompressedStreamTools; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -38,6 +42,7 @@ public class RegionFile implements AutoCloseable { - private final IntBuffer i; - @VisibleForTesting - protected final RegionFileBitSet freeSectors; -+ public final File file; // Paper - - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); -@@ -45,6 +50,8 @@ public class RegionFile implements AutoCloseable { - - public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { - this.g = ByteBuffer.allocateDirect(8192); -+ this.file = path.toFile(); // Paper -+ initOversizedState(); // Paper - this.freeSectors = new RegionFileBitSet(); - this.f = regionfilecompression; - if (!Files.isDirectory(path1, new LinkOption[0])) { -@@ -408,6 +415,74 @@ public class RegionFile implements AutoCloseable { - void run() throws IOException; - } - -+ // Paper start -+ private final byte[] oversized = new byte[1024]; -+ private int oversizedCount = 0; -+ -+ private synchronized void initOversizedState() throws IOException { -+ File metaFile = getOversizedMetaFile(); -+ if (metaFile.exists()) { -+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); -+ System.arraycopy(read, 0, oversized, 0, oversized.length); -+ for (byte temp : oversized) { -+ oversizedCount += temp; -+ } -+ } -+ } -+ -+ private static int getChunkIndex(int x, int z) { -+ return (x & 31) + (z & 31) * 32; -+ } -+ synchronized boolean isOversized(int x, int z) { -+ return this.oversized[getChunkIndex(x, z)] == 1; -+ } -+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { -+ final int offset = getChunkIndex(x, z); -+ boolean previous = this.oversized[offset] == 1; -+ this.oversized[offset] = (byte) (oversized ? 1 : 0); -+ if (!previous && oversized) { -+ oversizedCount++; -+ } else if (!oversized && previous) { -+ oversizedCount--; -+ } -+ if (previous && !oversized) { -+ File oversizedFile = getOversizedFile(x, z); -+ if (oversizedFile.exists()) { -+ oversizedFile.delete(); -+ } -+ } -+ if (oversizedCount > 0) { -+ if (previous != oversized) { -+ writeOversizedMeta(); -+ } -+ } else if (previous) { -+ File oversizedMetaFile = getOversizedMetaFile(); -+ if (oversizedMetaFile.exists()) { -+ oversizedMetaFile.delete(); -+ } -+ } -+ } -+ -+ private void writeOversizedMeta() throws IOException { -+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); -+ } -+ -+ private File getOversizedMetaFile() { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); -+ } -+ -+ private File getOversizedFile(int x, int z) { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); -+ } -+ -+ synchronized NBTTagCompound getOversizedData(int x, int z) throws IOException { -+ File file = getOversizedFile(x, z); -+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { -+ return NBTCompressedStreamTools.readNBT((java.io.DataInput) out); -+ } -+ -+ } -+ // Paper end - class ChunkBuffer extends ByteArrayOutputStream { - - private final ChunkCoordIntPair b; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 75b10a3755392870d8f5b51239a09a0e7fd75a42..ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -9,8 +9,10 @@ import java.io.DataOutputStream; - import java.io.File; - import java.io.IOException; - import javax.annotation.Nullable; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -50,6 +52,74 @@ public final class RegionFileCache implements AutoCloseable { - } - } - -+ // Paper start -+ private static void printOversizedLog(String msg, File file, int x, int z) { -+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); -+ } -+ -+ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; -+ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; -+ private static final int OVERZEALOUS_THRESHOLD = 1024; -+ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; -+ private static void resetFilterThresholds() { -+ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); -+ } -+ static { -+ resetFilterThresholds(); -+ } -+ -+ static boolean isOverzealous() { -+ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; -+ } -+ -+ -+ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { -+ synchronized (regionfile) { -+ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { -+ NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -+ NBTTagCompound chunk = NBTCompressedStreamTools.readNBT((DataInput) datainputstream); -+ if (oversizedData == null) { -+ return chunk; -+ } -+ NBTTagCompound oversizedLevel = oversizedData.getCompound("Level"); -+ NBTTagCompound level = chunk.getCompound("Level"); -+ -+ mergeChunkList(level, oversizedLevel, "Entities"); -+ mergeChunkList(level, oversizedLevel, "TileEntities"); -+ -+ chunk.set("Level", level); -+ -+ return chunk; -+ } catch (Throwable throwable) { -+ throwable.printStackTrace(); -+ throw throwable; -+ } -+ } -+ } -+ -+ private static void mergeChunkList(NBTTagCompound level, NBTTagCompound oversizedLevel, String key) { -+ NBTTagList levelList = level.getList(key, 10); -+ NBTTagList oversizedList = oversizedLevel.getList(key, 10); -+ -+ if (!oversizedList.isEmpty()) { -+ levelList.addAll(oversizedList); -+ level.set(key, levelList); -+ } -+ } -+ -+ private static int getNBTSize(NBTBase nbtBase) { -+ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); -+ try { -+ nbtBase.write(test); -+ return test.size(); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return 0; -+ } -+ } -+ -+ // Paper End -+ - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -@@ -59,6 +129,12 @@ public final class RegionFileCache implements AutoCloseable { - } - // CraftBukkit end - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); -+ // Paper start -+ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); -+ return readOversizedChunk(regionfile, chunkcoordintpair); -+ } -+ // Paper end - Throwable throwable = null; - - NBTTagCompound nbttagcompound; -@@ -99,6 +175,7 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; diff --git a/Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch deleted file mode 100644 index f3f9b1eb62b0..000000000000 --- a/Spigot-Server-Patches/0333-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:08:09 +0200 -Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1a4ae92065f729ec521752bb87df8343d747f566..1ae969aff1d44ad9af28fc94d8821884b9ad0563 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1135,6 +1135,7 @@ public abstract class PlayerList { - } - - public void setHasWhitelist(boolean flag) { -+ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(flag).callEvent(); - this.hasWhitelist = flag; - } - diff --git a/Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch b/Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index d556d1b4ec3f..000000000000 --- a/Spigot-Server-Patches/0334-Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:33:08 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 1e5930f5ae75b82abf6ea2a50558449fb667016f..e9b535622d6c33083c575ee4691598014dba0e2c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1504,6 +1504,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.c(f - 90.0F, f1); - } - -+ public final Vec3D getEyePosition(float partialTicks) { return j(partialTicks); } // Paper - OBFHELPER - public final Vec3D j(float f) { - if (f == 1.0F) { - return new Vec3D(this.locX(), this.getHeadY(), this.locZ()); -@@ -2149,6 +2150,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.getPassengers().size() < 1; - } - -+ public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER - public float bg() { - return 0.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 6ada2fe58966553b52a8a890088c78d5ea0dfd73..c98562980ca02c85f2f777a31983c164f2dd5e1e 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -108,6 +108,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSet - import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.ScoreboardTeam; - import org.apache.logging.log4j.Logger; -@@ -3637,6 +3638,37 @@ public abstract class EntityLiving extends Entity { - return world.rayTrace(raytrace); - } - -+ public MovingObjectPositionEntity getTargetEntity(int maxDistance) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = this.getEyePosition(1.0F); -+ Vec3D direction = this.getLookDirection(); -+ Vec3D end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); -+ -+ List entityList = world.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).grow(1.0D, 1.0D, 1.0D), IEntitySelector.canAITarget().and(Entity::isInteractable)); -+ -+ double distance = 0.0D; -+ MovingObjectPositionEntity result = null; -+ -+ for (Entity entity : entityList) { -+ AxisAlignedBB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); -+ Optional rayTraceResult = aabb.calculateIntercept(start, end); -+ -+ if (rayTraceResult.isPresent()) { -+ Vec3D rayTrace = rayTraceResult.get(); -+ double distanceTo = start.distanceSquared(rayTrace); -+ if (distanceTo < distance || distance == 0.0D) { -+ result = new MovingObjectPositionEntity(entity, rayTrace); -+ distance = distanceTo; -+ } -+ } -+ } -+ -+ return result; -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 4776a47566aac487dc77fd6b4b9b42b95974e31a..cb5cda5e6497edeb801ef712f9bd8823cb055750 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -22,6 +22,7 @@ public final class IEntitySelector { - public static final Predicate e = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative(); - }; -+ public static Predicate canAITarget() { return f; } // Paper - OBFHELPER - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 3941dd33da4b5c09d0087143f1d8a2d76fc18792..62513c812b497bb9d8dafe1d9c2f574059aebf15 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -116,6 +116,7 @@ public class AxisAlignedBB { - return this.b(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final AxisAlignedBB expand(double x, double y, double z) { return b(x, y, z); } // Paper - OBFHELPER - public AxisAlignedBB b(double d0, double d1, double d2) { - double d3 = this.minX; - double d4 = this.minY; -@@ -145,6 +146,12 @@ public class AxisAlignedBB { - return new AxisAlignedBB(d3, d4, d5, d6, d7, d8); - } - -+ // Paper start -+ public AxisAlignedBB grow(double d0) { -+ return grow(d0, d0, d0); -+ } -+ // Paper end -+ - public AxisAlignedBB grow(double d0, double d1, double d2) { - double d3 = this.minX - d0; - double d4 = this.minY - d1; -@@ -204,6 +211,7 @@ public class AxisAlignedBB { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } - -+ public final boolean contains(Vec3D vec3d) { return d(vec3d); } // Paper - OBFHELPER - public boolean d(Vec3D vec3d) { - return this.e(vec3d.x, vec3d.y, vec3d.z); - } -@@ -237,6 +245,7 @@ public class AxisAlignedBB { - return this.g(-d0); - } - -+ public final Optional calculateIntercept(Vec3D vec3d, Vec3D vec3d1) { return b(vec3d, vec3d1); } // Paper - OBFHELPER - public Optional b(Vec3D vec3d, Vec3D vec3d1) { - double[] adouble = new double[]{1.0D}; - double d0 = vec3d1.x - vec3d.x; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index c692626b747008a5418ecabf550fc67e3b676f5b..ff586b8366a6298f1906551b068e8abb26fcabc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.entity.TargetEntityInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -42,8 +43,11 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -227,6 +231,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), - MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); - } -+ -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); -+ } -+ -+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getPos().x, rayTrace.getPos().y, rayTrace.getPos().z)); -+ } -+ -+ public MovingObjectPositionEntity rayTraceEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = getHandle().getTargetEntity(maxDistance); -+ if (rayTrace == null) { -+ return null; -+ } -+ if (!ignoreBlocks) { -+ MovingObjectPosition rayTraceBlocks = getHandle().getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ if (rayTraceBlocks != null) { -+ Vec3D eye = getHandle().getEyePosition(1.0F); -+ if (eye.distanceSquared(rayTraceBlocks.getPos()) <= eye.distanceSquared(rayTrace.getPos())) { -+ return null; -+ } -+ } -+ } -+ return rayTrace; -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch deleted file mode 100644 index b9eefdc882e5..000000000000 --- a/Spigot-Server-Patches/0335-Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kashike -Date: Wed, 20 Mar 2019 21:19:29 -0700 -Subject: [PATCH] Use proper max length when serialising BungeeCord text - component - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index f6a1c5ac9acb34b1ef2262721adbbb1a5b0feaf7..fefcacf27d71c67403555502685a992a5a706099 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -9,7 +9,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutChat implements Packet { -- -+ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private IChatBaseComponent a; - public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -43,9 +43,9 @@ public class PacketPlayOutChat implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below - // Paper start - don't nest if we don't need to so that we can preserve formatting - if (this.components.length == 1) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length - } else { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length - } - // Paper end - } else { diff --git a/Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch b/Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch deleted file mode 100644 index 04f236f973e2..000000000000 --- a/Spigot-Server-Patches/0336-Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:24:52 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index ecb4cb5df868673e5aa2eec3fdd8618dbea09655..d7c6f49ba1c84c45b387e155d9ae7452e5171df6 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1041,6 +1041,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1ae969aff1d44ad9af28fc94d8821884b9ad0563..47aa69dfe43390b811c264adc0af1d01bcd5ce4d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -335,7 +335,7 @@ public abstract class PlayerList { - // CraftBukkit start - WorldServer finalWorldServer = worldserver1; - Entity entity = EntityTypes.a(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { -- return !finalWorldServer.addEntitySerialized(entity1) ? null : entity1; -+ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper - // CraftBukkit end - }); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e9b535622d6c33083c575ee4691598014dba0e2c..cbdd75feb7250e771111184b1fac7c4a6bf6e575 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -63,6 +63,8 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -158,6 +160,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - }; - public List entitySlice = null; -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1673,6 +1676,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (this.origin != null) { - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ if (spawnReason != null) { -+ nbttagcompound.setString("Paper.SpawnReason", spawnReason.name()); -+ } - // Save entity's from mob spawner status - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -@@ -1807,6 +1813,26 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (nbttagcompound.hasKey("Paper.SpawnReason")) { -+ String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); -+ try { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); -+ } catch (Exception ignored) { -+ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); -+ } -+ } -+ if (spawnReason == null) { -+ if (spawnedViaMobSpawner) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; -+ } else if (this instanceof EntityInsentient && (this instanceof EntityAnimal || this instanceof EntityFish) && !((EntityInsentient) this).isTypeNotPersistent(0.0)) { -+ if (!nbttagcompound.getBoolean("PersistenceRequired")) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; -+ } -+ } -+ } -+ if (spawnReason == null) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; -+ } - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 867478484c0ba4ff467b96e458689937299b981d..34bcee4ff55ba118ba393e94b3c25ee2b84feaa2 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -183,6 +183,7 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 3642b17cafffd2818ee7a18d26bc25645f596115..93bbf63e9d38f32d5528c7693633d4b65655bb9d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean fromMobSpawner() { - return getHandle().spawnedViaMobSpawner; - } -+ -+ @Override -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { -+ return getHandle().spawnReason; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch b/Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index f05b82653c43..000000000000 --- a/Spigot-Server-Patches/0337-Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index e3cdea3c85d762af6984f3dbe544fdfe101f6ff6..6110d7723b70df5380338a42b5cbff3446294bac 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -421,6 +421,12 @@ public class EntityTrackerEntry { - return PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastIncludingSelf(Packet packet) { - this.f.accept(packet); - if (this.tracker instanceof EntityPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 2c949e079e5de86c902b162dfdb6adffe0511448..02ae07db49d3793c0cc40ebe55cdc6b383f9b2e3 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2287,7 +2287,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem) { - // Refresh the current entity metadata -- this.sendPacket(new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true)); -+ // Paper start - update entity for all players -+ PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet); -+ } else { -+ this.sendPacket(packet); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch b/Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch deleted file mode 100644 index 8a761d4f0cca..000000000000 --- a/Spigot-Server-Patches/0338-Implement-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:31:00 -0700 -Subject: [PATCH] Implement PlayerPostRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 47aa69dfe43390b811c264adc0af1d01bcd5ce4d..ec4e84f6275f8b305fb5a64f9c0cff24729d73ec 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -741,9 +741,14 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed - boolean flag2 = false; - -+ // Paper start -+ boolean isBedSpawn = false; -+ boolean isRespawn = false; -+ // Paper end -+ - // CraftBukkit start - fire PlayerRespawnEvent - if (location == null) { -- boolean isBedSpawn = false; -+ // boolean isBedSpawn = false; // Paper - moved up - WorldServer worldserver1 = this.server.getWorldServer(entityplayer.getSpawnDimension()); - if (worldserver1 != null) { - Optional optional; -@@ -794,6 +799,7 @@ public abstract class PlayerList { - - location = respawnEvent.getRespawnLocation(); - if (!flag) entityplayer.reset(); // SPIGOT-4785 -+ isRespawn = true; // Paper - } else { - location.setWorld(worldserver.getWorld()); - } -@@ -851,6 +857,13 @@ public abstract class PlayerList { - if (entityplayer.playerConnection.isDisconnected()) { - this.savePlayerFile(entityplayer); - } -+ -+ // Paper start -+ if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); -+ } -+ // Paper end -+ - // CraftBukkit end - return entityplayer1; - } diff --git a/Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch deleted file mode 100644 index f77a4f7db2e0..000000000000 --- a/Spigot-Server-Patches/0339-don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:09:20 -0400 -Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items - -vanilla checks for == 0 - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 4cfe3475fa913cd46116f13ea8ed9caf5372a41a..02e4d6891adc902f73ed349f15dae3a429bd283a 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -87,6 +87,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end -@@ -179,6 +180,7 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end diff --git a/Spigot-Server-Patches/0340-Server-Tick-Events.patch b/Spigot-Server-Patches/0340-Server-Tick-Events.patch deleted file mode 100644 index fc5d42ec1573..000000000000 --- a/Spigot-Server-Patches/0340-Server-Tick-Events.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 22:48:45 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4d44604da7c65df6d8e87b6c6c56371ca307c11f..7ef01f2f80eea31fa76d22c3a0d5036883dee516 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1239,6 +1239,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Wed, 27 Mar 2019 23:01:33 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 82f49078a91b6ac471d303bc68891d80e201bd1f..a15b119b24090ffc607bfc9003d5b95f3acf3b2f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -695,6 +695,46 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - }); - } - -+ // Paper start - process inventory -+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { -+ List itemsToKeep = event.getItemsToKeep(); -+ if (inv == null) { -+ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? -+ if (!itemsToKeep.isEmpty()) { -+ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { -+ event.getEntity().getInventory().addItem(itemStack); -+ } -+ } -+ -+ return; -+ } -+ -+ for (int i = 0; i < inv.size(); ++i) { -+ ItemStack item = inv.get(i); -+ if (EnchantmentManager.shouldNotDrop(item) || itemsToKeep.isEmpty() || item.isEmpty()) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ continue; -+ } -+ -+ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); -+ boolean keep = false; -+ final Iterator iterator = itemsToKeep.iterator(); -+ while (iterator.hasNext()) { -+ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); -+ if (bukkitStack.equals(itemStack)) { -+ iterator.remove(); -+ keep = true; -+ break; -+ } -+ } -+ -+ if (!keep) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ } -+ } -+ } -+ // Paper end -+ - @Override - public void die(DamageSource damagesource) { - boolean flag = this.world.getGameRules().getBoolean(GameRules.SHOW_DEATH_MESSAGES); -@@ -778,7 +818,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.dropExperience(); - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { -- this.inventory.clear(); -+ // Paper start - replace logic -+ for (NonNullList inv : this.inventory.getComponents()) { -+ processKeep(event, inv); -+ } -+ processKeep(event, null); -+ // Paper end - } - - this.setSpectatorTarget(this); // Remove spectated target diff --git a/Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch b/Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch deleted file mode 100644 index bcc309836458..000000000000 --- a/Spigot-Server-Patches/0342-Optimize-Captured-TileEntity-Lookup.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Apr 2019 10:16:48 -0400 -Subject: [PATCH] Optimize Captured TileEntity Lookup - -upstream was doing a containsKey/get pattern, and always doing it at that. -that scenario is only even valid if were in the middle of a block place. - -Optimize to check if the captured list even has values in it, and also to -just do a get call since the value can never be null. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 3b5ddc083719608e944bdefa38e1fd3909e8e200..b6b9a471426ddf911a1f6bf38543c0304bfc31f6 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -968,12 +968,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return null; - } else { - // CraftBukkit start -- if (capturedTileEntities.containsKey(blockposition)) { -- return capturedTileEntities.get(blockposition); -+ TileEntity tileentity = null; // Paper -+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper -+ return tileentity; // Paper - } - // CraftBukkit end - -- TileEntity tileentity = null; -+ //TileEntity tileentity = null; // Paper - move up - - if (this.tickingTileEntities) { - tileentity = this.E(blockposition); diff --git a/Spigot-Server-Patches/0343-Add-Heightmap-API.patch b/Spigot-Server-Patches/0343-Add-Heightmap-API.patch deleted file mode 100644 index f2e6c957312c..000000000000 --- a/Spigot-Server-Patches/0343-Add-Heightmap-API.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 1 Jan 2019 02:22:01 -0800 -Subject: [PATCH] Add Heightmap API - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b6b9a471426ddf911a1f6bf38543c0304bfc31f6..12ac3608736b45447afe6b0d35ead1441390be5e 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -670,8 +670,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - } - -- @Override -- public int a(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(final HeightMap.Type heightmap, final int x, final int z) { return this.a(heightmap, x, z); } // Paper - OBFHELPER -+ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper - OBFHELPER - int k; - - if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 95b4774b7696fa9711d7169d06a23c70364bfdb2..9e44b60843a6463951382cb66c93f1fab24e5e5d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -343,6 +343,29 @@ public class CraftWorld implements World { - return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); - } - -+ // Paper start - Implement heightmap api -+ @Override -+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas -+ -+ switch (heightmap) { -+ case LIGHT_BLOCKING: -+ throw new UnsupportedOperationException(); // TODO -+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); -+ case ANY: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.WORLD_SURFACE, x, z); -+ case SOLID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.OCEAN_FLOOR, x, z); -+ case SOLID_OR_LIQUID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING, x, z); -+ case SOLID_OR_LIQUID_NO_LEAVES: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); -+ default: -+ throw new UnsupportedOperationException(); -+ } -+ } -+ // Paper end -+ - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); diff --git a/Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch b/Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index 37f6cfaac54e..000000000000 --- a/Spigot-Server-Patches/0344-Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:13 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 34bcee4ff55ba118ba393e94b3c25ee2b84feaa2..5538404456dfee42257fad9040fcc0fefdfc5fab 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -65,6 +65,7 @@ public abstract class MobSpawnerAbstract { - this.mobs.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 - } - -+ public boolean isActivated() { return h(); } // Paper - OBFHELPER - private boolean h() { - BlockPosition blockposition = this.b(); - -@@ -221,6 +222,7 @@ public abstract class MobSpawnerAbstract { - } - } - -+ public void resetTimer() { i(); } // Paper - OBFHELPER - private void i() { - if (this.maxSpawnDelay <= this.minSpawnDelay) { - this.spawnDelay = this.minSpawnDelay; -@@ -238,7 +240,13 @@ public abstract class MobSpawnerAbstract { - } - - public void a(NBTTagCompound nbttagcompound) { -+ // Paper start - use larger int if set -+ if (nbttagcompound.hasKey("Paper.Delay")) { -+ this.spawnDelay = nbttagcompound.getInt("Paper.Delay"); -+ } else { - this.spawnDelay = nbttagcompound.getShort("Delay"); -+ } -+ // Paper end - this.mobs.clear(); - if (nbttagcompound.hasKeyOfType("SpawnPotentials", 9)) { - NBTTagList nbttaglist = nbttagcompound.getList("SpawnPotentials", 10); -@@ -253,10 +261,15 @@ public abstract class MobSpawnerAbstract { - } else if (!this.mobs.isEmpty()) { - this.setSpawnData((MobSpawnerData) WeightedRandom.a(this.a().random, this.mobs)); - } -- -+ // Paper start - use ints if set -+ if (nbttagcompound.hasKeyOfType("Paper.MinSpawnDelay", 99)) { -+ this.minSpawnDelay = nbttagcompound.getInt("Paper.MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("Paper.MaxSpawnDelay"); -+ this.spawnCount = nbttagcompound.getShort("SpawnCount"); -+ } else // Paper end - if (nbttagcompound.hasKeyOfType("MinSpawnDelay", 99)) { -- this.minSpawnDelay = nbttagcompound.getShort("MinSpawnDelay"); -- this.maxSpawnDelay = nbttagcompound.getShort("MaxSpawnDelay"); -+ this.minSpawnDelay = nbttagcompound.getInt("MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("MaxSpawnDelay"); - this.spawnCount = nbttagcompound.getShort("SpawnCount"); - } - -@@ -281,9 +294,20 @@ public abstract class MobSpawnerAbstract { - if (minecraftkey == null) { - return nbttagcompound; - } else { -- nbttagcompound.setShort("Delay", (short) this.spawnDelay); -- nbttagcompound.setShort("MinSpawnDelay", (short) this.minSpawnDelay); -- nbttagcompound.setShort("MaxSpawnDelay", (short) this.maxSpawnDelay); -+ // Paper start -+ if (spawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.Delay", this.spawnDelay); -+ } -+ nbttagcompound.setShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); -+ -+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.MinSpawnDelay", this.minSpawnDelay); -+ nbttagcompound.setInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); -+ } -+ -+ nbttagcompound.setShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); -+ nbttagcompound.setShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); -+ // Paper end - nbttagcompound.setShort("SpawnCount", (short) this.spawnCount); - nbttagcompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities); - nbttagcompound.setShort("RequiredPlayerRange", (short) this.requiredPlayerRange); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -index 28295ebd338806a35cbef164cb014abfe7dae769..3d29be926e36b9a5a981eea1f2a1ec54a4c43393 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -1,13 +1,21 @@ - package org.bukkit.craftbukkit.block; - - import com.google.common.base.Preconditions; -+import net.minecraft.core.IRegistry; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.MobSpawnerData; - import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.CreatureSpawner; - import org.bukkit.entity.EntityType; -+// Paper start -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { - -@@ -121,4 +129,30 @@ public class CraftCreatureSpawner extends CraftBlockEntityState -Date: Mon, 6 May 2019 01:29:25 -0400 -Subject: [PATCH] Per-Player View Distance API placeholders - -I hope to look at this more in-depth soon. It appears doable. -However this should not block the update. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 51993191e01f55e16667c25b8b57d6a6ddaf493b..5168a40eb53565bb3028efe559601acf72bddae5 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -625,9 +625,10 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 145767e8b0fc4105a0afa47af17dcdbb75e952bc..174eb12722872182b2d9b54841e5bb57893695a1 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -258,9 +258,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (EntityPlayer player : (List)this.world.getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index f57ad014fb3d2ce2405bdd63db4c730458aac17a..dc8545241ed62f6b654b2559e025c3b34c00575f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2243,6 +2243,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - super.remove(); - } - } -+ -+ @Override -+ public int getViewDistance() { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch b/Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch deleted file mode 100644 index 9d2ee3f6277a..000000000000 --- a/Spigot-Server-Patches/0346-Fix-CB-call-to-changed-postToMainThread-method.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 10 May 2019 18:38:19 +0100 -Subject: [PATCH] Fix CB call to changed postToMainThread method - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 02ae07db49d3793c0cc40ebe55cdc6b383f9b2e3..d84d87b0dd01b4d67e55f1b445928285c45a08ca 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -445,7 +445,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.networkManager.getClass(); - // CraftBukkit - Don't wait -- minecraftserver.postToMainThread(networkmanager::handleDisconnection); -+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper - } - - private void a(T t0, Consumer consumer, BiFunction>> bifunction) { diff --git a/Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch deleted file mode 100644 index 05a0bc0d4c36..000000000000 --- a/Spigot-Server-Patches/0347-Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 27 Apr 2019 20:00:43 +0100 -Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) - -This also fixes the adding sound playing when the item frame direction is changed. - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -index 584f64946821092afab57b9409bc249403bc16e7..43152a6c70c9433d627a58051101530ddd693307 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -@@ -277,7 +277,7 @@ public class EntityItemFrame extends EntityHanging { - } - - this.getDataWatcher().set(EntityItemFrame.ITEM, itemstack); -- if (!itemstack.isEmpty() && playSound) { // CraftBukkit -+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set - this.playSound(SoundEffects.ENTITY_ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); - } - diff --git a/Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch deleted file mode 100644 index 3331bb8319a4..000000000000 --- a/Spigot-Server-Patches/0348-Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 May 2019 21:10:59 -0700 -Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer - isMainThread - -md_5 changed it so he could shut down the server asynchronously -from watchdog, although we have patches that prevent that type -of behavior for this exact reason. - -md_5 also placed code in PlayerConnectionUtils that would have -solved https://bugs.mojang.com/browse/MC-142590, making the change -to MinecraftServer#isMainThread irrelevant. -By reverting his change to MinecraftServer#isMainThread packet -handling that should have been handled synchronously will be handled -synchronously when the server gets shut down. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7ef01f2f80eea31fa76d22c3a0d5036883dee516..e885e5c4c772a87c0359ed2c56aa71a856c3be59 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2192,7 +2192,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 28 Sep 2018 21:49:53 -0400 -Subject: [PATCH] Fix issues with entity loss due to unloaded chunks - -Vanilla has risk of losing entities by causing them to be -removed from all chunks if they try to move into an unloaded chunk. - -This pretty much means high chance this entity will be lost in this -scenario. - -There is another case that adding an entity to the world can fail if -the chunk isn't loaded. - -Lots of the server is designed around addEntity never expecting to fail -for these reasons, nor is it really logical. - -This change ensures the chunks are always loaded when entities are -added to the world, or a valid entity moves between chunks. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d7c6f49ba1c84c45b387e155d9ae7452e5171df6..4e26db120e544d8867d895395241e425f23f575b 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -854,11 +854,18 @@ public class WorldServer extends World implements GeneratorAccessSeed { - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { -+ // Paper start - remove entity if its in a chunk more correctly. -+ Chunk currentChunk = entity.getCurrentChunk(); -+ if (currentChunk != null) { -+ currentChunk.removeEntity(entity); -+ } -+ // Paper end -+ - if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) { - this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY); - } - -- if (!entity.ck() && !this.isChunkLoaded(i, k)) { -+ if (!entity.valid && !entity.ck() && !this.isChunkLoaded(i, k)) { // Paper - always load chunks to register valid entities location - if (entity.inChunk) { - WorldServer.LOGGER.warn("Entity {} left loaded chunk area", entity); - } -@@ -1073,7 +1080,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return false; - } - // CraftBukkit end -- IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, entity.attachedToPlayer); -+ IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds - - if (!(ichunkaccess instanceof Chunk)) { - return false; diff --git a/Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch b/Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch deleted file mode 100644 index 950ff7c1258e..000000000000 --- a/Spigot-Server-Patches/0350-Duplicate-UUID-Resolve-Option.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 14:27:34 -0400 -Subject: [PATCH] Duplicate UUID Resolve Option - -Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 -which was added all the way back in March of 2016, it was unknown (potentially not at the time) -that an entity might actually change the seed of the random object. - -At some point, EntitySquid did start setting the seed. Due to this shared random, this caused -every entity to use a Random object with a predictable seed. - -This has caused entities to potentially generate with the same UUID.... - -Over the years, servers have had entities disappear, but no sign of trouble -because CraftBukkit removed the log lines indicating that something was wrong. - -We have fixed the root issue causing duplicate UUID's, however we now have chunk -files full of entities that have the same UUID as another entity! - -When these chunks load, the 2nd entity will not be added to the world correctly. - -If that chunk loads in a different order in the future, then it will reverse and the -missing one is now the one added to the world and not the other. This results in very -inconsistent entity behavior. - -This change allows you to recover any duplicate entity by generating a new UUID for it. -This also lets you delete them instead if you don't want to risk having new entities added to -the world that you previously did not see. - -But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. - -It is recommended you regenerate the entities, as these were legit entities, and deserve your love. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fbf3ccfb347a5ba6e895339e9576629d940d1aa4..38d25a12c6a52d8a83214e2a0f43a218cf15ceac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -401,4 +401,43 @@ public class PaperWorldConfig { - private void preventMovingIntoUnloadedChunks() { - preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); - } -+ -+ public enum DuplicateUUIDMode { -+ SAFE_REGEN, DELETE, NOTHING, WARN -+ } -+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ public int duplicateUUIDDeleteRange = 32; -+ private void repairDuplicateUUID() { -+ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); -+ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); -+ switch (desiredMode.toLowerCase()) { -+ case "regen": -+ case "regenerate": -+ case "saferegen": -+ case "saferegenerate": -+ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); -+ break; -+ case "remove": -+ case "delete": -+ duplicateUUIDMode = DuplicateUUIDMode.DELETE; -+ log("Duplicate UUID Resolve: Delete Entity"); -+ break; -+ case "silent": -+ case "nothing": -+ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; -+ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); -+ break; -+ case "log": -+ case "warn": -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ default: -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 66c808244bba70f827d8f15a96814251d352a046..b736917891afb17e412f94c5d8713aa653b8dc46 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import co.aikar.timings.Timing; // Paper -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; - import com.google.common.collect.ComparisonChain; // Paper -@@ -23,14 +24,17 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.io.File; - import java.io.IOException; - import java.io.Writer; -+import java.util.HashMap; // Paper - import java.util.Collection; - import java.util.Iterator; - import java.util.List; -+import java.util.Map; // Paper - import java.util.Objects; - import java.util.Optional; - import java.util.Queue; - import java.util.Set; - import java.util.concurrent.CancellationException; -+import java.util.UUID; // Paper - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.CompletionException; - import java.util.concurrent.Executor; -@@ -73,6 +77,7 @@ import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GameRules; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -699,18 +704,18 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunk.needsDecoration) { - net.minecraft.server.dedicated.DedicatedServer server = this.world.getServer().getServer(); - if (!server.getSpawnNPCs() && entity instanceof net.minecraft.world.entity.npc.NPC) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - - if (!server.getSpawnAnimals() && (entity instanceof net.minecraft.world.entity.animal.EntityAnimal || entity instanceof net.minecraft.world.entity.animal.EntityWaterAnimal)) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - } -- -- if (!(entity instanceof EntityHuman) && (needsRemoval || !this.world.addEntityChunk(entity))) { -- // CraftBukkit end -+ // CraftBukkit end -+ checkDupeUUID(entity); // Paper -+ if (!(entity instanceof EntityHuman) && (entity.dead || !this.world.addEntityChunk(entity))) { // Paper - if (list == null) { - list = Lists.newArrayList(new Entity[]{entity}); - } else { -@@ -737,6 +742,44 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -+ // Paper start -+ private void checkDupeUUID(Entity entity) { -+ PaperWorldConfig.DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; -+ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN -+ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE -+ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { -+ return; -+ } -+ Entity other = world.getEntity(entity.getUniqueID()); -+ -+ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.dead -+ && Objects.equals(other.getSaveID(), entity.getSaveID()) -+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < world.paperConfig.duplicateUUIDDeleteRange -+ ) { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ return; -+ } -+ if (other != null && !other.dead) { -+ switch (mode) { -+ case SAFE_REGEN: { -+ entity.setUUID(UUID.randomUUID()); -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ case DELETE: { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ break; -+ } -+ default: -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ } -+ } -+ // Paper end -+ - public CompletableFuture> a(PlayerChunk playerchunk) { - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - CompletableFuture, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, 1, (i) -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 4e26db120e544d8867d895395241e425f23f575b..fbff779fa581a661cc03850bffa0da346ce15625 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -4,6 +4,8 @@ import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; - import co.aikar.timings.TimingHistory; // Paper - import co.aikar.timings.Timings; // Paper -+ -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -1108,7 +1110,22 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -+ // Paper start -+ if (entity1.dead) { -+ unregisterEntity(entity1); // remove the existing entity -+ return false; -+ } -+ // Paper end - WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper -+ // Paper start -+ if (DEBUG_ENTITIES && entity.world.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { -+ if (entity1.addedToWorldStack != null) { -+ entity1.addedToWorldStack.printStackTrace(); -+ } -+ -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cbdd75feb7250e771111184b1fac7c4a6bf6e575..5acf61ece9ca38a262387fd0395bd464312501fd 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2799,6 +2799,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }); - } - -+ public final void setUUID(UUID uuid) { a_(uuid); } // Paper - OBFHELPER - public void a_(UUID uuid) { - this.uniqueID = uuid; - this.ae = this.uniqueID.toString(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 79ff96f18c53f3d1ce4a00be2e2d8fe68f77bf54..3f926ed8e2b2c9dbf1e2493870af7eff3b6db019 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -542,6 +542,7 @@ public class Chunk implements IChunkAccess { - if (i != this.loc.x || j != this.loc.z) { - Chunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.loc.x, this.loc.z, entity); - entity.dead = true; -+ return; // Paper - } - - int k = MathHelper.floor(entity.locY() / 16.0D); diff --git a/Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch b/Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch deleted file mode 100644 index 111ce24a8142..000000000000 --- a/Spigot-Server-Patches/0351-improve-CraftWorld-isChunkLoaded.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 21 May 2019 02:34:04 +0100 -Subject: [PATCH] improve CraftWorld#isChunkLoaded - -getChunkAt will request the chunk using vanillas chunk loading system, -which while we're not going to load the chunk, does involve the server -waiting for the execution queue to get to our request; We can just query -the chunk status and get a response now, vs having to wait - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 9e44b60843a6463951382cb66c93f1fab24e5e5d..5a5f920954effbe549cacdaa39474989dc98ad75 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -414,13 +414,13 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkLoaded(int x, int z) { -- return world.getChunkProvider().isChunkLoaded(x, z); -+ return world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; // Paper - } - - @Override - public boolean isChunkGenerated(int x, int z) { - try { -- return isChunkLoaded(x, z) || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; -+ return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) - } catch (IOException ex) { - throw new RuntimeException(ex); - } diff --git a/Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch deleted file mode 100644 index 7d87597b6bdb..000000000000 --- a/Spigot-Server-Patches/0352-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 13 Sep 2014 23:14:43 -0400 -Subject: [PATCH] Configurable Keep Spawn Loaded range per world - -This lets you disable it for some worlds and lower it for others. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 38d25a12c6a52d8a83214e2a0f43a218cf15ceac..ffe9b1a63d78925e1d77b9e730aef42fed6d58fa 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -440,4 +440,10 @@ public class PaperWorldConfig { - break; - } - } -+ -+ public short keepLoadedRange; -+ private void keepLoadedRange() { -+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); -+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e885e5c4c772a87c0359ed2c56aa71a856c3be59..334fe66cf49404c7514b317629b676e52f1841cb 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -718,35 +718,36 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> 4).forEach(pair -> { -+ getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ }); -+ } -+ public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -+ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets -+ // with level 31 for the non-border spawn chunks -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ int tickRadius = radiusInBlocks - 16; -+ -+ // remove ticking chunks -+ for (int x = -tickRadius; x <= tickRadius; x += 16) { -+ for (int z = -tickRadius; z <= tickRadius; z += 16) { -+ // radius of 2 will have the current chunk be level 31 -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE); -+ } -+ } -+ -+ // remove border chunks -+ -+ // remove border along x axis (including corner chunks) -+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { -+ // top -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ // bottom -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ } -+ -+ // remove border along z axis (excluding corner chunks) -+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { -+ // right -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ // left -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ } -+ } -+ // Paper end -+ - public void a(BlockPosition blockposition, float f) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); -+ // Paper - configurable spawn radius -+ BlockPosition prevSpawn = this.getSpawn(); -+ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -- this.getChunkProvider().removeTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); -- this.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); -+ if (this.keepSpawnInMemory) { -+ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add -+ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -+ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, blockposition); -+ } - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -index de011b5e3a5e751160b4d3b65b50f28e6c6a5f52..4d9c167a41366779dbfb5ded6ea0115ffbf06ed7 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -@@ -11,4 +11,6 @@ public interface WorldLoadListener { - void a(ChunkCoordIntPair chunkcoordintpair, @Nullable ChunkStatus chunkstatus); - - void b(); -+ -+ void setChunkRadius(int radius); // Paper - allow changing chunk radius - } -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -index 872d00de41533ab7f4b43874de6c1747022e2ac5..ca81664d884e80e5cb1eb376a2c2ef1e017f16c0 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -@@ -12,16 +12,24 @@ import org.apache.logging.log4j.Logger; - public class WorldLoadListenerLogger implements WorldLoadListener { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final int b; -+ private int b; // Paper - remove final - private int c; - private long d; - private long e = Long.MAX_VALUE; - - public WorldLoadListenerLogger(int i) { -- int j = i * 2 + 1; -+ // Paper start - Allow changing radius later for configurable spawn patch -+ this.setChunkRadius(i); // Move to method -+ } -+ -+ @Override -+ public void setChunkRadius(int radius) { -+ // Paper - copied from above -+ int j = radius * 2 + 1; - - this.b = j * j; - } -+ // Paper end - - @Override - public void a(ChunkCoordIntPair chunkcoordintpair) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5a5f920954effbe549cacdaa39474989dc98ad75..ec9f9fdf1be4f1e68eea5554a6721efd11a53958 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1972,15 +1972,21 @@ public class CraftWorld implements World { - - @Override - public void setKeepSpawnInMemory(boolean keepLoaded) { -+ // Paper start - Configurable spawn radius -+ if (keepLoaded == world.keepSpawnInMemory) { -+ // do nothing, nothing has changed -+ return; -+ } - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPosition chunkcoordinates = this.world.getSpawn(); -+ BlockPosition prevSpawn = this.world.getSpawn(); - if (keepLoaded) { -- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } else { -- // TODO: doesn't work well if spawn changed.... -- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ // TODO: doesn't work well if spawn changed.... // paper - resolved -+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch deleted file mode 100644 index be4c0838f185..000000000000 --- a/Spigot-Server-Patches/0353-MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 27 May 2019 17:35:39 -0500 -Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative - size - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -index 47099ecd70e5077cad8372446d54e28398785bec..679dfe75ea68e38679cd7d6348d0e24ca61911e4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -@@ -196,6 +196,12 @@ public class EntityAreaEffectCloud extends Entity { - super.tick(); - boolean flag = this.k(); - float f = this.getRadius(); -+ // Paper start - fix MC-114618 -+ if (f < 0.0F) { -+ this.die(); -+ return; -+ } -+ // Paper end - - if (this.world.isClientSide) { - ParticleParam particleparam = this.getParticle(); diff --git a/Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch b/Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch deleted file mode 100644 index 148847522f64..000000000000 --- a/Spigot-Server-Patches/0354-ChunkMapDistance-CME.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 29 May 2019 04:01:22 +0100 -Subject: [PATCH] ChunkMapDistance CME - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 6ef404ee29ddc79aeca534a58ec182e0e8b1b6c8..961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -39,7 +39,16 @@ public abstract class ChunkMapDistance { - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); - private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); -- private final Set pendingChunkUpdates = Sets.newHashSet(); -+ // Paper start use a queue, but still keep unique requirement -+ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -+ @Override -+ public boolean add(PlayerChunk o) { -+ if (o.isUpdateQueued) return true; -+ o.isUpdateQueued = true; -+ return super.add(o); -+ } -+ }; -+ // Paper end - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -@@ -100,26 +109,14 @@ public abstract class ChunkMapDistance { - ; - } - -+ // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -- // CraftBukkit start -- // Iterate pending chunk updates with protection against concurrent modification exceptions -- java.util.Iterator iter = this.pendingChunkUpdates.iterator(); -- int expectedSize = this.pendingChunkUpdates.size(); -- do { -- PlayerChunk playerchunk = iter.next(); -- iter.remove(); -- expectedSize--; -- -- playerchunk.a(playerchunkmap); -- -- // Reset iterator if set was modified using add() -- if (this.pendingChunkUpdates.size() != expectedSize) { -- expectedSize = this.pendingChunkUpdates.size(); -- iter = this.pendingChunkUpdates.iterator(); -- } -- } while (iter.hasNext()); -- // CraftBukkit end -- -+ while(!this.pendingChunkUpdates.isEmpty()) { -+ PlayerChunk remove = this.pendingChunkUpdates.remove(); -+ remove.isUpdateQueued = false; -+ remove.a(playerchunkmap); -+ } -+ // Paper end - return true; - } else { - if (!this.l.isEmpty()) { -@@ -373,7 +370,7 @@ public abstract class ChunkMapDistance { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); -+ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 7dea5e783ce2a1f8ddd2b3ab7a19e03a56c36ba1..2c3d9a5d118cc4f3b5e78daf943911bb7386488a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -45,6 +45,7 @@ public class PlayerChunk { - private static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK); - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); -+ boolean isUpdateQueued = false; // Paper - private final AtomicReferenceArray>> statusFutures; - private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage - private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage diff --git a/Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch b/Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch deleted file mode 100644 index 722e63e63a8d..000000000000 --- a/Spigot-Server-Patches/0355-Implement-CraftBlockSoundGroup.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:48:51 -0700 -Subject: [PATCH] Implement CraftBlockSoundGroup - - -diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..34b3b858f616c4a1f877e6e58d315de2d8ff0720 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -@@ -0,0 +1,38 @@ -+package com.destroystokyo.paper.block; -+ -+import net.minecraft.world.level.block.SoundEffectType; -+import org.bukkit.Sound; -+import org.bukkit.craftbukkit.CraftSound; -+ -+public class CraftBlockSoundGroup implements BlockSoundGroup { -+ private final SoundEffectType soundEffectType; -+ -+ public CraftBlockSoundGroup(SoundEffectType soundEffectType) { -+ this.soundEffectType = soundEffectType; -+ } -+ -+ @Override -+ public Sound getBreakSound() { -+ return CraftSound.getBukkit(soundEffectType.getBreakSound()); -+ } -+ -+ @Override -+ public Sound getStepSound() { -+ return CraftSound.getBukkit(soundEffectType.getStepSound()); -+ } -+ -+ @Override -+ public Sound getPlaceSound() { -+ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); -+ } -+ -+ @Override -+ public Sound getHitSound() { -+ return CraftSound.getBukkit(soundEffectType.getHitSound()); -+ } -+ -+ @Override -+ public Sound getFallSound() { -+ return CraftSound.getBukkit(soundEffectType.getFallSound()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -index 0987b25ac586d5d7b7954256c740fdf736498dae..b2a52c6bad5a83f34188b8f3db18c61ff9f52869 100644 ---- a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -+++ b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -@@ -54,10 +54,10 @@ public class SoundEffectType { - public static final SoundEffectType U = new SoundEffectType(1.0F, 1.0F, SoundEffects.BLOCK_GILDED_BLACKSTONE_BREAK, SoundEffects.BLOCK_GILDED_BLACKSTONE_STEP, SoundEffects.BLOCK_GILDED_BLACKSTONE_PLACE, SoundEffects.BLOCK_GILDED_BLACKSTONE_HIT, SoundEffects.BLOCK_GILDED_BLACKSTONE_FALL); - public final float volume; - public final float pitch; -- public final SoundEffect breakSound; -+ public final SoundEffect breakSound; public final SoundEffect getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound - private final SoundEffect stepSound; - private final SoundEffect placeSound; -- public final SoundEffect hitSound; -+ public final SoundEffect hitSound; public final SoundEffect getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound - private final SoundEffect fallSound; - - public SoundEffectType(float f, float f1, SoundEffect soundeffect, SoundEffect soundeffect1, SoundEffect soundeffect2, SoundEffect soundeffect3, SoundEffect soundeffect4) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 8a6d8f21937ce7e2ac4623a3083421ed5ef9aa63..724b230259b1b44bc9fdde6c4fcbcdde5f690e05 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -750,4 +750,11 @@ public class CraftBlock implements Block { - AxisAlignedBB aabb = shape.getBoundingBox(); - return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); - } -+ -+ // Paper start -+ @Override -+ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { -+ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0356-Chunk-debug-command.patch b/Spigot-Server-Patches/0356-Chunk-debug-command.patch deleted file mode 100644 index bcb44d30737f..000000000000 --- a/Spigot-Server-Patches/0356-Chunk-debug-command.patch +++ /dev/null @@ -1,486 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Jun 2019 13:00:55 -0700 -Subject: [PATCH] Chunk debug command - -Prints all chunk information to a text file into the debug -folder in the root server folder. The format is in JSON, and -the data format is described in MCUtil#dumpChunks(File) - -The command will output server version and all online players to the -file as well. We do not log anything but the location, world and -username of the player. - -Also logs the value of these config values (note not all are paper's): -- keep spawn loaded value -- spawn radius -- view distance - -Each chunk has the following logged: -- Coordinate -- Ticket level & its corresponding state -- Whether it is queued for unload -- Chunk status (may be unloaded) -- All tickets on the chunk - -Example log: -https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt - -For references on certain keywords (ticket, status, etc), please see: - -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index b67bd98cca4a06bc0ebaed577195dffc3b3251ec..a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -9,10 +9,12 @@ import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.server.MCUtil; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -41,7 +43,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -69,6 +71,21 @@ public class PaperCommand extends Command { - if (args.length == 3) - return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); - break; -+ case "debug": -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, "help", "chunks"); -+ } -+ break; -+ case "chunkinfo": -+ List worldNames = new ArrayList<>(); -+ worldNames.add("*"); -+ for (org.bukkit.World world : Bukkit.getWorlds()) { -+ worldNames.add(world.getName()); -+ } -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, worldNames); -+ } -+ break; - } - return Collections.emptyList(); - } -@@ -135,6 +152,12 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "debug": -+ doDebug(sender, args); -+ break; -+ case "chunkinfo": -+ doChunkInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -152,6 +175,114 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doChunkInfo(CommandSender sender, String[] args) { -+ List worlds; -+ if (args.length < 2 || args[1].equals("*")) { -+ worlds = Bukkit.getWorlds(); -+ } else { -+ worlds = new ArrayList<>(args.length - 1); -+ for (int i = 1; i < args.length; ++i) { -+ org.bukkit.World world = Bukkit.getWorld(args[i]); -+ if (world == null) { -+ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); -+ return; -+ } -+ worlds.add(world); -+ } -+ } -+ -+ int accumulatedTotal = 0; -+ int accumulatedInactive = 0; -+ int accumulatedBorder = 0; -+ int accumulatedTicking = 0; -+ int accumulatedEntityTicking = 0; -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ WorldServer world = ((CraftWorld)bukkitWorld).getHandle(); -+ -+ int total = 0; -+ int inactive = 0; -+ int border = 0; -+ int ticking = 0; -+ int entityTicking = 0; -+ -+ for (PlayerChunk chunk : world.getChunkProvider().playerChunkMap.updatingChunks.values()) { -+ if (chunk.getFullChunkIfCached() == null) { -+ continue; -+ } -+ -+ ++total; -+ -+ PlayerChunk.State state = PlayerChunk.getChunkState(chunk.getTicketLevel()); -+ -+ switch (state) { -+ case INACCESSIBLE: -+ ++inactive; -+ continue; -+ case BORDER: -+ ++border; -+ continue; -+ case TICKING: -+ ++ticking; -+ continue; -+ case ENTITY_TICKING: -+ ++entityTicking; -+ continue; -+ } -+ } -+ -+ accumulatedTotal += total; -+ accumulatedInactive += inactive; -+ accumulatedBorder += border; -+ accumulatedTicking += ticking; -+ accumulatedEntityTicking += entityTicking; -+ -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); -+ } -+ if (worlds.size() > 1) { -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); -+ } -+ } -+ -+ private void doDebug(CommandSender sender, String[] args) { -+ if (args.length < 2) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ -+ String debugType = args[1].toLowerCase(Locale.ENGLISH); -+ switch (debugType) { -+ case "chunks": -+ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); -+ break; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); -+ try { -+ MCUtil.dumpChunks(file); -+ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); -+ } catch (Throwable thr) { -+ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); -+ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); -+ } -+ -+ break; -+ case "help": -+ // fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ } -+ - /* - * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 - */ -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 35d1444c5b75d9a3a6cface5dd70aea0a08ac89d..fbd33aef21b4539d249c367609a36491530fb7ca 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.level.ChunkMapDistance; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; - import com.mojang.authlib.GameProfile; -+import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import java.io.*; -+import java.util.ArrayList; - import java.util.List; - import java.util.Queue; -+import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.ExecutionException; - import java.util.concurrent.LinkedBlockingQueue; -@@ -531,4 +548,170 @@ public final class MCUtil { - - return null; - } -+ -+ public static ChunkStatus getChunkStatus(PlayerChunk chunk) { -+ List statuses = ChunkProviderServer.getPossibleChunkStatuses(); -+ for (int i = statuses.size() - 1; i >= 0; --i) { -+ ChunkStatus curr = statuses.get(i); -+ CompletableFuture> future = chunk.getStatusFutureUnchecked(curr); -+ if (future != PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE) { -+ return curr; -+ } -+ } -+ return null; // unloaded -+ } -+ -+ public static void dumpChunks(File file) throws IOException { -+ file.getParentFile().mkdirs(); -+ file.createNewFile(); -+ /* -+ * Json format: -+ * -+ * Main data format: -+ * -server-version: -+ * -data-version: -+ * -worlds: -+ * -name: -+ * -view-distance: -+ * -keep-spawn-loaded: -+ * -keep-spawn-loaded-range: -+ * -visible-chunk-count: -+ * -loaded-chunk-count: -+ * -verified-fully-loaded-chunks: -+ * -players: -+ * -chunk-data: -+ * -+ * Player format: -+ * -name: -+ * -x: -+ * -y: -+ * -z: -+ * -+ * Chunk Format: -+ * -x: -+ * -z: -+ * -ticket-level: -+ * -state: -+ * -queued-for-unload: -+ * -status: -+ * -tickets: -+ * -+ * -+ * Ticket format: -+ * -ticket-type: -+ * -ticket-level: -+ * -add-tick: -+ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id -+ */ -+ List worlds = org.bukkit.Bukkit.getWorlds(); -+ JsonObject data = new JsonObject(); -+ -+ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); -+ data.addProperty("data-version", 0); -+ -+ JsonArray worldsData = new JsonArray(); -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ JsonObject worldData = new JsonObject(); -+ -+ WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); -+ PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; -+ List allChunks = new ArrayList<>(visibleChunks.values()); -+ List players = world.players; -+ -+ int fullLoadedChunks = 0; -+ -+ for (PlayerChunk chunk : allChunks) { -+ if (chunk.getFullChunkIfCached() != null) { -+ ++fullLoadedChunks; -+ } -+ } -+ -+ // sorting by coordinate makes the log easier to read -+ allChunks.sort((PlayerChunk v1, PlayerChunk v2) -> { -+ if (v1.location.x != v2.location.x) { -+ return Integer.compare(v1.location.x, v2.location.x); -+ } -+ return Integer.compare(v1.location.z, v2.location.z); -+ }); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); -+ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); -+ worldData.addProperty("visible-chunk-count", visibleChunks.size()); -+ worldData.addProperty("loaded-chunk-count", chunkMap.loadedChunks.size()); -+ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); -+ -+ JsonArray playersData = new JsonArray(); -+ -+ for (EntityPlayer player : players) { -+ JsonObject playerData = new JsonObject(); -+ -+ playerData.addProperty("name", player.getName()); -+ playerData.addProperty("x", player.locX()); -+ playerData.addProperty("y", player.locY()); -+ playerData.addProperty("z", player.locZ()); -+ -+ playersData.add(playerData); -+ -+ } -+ -+ worldData.add("players", playersData); -+ -+ JsonArray chunksData = new JsonArray(); -+ -+ for (PlayerChunk playerChunk : allChunks) { -+ JsonObject chunkData = new JsonObject(); -+ -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.location.pair()); -+ ChunkStatus status = getChunkStatus(playerChunk); -+ -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); -+ chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); -+ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -+ -+ JsonArray ticketsData = new JsonArray(); -+ -+ if (tickets != null) { -+ for (Ticket ticket : tickets) { -+ JsonObject ticketData = new JsonObject(); -+ -+ ticketData.addProperty("ticket-type", ticket.getTicketType().toString()); -+ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); -+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); -+ ticketData.addProperty("add-tick", ticket.getCreationTick()); -+ -+ ticketsData.add(ticketData); -+ } -+ } -+ -+ chunkData.add("tickets", ticketsData); -+ chunksData.add(chunkData); -+ } -+ -+ -+ worldData.add("chunk-data", chunksData); -+ worldsData.add(worldData); -+ } -+ -+ data.add("worlds", worldsData); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { -+ out.print(fileData); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index b9bde85a90b429659e1a4ab111253cddd797368e..94af98e250fe7ef37c16d432c05c6f2b68625fe1 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - - public class ChunkProviderServer extends IChunkProvider { - -- private static final List b = ChunkStatus.a(); -+ private static final List b = ChunkStatus.a(); public static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER - private final ChunkMapDistance chunkMapDistance; - public final ChunkGenerator chunkGenerator; - private final WorldServer world; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 2c3d9a5d118cc4f3b5e78daf943911bb7386488a..9891cf98f8c740f84f9135ee8176e67abb648b3a 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -54,7 +54,7 @@ public class PlayerChunk { - public int oldTicketLevel; - private int ticketLevel; - private int n; -- private final ChunkCoordIntPair location; -+ final ChunkCoordIntPair location; // Paper - private -> package - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index b736917891afb17e412f94c5d8713aa653b8dc46..e10c661755796e9c4e40f62a649b45dd1a71b46c 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -106,7 +106,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunks; - private final Long2ObjectLinkedOpenHashMap pendingUnload; -- private final LongSet loadedChunks; -+ public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 51ef4adf66c1e21093e63ab46fa47e66c2425fdb..e06fe77f6ea05a93e95fce223bcfd0d16394f96f 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -6,8 +6,8 @@ public final class Ticket implements Comparable> { - - private final TicketType a; - private final int b; -- public final T identifier; -- private long d; -+ public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER -+ private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -51,6 +51,7 @@ public final class Ticket implements Comparable> { - return this.a; - } - -+ public final int getTicketLevel() { return this.b(); } // Paper - OBFHELPER - public int b() { - return this.b; - } diff --git a/Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch b/Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch deleted file mode 100644 index 44ad23e85f32..000000000000 --- a/Spigot-Server-Patches/0357-Catch-exceptions-from-dispenser-entity-spawns.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 10 Jun 2019 09:36:40 +0100 -Subject: [PATCH] Catch exceptions from dispenser entity spawns - - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index a7d690cb2289a79ee2b8fc665caef58a10ddab3e..50911632341d1b861c00f01077cae43884147fe0 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.ISourceBlock; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -237,7 +238,14 @@ public interface IDispenseBehavior { - } - } - -+ try { // Paper - entitytypes.spawnCreature(isourceblock.getWorld(), itemstack, (EntityHuman) null, isourceblock.getBlockPosition().shift(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false); -+ // Paper start -+ } catch (Exception ex){ -+ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), isourceblock.getBlockPosition(), ex); -+ } -+ // Paper end -+ - // itemstack.subtract(1); // Handled during event processing - // CraftBukkit end - return itemstack; diff --git a/Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch b/Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index a8057528d3e4..000000000000 --- a/Spigot-Server-Patches/0358-Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 94af98e250fe7ef37c16d432c05c6f2b68625fe1..f2d48659fdb9f030dbeec12ed820062d4d066e48 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -52,7 +52,7 @@ public class ChunkProviderServer extends IChunkProvider { - private final WorldServer world; - public final Thread serverThread; // Paper - private -> public - private final LightEngineThreaded lightEngine; -- private final ChunkProviderServer.a serverThreadQueue; -+ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public - public final PlayerChunkMap playerChunkMap; - private final WorldPersistentData worldPersistentData; - private long lastTickTime; -@@ -317,6 +317,21 @@ public class ChunkProviderServer extends IChunkProvider { - - return ret; - } -+ -+ @Nullable -+ public IChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } - // Paper end - - @Nullable -@@ -768,7 +783,7 @@ public class ChunkProviderServer extends IChunkProvider { - return this.p; - } - -- final class a extends IAsyncTaskHandler { -+ public final class a extends IAsyncTaskHandler { // Paper - package -> public - - private a(World world) { - super("Chunk source main thread executor for " + world.getDimensionKey().a()); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 9891cf98f8c740f84f9135ee8176e67abb648b3a..6bced8533df49d7bfdb32dfa0caad9d788ffc2c8 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -142,6 +142,19 @@ public class PlayerChunk { - Either either = (Either) statusFuture.getNow(null); - return either == null ? null : (Chunk) either.left().orElse(null); - } -+ -+ public IChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e10c661755796e9c4e40f62a649b45dd1a71b46c..ed454f8dff7b0d94d4bde914a6f26bb019e82296 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -993,12 +993,61 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -+ // Paper start - Cache chunk status on disk -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound); -+ -+ return nbttagcompound; -+ // Paper end -+ } -+ -+ // Paper start - chunk status cache "api" -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunkData(chunkPos); - -- return nbttagcompound == null ? null : this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - } - -+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } -+ -+ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ)); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); -+ } -+ // Paper end -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 5e4c162654349f884becc10e8fbae4ded6889deb..711308cf84a816f09d116a7414f9cbee803c8713 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -193,6 +193,7 @@ public class ChunkStatus { - return this.s; - } - -+ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -213,6 +214,17 @@ public class ChunkStatus { - return this.y; - } - -+ // Paper start -+ public static ChunkStatus getStatus(String name) { -+ try { -+ // We need this otherwise we return EMPTY for invalid names -+ MinecraftKey key = new MinecraftKey(name); -+ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null); -+ } catch (Exception ex) { -+ return null; // invalid name -+ } -+ } -+ // Paper end - public static ChunkStatus a(String s) { - return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s)); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 69bc9dc18bab157851d8080a672504598e8572a8..98bc26c7ae01884eb53766e72fc7cbabbf065e6e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -462,6 +462,17 @@ public class ChunkRegionLoader { - } - // Paper end - -+ // Paper start -+ public static ChunkStatus getStatus(NBTTagCompound compound) { -+ if (compound == null) { -+ return null; -+ } -+ -+ // Note: Copied from below -+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); -+ } -+ // Paper end -+ - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { - ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 247d14a3ca56734bbbf4dc0ec247d60a1f241e7a..d785f44cd503d4d91589f3fc4bc8dc805dff3d41 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -25,7 +25,7 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; -+ private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - protected final DataFixer b; - @Nullable - private PersistentStructureLegacy c; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 00cef1c0bc19976a000389e57a1af5d93690c0e7..d50b9c9d030016f951e2ed7fb519250b7408c833 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -27,6 +27,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -44,6 +45,30 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ // Paper start - Cache chunk status -+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[getChunkLocation(x, z)] = status; -+ } -+ -+ public ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = getChunkLocation(x, z); -+ return this.statuses[location]; -+ } -+ // Paper end -+ - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); - } -@@ -380,11 +405,13 @@ public class RegionFile implements AutoCloseable { - return this.getOffset(chunkcoordintpair) != 0; - } - -+ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below - private static int g(ChunkCoordIntPair chunkcoordintpair) { - return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; - } - - public void close() throws IOException { -+ this.closed = true; // Paper - try { - this.d(); - } finally { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index ab9f4d40fd1126a3d7ba5b16fdc6ab09de4a7fdb..55e7e983d2c760a8052d7b3ddbdc8447f619a60f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -28,7 +28,14 @@ public final class RegionFileCache implements AutoCloseable { - this.c = flag; - } - -- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit -+ -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ -+ // Paper end -+ public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - -@@ -175,6 +182,7 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setStatus(chunkcoordintpair.x, chunkcoordintpair.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk - regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ec9f9fdf1be4f1e68eea5554a6721efd11a53958..d46c513512c25e55ccdb0be16524f19444c358c5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -19,6 +19,7 @@ import java.util.Objects; - import java.util.Random; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletableFuture; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.core.BlockPosition; -@@ -419,8 +420,22 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkProvider().serverThreadQueue).join(); -+ } -+ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.world.level.chunk.Chunk; -+ } - try { -- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) -+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL; -+ // Paper end - } catch (IOException ex) { - throw new RuntimeException(ex); - } -@@ -531,20 +546,48 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); - -- // If generate = false, but the chunk already exists, we will get this back. -- if (chunk instanceof ProtoChunkExtension) { -- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -- } -+ if (!generate) { -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (immediate != null) { -+ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; // not full status -+ } -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } - -- if (chunk instanceof net.minecraft.world.level.chunk.Chunk) { -- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -- return true; -+ net.minecraft.world.level.chunk.storage.RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -+ return true; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch b/Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch deleted file mode 100644 index 8c64eb071a0b..000000000000 --- a/Spigot-Server-Patches/0359-Show-blockstate-location-if-we-failed-to-read-it.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 10:28:25 -0700 -Subject: [PATCH] Show blockstate location if we failed to read it - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 2f0b48869077c27d0cacea81a99c9e34ff59c684..a4bd0d352c2babdbb31cdf49d63e2db3af4de146 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -19,6 +19,8 @@ public class CraftBlockEntityState extends CraftBlockState - public CraftBlockEntityState(Block block, Class tileEntityClass) { - super(block); - -+ try {// Paper - show location on failure -+ - this.tileEntityClass = tileEntityClass; - - // get tile entity from block: -@@ -38,6 +40,14 @@ public class CraftBlockEntityState extends CraftBlockState - this.load(this.snapshot); - } - // Paper end -+ // Paper start - show location on failure -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); -+ } -+ // Paper end - } - - public final boolean snapshotDisabled; // Paper diff --git a/Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch deleted file mode 100644 index 1dcdb2ef2364..000000000000 --- a/Spigot-Server-Patches/0360-Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 20:29:02 -0400 -Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock - -Mojang has flaws in their logic about chunks being concurrently -wrote to. So we constantly see crashes around multiple threads writing. - -Additionally, java has optimized synchronization so well that its -in many times faster than trying to manage read wrote locks for low -contention situations. - -And this is extremely a low contention situation. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 8928157b01bb4f0dfe043732777b33708c23cda7..cc0c5995dc3840ce66ea849849f7c37555d3b5e6 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -32,7 +32,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - -- public void a() { -+ public void a() { /* // Paper start - disable this - use proper synchronization - if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { - String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { - return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); -@@ -44,11 +44,11 @@ public class DataPaletteBlock implements DataPaletteExpandable { - throw new ReportedException(crashreport); - } else { - this.j.lock(); -- } -+ } */ // Paper end - } - - public void b() { -- this.j.unlock(); -+ //this.j.unlock(); // Paper - disable this - } - - public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -@@ -84,7 +84,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - @Override -- public int onResize(int i, T t0) { -+ public synchronized int onResize(int i, T t0) { // Paper - synchronize - this.a(); - DataBits databits = this.a; - DataPalette datapalette = this.h; -@@ -107,18 +107,18 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T setBlock(int i, int j, int k, T t0) { -- this.a(); -- T t1 = this.a(b(i, j, k), t0); -+ //this.a(); // Paper - remove to reduce ops - synchronize handled below -+ return this.a(b(i, j, k), t0); // Paper - -- this.b(); -- return t1; -+ //this.b(); // Paper -+ //return t1; // PAper - } - - public T b(int i, int j, int k, T t0) { - return this.a(b(i, j, k), t0); - } - -- protected T a(int i, T t0) { -+ protected synchronized T a(int i, T t0) { // Paper - synchronize - writes - int j = this.h.a(t0); - int k = this.a.a(i, j); - T t1 = this.h.a(k); -@@ -143,7 +143,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -@@ -151,7 +151,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagList nbttaglist, long[] along) { -+ public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); - int i = Math.max(4, MathHelper.e(nbttaglist.size())); - -@@ -184,7 +184,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagCompound nbttagcompound, String s, String s1) { -+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize - this.a(); - DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); - T t0 = this.g; diff --git a/Spigot-Server-Patches/0361-incremental-chunk-saving.patch b/Spigot-Server-Patches/0361-incremental-chunk-saving.patch deleted file mode 100644 index bca0562141d2..000000000000 --- a/Spigot-Server-Patches/0361-incremental-chunk-saving.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 9 Jun 2019 03:53:22 +0100 -Subject: [PATCH] incremental chunk saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ffe9b1a63d78925e1d77b9e730aef42fed6d58fa..1278d09f70c1e97607ef20d87a178dc252c7f723 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -446,4 +446,19 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); - log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); - } -+ -+ public int autoSavePeriod = -1; -+ private void autoSavePeriod() { -+ autoSavePeriod = getInt("auto-save-interval", -1); -+ if (autoSavePeriod > 0) { -+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); -+ } else if (autoSavePeriod < 0) { -+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; -+ } -+ } -+ -+ public int maxAutoSaveChunksPerTick = 24; -+ private void maxAutoSaveChunksPerTick() { -+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 334fe66cf49404c7514b317629b676e52f1841cb..571f3860bc31c077c239a32776f6aaf6ff30ce71 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -263,6 +263,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -+ public boolean serverAutoSave = false; // Paper - public CommandDispatcher vanillaCommandDispatcher; - private boolean forceTicks; - // CraftBukkit end -@@ -1258,14 +1259,24 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- MinecraftServer.LOGGER.debug("Autosave started"); -+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down -+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper -+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper - this.methodProfiler.enter("save"); -+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper - this.playerList.savePlayers(); -- this.saveChunks(true, false, false); -+ }// Paper -+ // Paper start -+ for (WorldServer world : getWorlds()) { -+ if (world.paperConfig.autoSavePeriod > 0) { -+ world.saveIncrementally(serverAutoSave); -+ } -+ } -+ // Paper end -+ - this.methodProfiler.exit(); -- MinecraftServer.LOGGER.debug("Autosave finished"); -- } -+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper -+ //} // Paper - - this.methodProfiler.enter("snooper"); - if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index f2d48659fdb9f030dbeec12ed820062d4d066e48..5122afbd51c87c27efa82d7d9393f252efa848d4 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -557,6 +557,15 @@ public class ChunkProviderServer extends IChunkProvider { - } // Paper - Timings - } - -+ // Paper start - duplicate save, but call incremental -+ public void saveIncrementally() { -+ this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings -+ this.playerChunkMap.saveIncrementally(); -+ } // Paper - Timings -+ } -+ // Paper end -+ - @Override - public void close() throws IOException { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 6bced8533df49d7bfdb32dfa0caad9d788ffc2c8..75d4a8fc394449ccc006fe67a8842edcd9f36854 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -67,6 +67,9 @@ public class PlayerChunk { - - private final PlayerChunkMap chunkMap; // Paper - -+ long lastAutoSaveTime; // Paper - incremental autosave -+ long inactiveTimeStart; // Paper - incremental autosave -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -422,7 +425,19 @@ public class PlayerChunk { - boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER); - boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER); - -+ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper - this.hasBeenLoaded |= flag3; -+ // Paper start - incremental autosave -+ if (this.hasBeenLoaded & !prevHasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } -+ // Paper end - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -@@ -542,8 +557,32 @@ public class PlayerChunk { - } - - public void m() { -+ boolean prev = this.hasBeenLoaded; // Paper -+ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ // Paper start - incremental autosave -+ if (prev != this.hasBeenLoaded) { -+ if (this.hasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } else { -+ this.inactiveTimeStart = this.chunkMap.world.getTime(); -+ this.chunkMap.autoSaveQueue.remove(this); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - incremental autosave -+ public boolean setHasBeenLoaded() { - this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ return this.hasBeenLoaded; - } -+ // Paper end - - public void a(ProtoChunkExtension protochunkextension) { - for (int i = 0; i < this.statusFutures.length(); ++i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index ed454f8dff7b0d94d4bde914a6f26bb019e82296..ca05fe4ed0773b94035c63f8f8db6c034f0b92e2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -93,6 +93,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStruct - import net.minecraft.world.level.storage.Convertable; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -380,6 +381,64 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - incremental autosave -+ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { -+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); -+ if (timeCompare != 0) { -+ return timeCompare; -+ } -+ -+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location)); -+ }); -+ -+ protected void saveIncrementally() { -+ int savedThisTick = 0; -+ // optimized since we search far less chunks to hit ones that need to be saved -+ List reschedule = new java.util.ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick); -+ long currentTick = this.world.getTime(); -+ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod; -+ -+ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { -+ PlayerChunk playerchunk = iterator.next(); -+ if (playerchunk.lastAutoSaveTime > maxSaveTime) { -+ break; -+ } -+ -+ iterator.remove(); -+ -+ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null); -+ if (ichunkaccess instanceof Chunk) { -+ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime; -+ -+ if (shouldSave && this.saveChunk(ichunkaccess)) { -+ ++savedThisTick; -+ -+ if (!playerchunk.setHasBeenLoaded()) { -+ // do not fall through to reschedule logic -+ playerchunk.inactiveTimeStart = currentTick; -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ continue; -+ } -+ } -+ } -+ -+ reschedule.add(playerchunk); -+ -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ } -+ -+ for (int i = 0, len = reschedule.size(); i < len; ++i) { -+ PlayerChunk playerchunk = reschedule.get(i); -+ playerchunk.lastAutoSaveTime = this.world.getTime(); -+ this.autoSaveQueue.add(playerchunk); -+ } -+ } -+ // Paper end -+ - protected void save(boolean flag) { - if (flag) { - List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -@@ -490,6 +549,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.world.unloadChunk(chunk); - } -+ this.autoSaveQueue.remove(playerchunk); // Paper - - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); -@@ -682,6 +742,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunk.a(new ProtoChunkExtension(chunk)); - } - -+ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks -+ - chunk.a(() -> { - return PlayerChunk.getChunkState(playerchunk.getTicketLevel()); - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d308197995a92f5be8f5b928fa9ae83dd659545c..12e34e1514f060ffef96cdd3ac57d0495dd37321 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -888,6 +888,38 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition); - } - -+ // Paper start - derived from below -+ public void saveIncrementally(boolean doFull) { -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ -+ if (doFull) { -+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); -+ } -+ -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { -+ if (doFull) { -+ this.saveData(); -+ } -+ -+ timings.worldSaveChunks.startTiming(); // Paper -+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally(); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ -+ -+ // Copied from save() -+ // CraftBukkit start - moved from MinecraftServer.saveChunks -+ if (doFull) { // Paper -+ WorldServer worldserver1 = this; -+ -+ worldDataServer.a(worldserver1.getWorldBorder().t()); -+ worldDataServer.setCustomBossEvents(this.server.getBossBattleCustomData().save()); -+ convertable.a(this.server.customRegistry, this.worldDataServer, this.server.getPlayerList().save()); -+ } -+ // CraftBukkit end -+ } -+ } -+ // Paper end -+ - public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) { - ChunkProviderServer chunkproviderserver = this.getChunkProvider(); - -@@ -918,6 +950,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - } - -+ private void saveData() { this.aj(); } // Paper - OBFHELPER - private void aj() { - if (this.dragonBattle != null) { - this.worldDataServer.a(this.dragonBattle.a()); // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 3f926ed8e2b2c9dbf1e2493870af7eff3b6db019..2690c44eaae193a259fe195c95e59d07d5e1cc5a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -81,7 +81,7 @@ public class Chunk implements IChunkAccess { - private TickList o; - private TickList p; - private boolean q; -- private long lastSaved; -+ public long lastSaved; // Paper - private volatile boolean s; - private long inhabitedTime; - @Nullable diff --git a/Spigot-Server-Patches/0362-Anti-Xray.patch b/Spigot-Server-Patches/0362-Anti-Xray.patch deleted file mode 100644 index ff640d6ee927..000000000000 --- a/Spigot-Server-Patches/0362-Anti-Xray.patch +++ /dev/null @@ -1,1567 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: stonar96 -Date: Mon, 20 Aug 2018 03:03:58 +0200 -Subject: [PATCH] Anti-Xray - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1278d09f70c1e97607ef20d87a178dc252c7f723..c45493e88bf7e8811be2759ff9ac19e3fe9d938a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,7 +1,9 @@ - package com.destroystokyo.paper; - -+import java.util.Arrays; - import java.util.List; - -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; -@@ -461,4 +463,38 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } -+ -+ public boolean antiXray; -+ public EngineMode engineMode; -+ public int maxChunkSectionIndex; -+ public int updateRadius; -+ public boolean lavaObscures; -+ public boolean usePermission; -+ public List hiddenBlocks; -+ public List replacementBlocks; -+ private void antiXray() { -+ antiXray = getBoolean("anti-xray.enabled", false); -+ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); -+ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; -+ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); -+ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; -+ updateRadius = getInt("anti-xray.update-radius", 2); -+ lavaObscures = getBoolean("anti-xray.lava-obscures", false); -+ usePermission = getBoolean("anti-xray.use-permission", false); -+ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); -+ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); -+ if (PaperConfig.version < 19) { -+ hiddenBlocks.remove("lit_redstone_ore"); -+ int index = replacementBlocks.indexOf("planks"); -+ if (index != -1) { -+ replacementBlocks.set(index, "oak_planks"); -+ } -+ set("anti-xray.hidden-blocks", hiddenBlocks); -+ set("anti-xray.replacement-blocks", replacementBlocks); -+ } -+ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); -+ if (antiXray && usePermission) { -+ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -new file mode 100644 -index 0000000000000000000000000000000000000000..83a023ae018cbb79b5f151b1c7a5c8ba0c3bf1bf ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -@@ -0,0 +1,45 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.IChunkAccess; -+ -+public class ChunkPacketBlockController { -+ -+ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); -+ -+ protected ChunkPacketBlockController() { -+ -+ } -+ -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ return null; -+ } -+ -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return false; -+ } -+ -+ public ChunkPacketInfo getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ return null; -+ } -+ -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ packetPlayOutMapChunk.setReady(true); -+ } -+ -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ -+ } -+ -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd3b5b62d470ab6753b44f9b13dcf5522e4cbd15 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -@@ -0,0 +1,650 @@ -+package com.destroystokyo.paper.antixray; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.Executor; -+import java.util.concurrent.ThreadLocalRandom; -+import java.util.function.IntSupplier; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.core.IRegistry; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkEmpty; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPalette; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import org.bukkit.Bukkit; -+import org.bukkit.World.Environment; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+ -+public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { -+ -+ private final Executor executor; -+ private final EngineMode engineMode; -+ private final int maxChunkSectionIndex; -+ private final int updateRadius; -+ private final boolean usePermission; -+ private final IBlockData[] predefinedBlockData; -+ private final IBlockData[] predefinedBlockDataFull; -+ private final IBlockData[] predefinedBlockDataStone; -+ private final IBlockData[] predefinedBlockDataNetherrack; -+ private final IBlockData[] predefinedBlockDataEndStone; -+ private final int[] predefinedBlockDataBitsGlobal; -+ private final int[] predefinedBlockDataBitsStoneGlobal; -+ private final int[] predefinedBlockDataBitsNetherrackGlobal; -+ private final int[] predefinedBlockDataBitsEndStoneGlobal; -+ private final boolean[] solidGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final boolean[] obfuscateGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final ChunkSection[] emptyNearbyChunkSections = {Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION}; -+ private final int maxBlockYUpdatePosition; -+ -+ public ChunkPacketBlockControllerAntiXray(World world, Executor executor) { -+ PaperWorldConfig paperWorldConfig = world.paperConfig; -+ engineMode = paperWorldConfig.engineMode; -+ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; -+ updateRadius = paperWorldConfig.updateRadius; -+ usePermission = paperWorldConfig.usePermission; -+ -+ this.executor = executor; -+ -+ List toObfuscate; -+ -+ if (engineMode == EngineMode.HIDE) { -+ toObfuscate = paperWorldConfig.hiddenBlocks; -+ predefinedBlockData = null; -+ predefinedBlockDataFull = null; -+ predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()}; -+ predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()}; -+ predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()}; -+ predefinedBlockDataBitsGlobal = null; -+ predefinedBlockDataBitsStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.STONE.getBlockData())}; -+ predefinedBlockDataBitsNetherrackGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.getBlockData())}; -+ predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())}; -+ } else { -+ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); -+ List predefinedBlockDataList = new LinkedList(); -+ -+ for (String id : paperWorldConfig.hiddenBlocks) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ if (block != null && !block.isTileEntity()) { -+ toObfuscate.add(id); -+ predefinedBlockDataList.add(block.getBlockData()); -+ } -+ } -+ -+ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation -+ Set predefinedBlockDataSet = new LinkedHashSet(); -+ // Therefore addAll(Collection c) is used, which guarantees this order in the doc -+ predefinedBlockDataSet.addAll(predefinedBlockDataList); -+ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]); -+ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataList.toArray(new IBlockData[0]); -+ predefinedBlockDataStone = null; -+ predefinedBlockDataNetherrack = null; -+ predefinedBlockDataEndStone = null; -+ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; -+ -+ for (int i = 0; i < predefinedBlockDataFull.length; i++) { -+ predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ -+ predefinedBlockDataBitsStoneGlobal = null; -+ predefinedBlockDataBitsNetherrackGlobal = null; -+ predefinedBlockDataBitsEndStoneGlobal = null; -+ } -+ -+ for (String id : toObfuscate) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void -+ if (block != null && !block.getBlockData().isAir()) { -+ // Replace all block states of a specified block -+ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors -+ // The OBFHELPER should be getBlockDataList() -+ for (IBlockData blockData : block.getStates().a()) { -+ obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)] = true; -+ } -+ } -+ } -+ -+ ChunkEmpty emptyChunk = new ChunkEmpty(world, new ChunkCoordIntPair(0, 0)); -+ BlockPosition zeroPos = new BlockPosition(0, 0, 0); -+ -+ for (int i = 0; i < solidGlobal.length; i++) { -+ IBlockData blockData = ChunkSection.GLOBAL_PALETTE.getObject(i); -+ -+ if (blockData != null) { -+ solidGlobal[i] = blockData.isOccluding(emptyChunk, zeroPos) -+ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.getBlockData(); -+ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used -+ // shulker box checks TE. -+ } -+ } -+ -+ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; -+ } -+ -+ private int getPredefinedBlockDataFullLength() { -+ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; -+ } -+ -+ @Override -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation -+ if (chunkSection.getYPosition() >> 4 <= maxChunkSectionIndex) { -+ switch (engineMode) { -+ case HIDE: -+ switch (world.getWorld().getEnvironment()) { -+ case NETHER: -+ return predefinedBlockDataNetherrack; -+ case THE_END: -+ return predefinedBlockDataEndStone; -+ default: -+ return predefinedBlockDataStone; -+ } -+ default: -+ return predefinedBlockData; -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); -+ } -+ -+ @Override -+ public ChunkPacketInfoAntiXray getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later -+ // Note: As of 1.14 this has to be moved later due to the chunk system. -+ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); -+ return chunkPacketInfoAntiXray; -+ } -+ -+ @Override -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ if (chunkPacketInfo == null) { -+ packetPlayOutMapChunk.setReady(true); -+ return; -+ } -+ -+ if (!Bukkit.isPrimaryThread()) { -+ // plugins? -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); -+ }); -+ return; -+ } -+ -+ Chunk chunk = chunkPacketInfo.getChunk(); -+ int x = chunk.getPos().x; -+ int z = chunk.getPos().z; -+ WorldServer world = (WorldServer)chunk.world; -+ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( -+ (Chunk) world.getChunkIfLoadedImmediately(x - 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x + 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z - 1), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z + 1)); -+ -+ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); -+ } -+ -+ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) -+ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here -+ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); -+ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate -+ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ -+ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { -+ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); -+ boolean[] solid = this.solid.get(); -+ boolean[] obfuscate = this.obfuscate.get(); -+ boolean[][] current = this.current.get(); -+ boolean[][] next = this.next.get(); -+ boolean[][] nextNext = this.nextNext.get(); -+ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it -+ DataBitsReader dataBitsReader = new DataBitsReader(); -+ DataBitsWriter dataBitsWriter = new DataBitsWriter(); -+ ChunkSection[] nearbyChunkSections = new ChunkSection[4]; -+ boolean[] solidTemp = null; -+ boolean[] obfuscateTemp = null; -+ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); -+ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); -+ int numberOfBlocks = predefinedBlockDataBits.length; -+ // Keep the lambda expressions as simple as possible. They are used very frequently. -+ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { -+ private int state; -+ -+ { -+ while ((state = ThreadLocalRandom.current().nextInt()) == 0); -+ } -+ -+ @Override -+ public int getAsInt() { -+ // https://en.wikipedia.org/wiki/Xorshift -+ state ^= state << 13; -+ state ^= state >>> 17; -+ state ^= state << 5; -+ // https://www.pcg-random.org/posts/bounded-rands.html -+ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); -+ } -+ }; -+ -+ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { -+ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { -+ int[] predefinedBlockDataBitsTemp; -+ -+ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) { -+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; -+ } else { -+ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead -+ IBlockData[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); -+ predefinedBlockDataBitsTemp = predefinedBlockDataBits; -+ -+ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { -+ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ } -+ -+ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ -+ // Check if the chunk section below was not obfuscated -+ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { -+ // If so, initialize some stuff -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); -+ // Read the blocks of the upper layer of the chunk section below if it exists -+ ChunkSection belowChunkSection = null; -+ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == Chunk.EMPTY_CHUNK_SECTION; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ current[z][x] = true; -+ next[z][x] = skipFirstLayer || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(belowChunkSection.getType(x, 15, z))]; -+ } -+ } -+ -+ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section -+ dataBitsWriter.setBitsPerObject(0); -+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; -+ -+ // Obfuscate all layers of the current chunk section except the upper one -+ for (int y = 0; y < 15; y++) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ // Check if the chunk section above doesn't need obfuscation -+ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { -+ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists -+ ChunkSection aboveChunkSection; -+ -+ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != Chunk.EMPTY_CHUNK_SECTION) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ if (!solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(aboveChunkSection.getType(x, 0, z))]) { -+ current[z][x] = true; -+ } -+ } -+ } -+ -+ // There is nothing to read anymore -+ dataBitsReader.setBitsPerObject(0); -+ solid[0] = true; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ } else { -+ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.finish(); -+ } -+ } -+ -+ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); -+ } -+ -+ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, IntSupplier random) { -+ // First block of first line -+ int dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][1] = true; -+ next[1][0] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(0, y, 15))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 0))] || current[0][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][0] = true; -+ } -+ -+ // First line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][x - 1] = true; -+ next[0][x + 1] = true; -+ next[1][x] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(x, y, 15))] || current[0][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][x] = true; -+ } -+ } -+ -+ // Last block of first line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][14] = true; -+ next[1][15] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(15, y, 15))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 0))] || current[0][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][15] = true; -+ } -+ -+ // All inner lines -+ for (int z = 1; z < 15; z++) { -+ // First block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][1] = true; -+ next[z - 1][0] = true; -+ next[z + 1][0] = true; -+ } else { -+ if (nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, z))] || current[z][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][0] = true; -+ } -+ -+ // All inner blocks -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][x - 1] = true; -+ next[z][x + 1] = true; -+ next[z - 1][x] = true; -+ next[z + 1][x] = true; -+ } else { -+ if (current[z][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][x] = true; -+ } -+ } -+ -+ // Last block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][14] = true; -+ next[z - 1][15] = true; -+ next[z + 1][15] = true; -+ } else { -+ if (nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, z))] || current[z][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][15] = true; -+ } -+ } -+ -+ // First block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][1] = true; -+ next[14][0] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(0, y, 0))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 15))] || current[15][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][0] = true; -+ } -+ -+ // Last line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][x - 1] = true; -+ next[15][x + 1] = true; -+ next[14][x] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(x, y, 0))] || current[15][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][x] = true; -+ } -+ } -+ -+ // Last block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][14] = true; -+ next[14][15] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(15, y, 0))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 15))] || current[15][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][15] = true; -+ } -+ } -+ -+ private boolean[] readDataPalette(DataPalette dataPalette, boolean[] temp, boolean[] global) { -+ if (dataPalette == ChunkSection.GLOBAL_PALETTE) { -+ return global; -+ } -+ -+ IBlockData blockData; -+ -+ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { -+ temp[i] = global[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]; -+ } -+ -+ return temp; -+ } -+ -+ @Override -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ if (oldBlockData != null && solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(world, blockPosition); -+ } -+ } -+ -+ @Override -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ if (blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(playerInteractManager.world, blockPosition); -+ } -+ } -+ -+ private void updateNearbyBlocks(World world, BlockPosition blockPosition) { -+ if (updateRadius >= 2) { -+ BlockPosition temp = blockPosition.west(); -+ updateBlock(world, temp); -+ updateBlock(world, temp.west()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.east()); -+ updateBlock(world, temp.east()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.down()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.up()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.north()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp = blockPosition.south()); -+ updateBlock(world, temp.south()); -+ } else if (updateRadius == 1) { -+ updateBlock(world, blockPosition.west()); -+ updateBlock(world, blockPosition.east()); -+ updateBlock(world, blockPosition.down()); -+ updateBlock(world, blockPosition.up()); -+ updateBlock(world, blockPosition.north()); -+ updateBlock(world, blockPosition.south()); -+ } else { -+ // Do nothing if updateRadius <= 0 (test mode) -+ } -+ } -+ -+ private void updateBlock(World world, BlockPosition blockPosition) { -+ IBlockData blockData = world.getTypeIfLoaded(blockPosition); -+ -+ if (blockData != null && obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]) { -+ // world.notify(blockPosition, blockData, blockData, 3); -+ ((WorldServer)world).getChunkProvider().flagDirty(blockPosition); // We only need to re-send to client -+ } -+ } -+ -+ public enum EngineMode { -+ -+ HIDE(1, "hide ores"), -+ OBFUSCATE(2, "obfuscate"); -+ -+ private final int id; -+ private final String description; -+ -+ EngineMode(int id, String description) { -+ this.id = id; -+ this.description = description; -+ } -+ -+ public static EngineMode getById(int id) { -+ for (EngineMode engineMode : values()) { -+ if (engineMode.id == id) { -+ return engineMode; -+ } -+ } -+ -+ return null; -+ } -+ -+ public int getId() { -+ return id; -+ } -+ -+ public String getDescription() { -+ return description; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..22c9adefc3e51e9e4b8d611a40d1497d2a16a8d2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -@@ -0,0 +1,81 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.DataPalette; -+ -+public class ChunkPacketInfo { -+ -+ private final PacketPlayOutMapChunk packetPlayOutMapChunk; -+ private final Chunk chunk; -+ private final int chunkSectionSelector; -+ private byte[] data; -+ private final int[] bitsPerObject = new int[16]; -+ private final Object[] dataPalettes = new Object[16]; -+ private final int[] dataBitsIndexes = new int[16]; -+ private final Object[][] predefinedObjects = new Object[16][]; -+ -+ public ChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ this.packetPlayOutMapChunk = packetPlayOutMapChunk; -+ this.chunk = chunk; -+ this.chunkSectionSelector = chunkSectionSelector; -+ } -+ -+ public PacketPlayOutMapChunk getPacketPlayOutMapChunk() { -+ return packetPlayOutMapChunk; -+ } -+ -+ public Chunk getChunk() { -+ return chunk; -+ } -+ -+ public int getChunkSectionSelector() { -+ return chunkSectionSelector; -+ } -+ -+ public byte[] getData() { -+ return data; -+ } -+ -+ public void setData(byte[] data) { -+ this.data = data; -+ } -+ -+ public int getBitsPerObject(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex]; -+ } -+ -+ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { -+ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public DataPalette getDataPalette(int chunkSectionIndex) { -+ return (DataPalette) dataPalettes[chunkSectionIndex]; -+ } -+ -+ public void setDataPalette(int chunkSectionIndex, DataPalette dataPalette) { -+ dataPalettes[chunkSectionIndex] = dataPalette; -+ } -+ -+ public int getDataBitsIndex(int chunkSectionIndex) { -+ return dataBitsIndexes[chunkSectionIndex]; -+ } -+ -+ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { -+ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public T[] getPredefinedObjects(int chunkSectionIndex) { -+ return (T[]) predefinedObjects[chunkSectionIndex]; -+ } -+ -+ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { -+ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; -+ } -+ -+ public boolean isWritten(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex] != 0; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4b64964e52b11bea4d2c0d0f64f55ad08d2189be ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -@@ -0,0 +1,30 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+ -+public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { -+ -+ private Chunk[] nearbyChunks; -+ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; -+ -+ public ChunkPacketInfoAntiXray(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector, -+ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { -+ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); -+ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; -+ } -+ -+ public Chunk[] getNearbyChunks() { -+ return nearbyChunks; -+ } -+ -+ public void setNearbyChunks(Chunk... nearbyChunks) { -+ this.nearbyChunks = nearbyChunks; -+ } -+ -+ @Override -+ public void run() { -+ chunkPacketBlockControllerAntiXray.obfuscate(this); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..298ea423084dbcc1b61f991bcd82b8ae51bf0977 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -@@ -0,0 +1,51 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsReader { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private int mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ } -+ -+ public int read() { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ int value = (int) (current >>> bitInLongIndex) & mask; -+ bitInLongIndex += bitsPerObject; -+ return value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..333763936897befda5bb6c077944d2667f922799 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -@@ -0,0 +1,79 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsWriter { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private long mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ private boolean dirty; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ -+ dirty = false; -+ } -+ -+ public void finish() { -+ if (dirty && dataBits.length > longInDataBitsIndex + 7) { -+ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); -+ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); -+ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); -+ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); -+ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); -+ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); -+ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); -+ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); -+ } -+ } -+ -+ public void write(int value) { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ finish(); -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; -+ dirty = true; -+ bitInLongIndex += bitsPerObject; -+ } -+ -+ public void skip() { -+ bitInLongIndex += bitsPerObject; -+ -+ if (bitInLongIndex > 64) { -+ finish(); -+ bitInLongIndex = bitsPerObject; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index a7d10d124021f3427f23fcd533f885367b64515c..3047cf8c4ec1b664d6b790f18d2b1657e4b00435 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol.game; - -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import com.google.common.collect.Lists; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; -@@ -16,6 +17,7 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -33,7 +35,13 @@ public class PacketPlayOutMapChunk implements Packet { - private List g; - private boolean h; - -- public PacketPlayOutMapChunk() {} -+ // Paper start - Async-Anti-Xray - Set the ready flag to true -+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager -+ public PacketPlayOutMapChunk() { -+ this.ready = true; -+ } -+ // Paper end -+ - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); - private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -@@ -43,7 +51,11 @@ public class PacketPlayOutMapChunk implements Packet { - return extraPackets; - } - // Paper end -- public PacketPlayOutMapChunk(Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { -+ ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - - this.a = chunkcoordintpair.x; -@@ -66,7 +78,12 @@ public class PacketPlayOutMapChunk implements Packet { - } - - this.f = new byte[this.a(chunk, i)]; -- this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setData(this.getData()); -+ } -+ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); -+ // Paper end - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); - int totalTileEntities = 0; // Paper -@@ -93,8 +110,19 @@ public class PacketPlayOutMapChunk implements Packet { - this.g.add(nbttagcompound); - } - } -+ chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks -+ } - -+ // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag -+ @Override -+ public boolean isReady() { -+ return this.ready; -+ } -+ -+ public void setReady(boolean ready) { -+ this.ready = ready; - } -+ // Paper end - - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { -@@ -160,8 +188,12 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -- public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER -- public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { return this.writeChunk(packetdataserializer, chunk, i, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector, ChunkPacketInfo chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER -+ public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); - int k = 0; -@@ -171,7 +203,7 @@ public class PacketPlayOutMapChunk implements Packet { - - if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { - j |= 1 << k; -- chunksection.b(packetdataserializer); -+ chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info - } - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index ca05fe4ed0773b94035c63f8f8db6c034f0b92e2..5a11765c8a7d754ec86d829fa5e85d2809dd937e 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -656,7 +656,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - this.g(chunkcoordintpair); -- return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a)); -+ return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter - }, this.executor); - } - -@@ -1404,9 +1404,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -- apacket[0] = new PacketPlayOutMapChunk(chunk, 65535); -+ apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index d86b1e528b53db809ac993aa2f1d2799d4f1a574..fbd8a6985a261396789c87e4b687140bd49cea0d 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -309,6 +309,8 @@ public class PlayerInteractManager { - } - - } -+ -+ this.world.chunkPacketBlockController.onPlayerLeftClickBlock(this, blockposition, enumdirection); // Paper - Anti-Xray - } - - public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index d7fe6f00b352dad9e9f579f9af86cb8b90ef83ae..e2c0d30c5b25f9c44025f0619ba254c89402d9f9 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -210,7 +210,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env); -+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor - this.pvpMode = minecraftserver.getPVP(); - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 12ac3608736b45447afe6b0d35ead1441390be5e..15da3511a9e57c320f4cf409852bee07109095bc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -2,6 +2,8 @@ package net.minecraft.world.level; - - import co.aikar.timings.Timing; - import co.aikar.timings.Timings; -+import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray - import com.destroystokyo.paper.event.server.ServerExceptionEvent; - import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.MoreObjects; -@@ -144,6 +146,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot -@@ -165,9 +168,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -- protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { -+ protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -433,6 +437,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit end - - IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag -+ this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray - - if (iblockdata1 == null) { - // CraftBukkit start - remove blockstate if failed (or the same) -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 2690c44eaae193a259fe195c95e59d07d5e1cc5a..3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -465,7 +465,7 @@ public class Chunk implements IChunkAccess { - return null; - } - -- chunksection = new ChunkSection(j >> 4 << 4); -+ chunksection = new ChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - this.sections[j >> 4] = chunksection; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 89efd0b68b04457e1cd617dcc8bb1a6ea1c4717c..9fb8d20e9e1a8cc716c32a100b1d70e90f385eca 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -8,6 +8,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.data.worldgen.biome.BiomeRegistry; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -28,7 +29,7 @@ public class ChunkEmpty extends Chunk { - }); - - public ChunkEmpty(World world, ChunkCoordIntPair chunkcoordintpair) { -- super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); -+ super(world, chunkcoordintpair, new BiomeStorage(MinecraftServer.getServer().getCustomRegistry().b(IRegistry.ay), ChunkEmpty.b)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry - } - - // Paper start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index eea4a30428293eaf7afbe303a37adec60b44c2b4..0b4e346daaea91565fde2f789fafa8b431a7b042 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -1,9 +1,11 @@ - package net.minecraft.world.level.chunk; - - import java.util.function.Predicate; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -@@ -18,16 +20,22 @@ public class ChunkSection { - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -- public ChunkSection(int i) { -- this(i, (short) 0, (short) 0, (short) 0); -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); -+ // Paper end - } - -- public ChunkSection(int i, short short0, short short1, short short2) { -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i, short short0, short short1, short short2) { this(i, short0, short1, short2, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, short short0, short short1, short short2, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ // Paper end - this.yPos = i; - this.nonEmptyBlockCount = short0; - this.tickingBlockCount = short1; - this.e = short2; -- this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); -+ this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data - } - - public final IBlockData getType(int i, int j, int k) { // Paper -@@ -139,10 +147,14 @@ public class ChunkSection { - return this.blockIds; - } - -- public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public final void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public final void b(PacketDataSerializer packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public final void writeChunkSection(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER -+ public void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - packetdataserializer.writeShort(this.nonEmptyBlockCount); -- this.blockIds.b(packetdataserializer); -+ this.blockIds.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.yPos >> 4); // Paper - Anti-Xray - Add chunk packet info - } - - public int j() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index cc0c5995dc3840ce66ea849849f7c37555d3b5e6..68d53a51acc9790b9cda20ec4d2ec6edd1baac1a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.chunk; - - import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import java.util.Arrays; - import java.util.Objects; - import java.util.concurrent.locks.ReentrantLock; -@@ -27,6 +28,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -+ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects - protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER - private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER -@@ -51,14 +53,47 @@ public class DataPaletteBlock implements DataPaletteExpandable { - //this.j.unlock(); // Paper - disable this - } - -- public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -+ // Paper start - Anti-Xray - Add predefined objects -+ @Deprecated public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { this(datapalette, registryblockid, function, function1, t0, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { -+ // Paper end - this.b = datapalette; - this.d = registryblockid; - this.e = function; - this.f = function1; - this.g = t0; -- this.b(4); -+ // Paper start - Anti-Xray - Add predefined objects -+ this.predefinedObjects = predefinedObjects; -+ -+ if (initialize) { -+ if (predefinedObjects == null) { -+ // Default -+ this.initialize(4); -+ } else { -+ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead -+ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning -+ // The length of the array is used because air is also added to the data palette from the beginning -+ // Start with at least 4 -+ int maxIndex = predefinedObjects.length >> 4; -+ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); -+ -+ // Initialize with at least 15 free indixes -+ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); -+ this.addPredefinedObjects(); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - Anti-Xray - Add predefined objects -+ private void addPredefinedObjects() { -+ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { -+ for (int i = 0; i < this.predefinedObjects.length; i++) { -+ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); -+ } -+ } - } -+ // Paper end - - private static int b(int i, int j, int k) { - return j << 8 | k << 4 | i; -@@ -93,6 +128,7 @@ public class DataPaletteBlock implements DataPaletteExpandable { - - int j; - -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - for (j = 0; j < databits.b(); ++j) { - T t1 = datapalette.a(databits.a(j)); - -@@ -142,24 +178,38 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -- public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public void b(PacketDataSerializer packetdataserializer) { this.writeDataPaletteBlock(packetdataserializer, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER -+ public synchronized void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize -+ // Paper end - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); -+ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); -+ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + PacketDataSerializer.countBytes(this.getDataBits().getDataBits().length)); -+ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); -+ } -+ // Paper end - packetdataserializer.a(this.a.a()); - this.b(); - } - - public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); -- int i = Math.max(4, MathHelper.e(nbttaglist.size())); -+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? -+ int i = Math.max(4, MathHelper.e(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects - -- if (i != this.i) { -+ if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet - this.b(i); - } - - this.h.a(nbttaglist); -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - int j = along.length * 64 / 4096; - - if (this.h == this.b) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 9eeb99a21a6ed7f71ff64cf4cfdff646d31abbcf..9b308a10554b037ede0c455fbd3e906021218ddc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,16 +64,24 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -+ private final World world; // Paper - Anti-Xray - Add world - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { -+ // Paper end - this(chunkcoordintpair, chunkconverter, (ChunkSection[]) null, new ProtoChunkTickList<>((block) -> { - return block == null || block.getBlockData().isAir(); - }, chunkcoordintpair), new ProtoChunkTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, chunkcoordintpair)); -+ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world - } - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { this(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1, World world) { -+ this.world = world; -+ // Paper end - this.f = Maps.newEnumMap(HeightMap.Type.class); - this.g = ChunkStatus.EMPTY; - this.h = Maps.newHashMap(); -@@ -228,7 +236,7 @@ public class ProtoChunk implements IChunkAccess { - - public ChunkSection a(int i) { - if (this.j[i] == Chunk.a) { -- this.j[i] = new ChunkSection(i << 4); -+ this.j[i] = new ChunkSection(i << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - } - - return this.j[i]; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index 9351e6ba541d440c485b6e4a3209170c5756e31e..7a82d43d51d80a3054e0871bf4b9aa7635920efc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -27,7 +27,7 @@ public class ProtoChunkExtension extends ProtoChunk { - private final Chunk a; - - public ProtoChunkExtension(Chunk chunk) { -- super(chunk.getPos(), ChunkConverter.a); -+ super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter - this.a = chunk; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 98bc26c7ae01884eb53766e72fc7cbabbf065e6e..c652897aae99c48c6cc020b5d64f6a8b02beecb5 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -101,7 +101,7 @@ public class ChunkRegionLoader { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.hasKeyOfType("Palette", 9) && nbttagcompound2.hasKeyOfType("BlockStates", 12)) { -- ChunkSection chunksection = new ChunkSection(b0 << 4); -+ ChunkSection chunksection = new ChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters - - chunksection.getBlocks().a(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -165,7 +165,7 @@ public class ChunkRegionLoader { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); -+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - - protochunk.a(biomestorage); - object = protochunk; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index a8e94f69faec93661dc6ae2efeec44b8bfd2e965..c36f55f178166eb099cc5c64784be5a9f4750199 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -44,7 +44,7 @@ public class CraftChunk implements Chunk { - private final WorldServer worldServer; - private final int x; - private final int z; -- private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0).getBlocks(); -+ private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0, null, null, true).getBlocks(); // Paper - Anti-Xray - Add parameters - private static final byte[] emptyLight = new byte[2048]; - - public CraftChunk(net.minecraft.world.level.chunk.Chunk chunk) { -@@ -288,7 +288,7 @@ public class CraftChunk implements Chunk { - NBTTagCompound data = new NBTTagCompound(); - cs[i].getBlocks().a(data, "Palette", "BlockStates"); - -- DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection -+ DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally - blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); - - sectionBlockIDs[i] = blockids; -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 3d15915275331cb767750c24c89b4b43d43033ef..afca0038bb74ac53f07a25729a3c1542e244c6fd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -21,9 +21,11 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; - private final ChunkSection[] sections; - private Set tiles; -+ private World world; // Paper - Anti-Xray - Add world - - public CraftChunkData(World world) { - this(world.getMaxHeight()); -+ this.world = world; // Paper - Anti-Xray - Add world - } - - /* pp for tests */ CraftChunkData(int maxHeight) { -@@ -157,7 +159,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private ChunkSection getChunkSection(int y, boolean create) { - ChunkSection section = sections[y >> 4]; - if (create && section == null) { -- sections[y >> 4] = section = new ChunkSection(y >> 4 << 4); -+ sections[y >> 4] = section = new ChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters - } - return section; - } diff --git a/Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch deleted file mode 100644 index 528f3c902287..000000000000 --- a/Spigot-Server-Patches/0363-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 01:01:32 -0400 -Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob - limit - -This resolves the super common complaint about mobs not spawning. - -This was ultimately a flaw in the vanilla count algorithim that allows -spawners and other misc mobs to count against the mob limit, which are -not bounded, and can prevent the entire world from spawning new. - -I believe Bukkits changes around persistence may of actually made it -worse than vanilla. - -This should fully solve all of the issues around it so that only natural -influences natural spawns. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c45493e88bf7e8811be2759ff9ac19e3fe9d938a..384cb363eed794551bee6b0ec11ba1be92a3d7ac 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -464,6 +464,16 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } - -+ public boolean countAllMobsForSpawning = false; -+ private void countAllMobsForSpawning() { -+ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); -+ if (countAllMobsForSpawning) { -+ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); -+ } else { -+ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); -+ } -+ } -+ - public boolean antiXray; - public EngineMode engineMode; - public int maxChunkSectionIndex; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 5307488fa48ffa91446dd4457de1ce6a8f61da61..d30a3de84dc75a57680052904337af02b6b80636 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -81,6 +81,13 @@ public final class SpawnerCreature { - EnumCreatureType enumcreaturetype = entity.getEntityType().e(); - - if (enumcreaturetype != EnumCreatureType.MISC) { -+ // Paper start - Only count natural spawns -+ if (!entity.world.paperConfig.countAllMobsForSpawning && -+ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || -+ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { -+ continue; -+ } -+ // Paper end - BlockPosition blockposition = entity.getChunkCoordinates(); - long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); - diff --git a/Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch b/Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch deleted file mode 100644 index 0f0d7c1e918d..000000000000 --- a/Spigot-Server-Patches/0364-Configurable-projectile-relative-velocity.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lucavon -Date: Tue, 23 Jul 2019 20:29:20 -0500 -Subject: [PATCH] Configurable projectile relative velocity - -This patch adds an option "disable relative projectile velocity", which, when -nabled, will cause projectiles to ignore the shooter's current velocity, -like they did in Minecraft 1.8 and prior. -If a player is falling, for example, their shooting range will be drastically -reduced, as a downwards velocity is applied to the projectile. This prevents -players from saving themselves from falling off floating islands, for example, -as a thrown ender pearl will not make it back to the island, while it would -have in 1.8. - -While this could easily be done with plugins, too, there are multiple problems: -P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity -from the projectile's velocity, the projectile's velocity would be different. -As there's no way to detect whether the projectile's velocity has already been -adjusted to ignore the player's velocity, plugins can't not do it if it's not -necessary. -P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while -using an elytra. Checking for those inconsistencies is possible, but not as -efficient as just not applying the velocity in the first place. -P3) Solutions for 1) and especially 2) might not be future-proof, while this -server-internal fix makes this change future-proof. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 384cb363eed794551bee6b0ec11ba1be92a3d7ac..1ee2cced100626e48eb36ee14f84b9257c79a2f8 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -507,4 +507,9 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); - } - } -+ -+ public boolean disableRelativeProjectileVelocity; -+ private void disableRelativeProjectileVelocity() { -+ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 29834a3613c7701d46e879d170779eb7e6f664e1..8fe98404ebb8b3b5d1fdac0896b27da10736026d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -130,7 +130,7 @@ public abstract class IProjectile extends Entity { - this.shoot((double) f5, (double) f6, (double) f7, f3, f4); - Vec3D vec3d = entity.getMot(); - -- this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); -+ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity - } - - // CraftBukkit start - call projectile hit event diff --git a/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch deleted file mode 100644 index ff018b922192..000000000000 --- a/Spigot-Server-Patches/0365-Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 28 Jul 2019 00:51:11 +0100 -Subject: [PATCH] Mark entities as being ticked when notifying navigation - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index e2c0d30c5b25f9c44025f0619ba254c89402d9f9..9012c837c2f284e9f2f11462e6dc7e2f6e190939 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1475,6 +1475,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - - if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { -+ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper - Iterator iterator = this.navigators.iterator(); - - while (iterator.hasNext()) { -@@ -1496,6 +1497,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ this.tickingEntities = wasTicking; // Paper - } - } - diff --git a/Spigot-Server-Patches/0366-offset-item-frame-ticking.patch b/Spigot-Server-Patches/0366-offset-item-frame-ticking.patch deleted file mode 100644 index b2190b5c55cc..000000000000 --- a/Spigot-Server-Patches/0366-offset-item-frame-ticking.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Tue, 30 Jul 2019 03:17:16 +0500 -Subject: [PATCH] offset item frame ticking - - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -index 477c86bec21159608707c1b3bf2ad5f2b455214f..9d491240bcb3ba6ffbee963a13d31aa7b6cd5d45 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -@@ -37,7 +37,7 @@ public abstract class EntityHanging extends Entity { - protected static final Predicate b = (entity) -> { - return entity instanceof EntityHanging; - }; -- private int e; -+ private int e; { this.e = this.getId() % this.world.spigotConfig.hangingTickFrequency; } // Paper - public BlockPosition blockPosition; - protected EnumDirection direction; - diff --git a/Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch b/Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index 77f09da2e9a2..000000000000 --- a/Spigot-Server-Patches/0367-Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CullanP -Date: Thu, 3 Mar 2016 02:13:38 -0600 -Subject: [PATCH] Avoid hopper searches if there are no items - -Hoppers searching for items and minecarts is the most expensive part of hopper ticking. -We keep track of the number of minecarts and items in a chunk. -If there are no items in the chunk, we skip searching for items. -If there are no minecarts in the chunk, we skip searching for them. - -Usually hoppers aren't near items, so we can skip most item searches. -And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. - -Combined, this adds up a lot. - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index cb5cda5e6497edeb801ef712f9bd8823cb055750..1a6f8aec32af85717f5d56e0b00a02cda88ce028 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -16,6 +16,7 @@ public final class IEntitySelector { - public static final Predicate c = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); - }; -+ public static final Predicate isInventory() { return d; } // Paper - OBFHELPER - public static final Predicate d = (entity) -> { - return entity instanceof IInventory && entity.isAlive(); - }; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 3fdce0e6fa34eb4b1eafc618068a3fb06abd5ec1..e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -32,10 +32,13 @@ import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.IInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.IEntitySelector; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.TickList; -@@ -123,6 +126,10 @@ public class Chunk implements IChunkAccess { - return removed; - } - } -+ // Track the number of minecarts and items -+ // Keep this synced with entitySlices.add() and entitySlices.remove() -+ private final int[] itemCounts = new int[16]; -+ private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { -@@ -582,6 +589,13 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ // Paper start -+ if (entity instanceof EntityItem) { -+ itemCounts[k]++; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } -@@ -615,6 +629,11 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ if (entity instanceof EntityItem) { -+ itemCounts[i]--; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[i]--; -+ } - entityCounts.decrement(entity.getMinecraftKeyString()); - this.markDirty(); // Paper - // Paper end -@@ -900,6 +919,14 @@ public class Chunk implements IChunkAccess { - for (int k = i; k <= j; ++k) { - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error - if (entity.shouldBeRemoved) continue; // Paper -@@ -920,9 +947,29 @@ public class Chunk implements IChunkAccess { - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - -+ // Paper start -+ int[] counts; -+ if (EntityItem.class.isAssignableFrom(oclass)) { -+ counts = itemCounts; -+ } else if (IInventory.class.isAssignableFrom(oclass)) { -+ counts = inventoryEntityCounts; -+ } else { -+ counts = null; -+ } -+ // Paper end - for (int k = i; k <= j; ++k) { -+ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error - if (t0.shouldBeRemoved) continue; // Paper diff --git a/Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch b/Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch deleted file mode 100644 index d013f781176d..000000000000 --- a/Spigot-Server-Patches/0368-Asynchronous-chunk-IO-and-loading.patch +++ /dev/null @@ -1,4203 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 13 Jul 2019 09:23:10 -0700 -Subject: [PATCH] Asynchronous chunk IO and loading - -This patch re-adds a file IO thread as well as shoving de-serializing -chunk NBT data onto worker threads. This patch also will shove -chunk data serialization onto the same worker threads when the chunk -is unloaded - this cannot be done for regular saves since that's unsafe. - -The file IO Thread - -Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can -be reoredered, however they are "stuck" to a world & coordinate. - -Scheduling IO tasks works as follows, given a world & coordinate - location: - -The IO thread has been designed to ensure that reads and writes appear to -occur synchronously for a given location, however the implementation also -has the unfortunate side-effect of making every write appear as if -they occur without failure. - -The IO thread has also been designed to accomodate Mojang's decision to -store chunk data and POI data separately. It can independently schedule -tasks for each. - -However threads can wait for writes to complete and check if: - - The write was overwriten by another scheduler - - The write failed (however it does not indicate whether it was overwritten by another scheduler) - -Scheduling reads: - - - If a write task is in progress, the task is not scheduled and returns the in-progress write data - This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write - - If a write task is not in progress but a read task is in progress, then the read task is simply chained - This means that again, readers cannot modify the NBTTagCompound returned - -Scheduling writes: - - - If a read task is in progress, ignore the read task and schedule the write - We cannot complete the read task since we assume it wants old data - not current - - If a write task is pending, overwrite the write data - The file IO thread does correctly handle cases where the data is overwritten when it - is writing data (before completing a task it will check if the data was overwritten and - will retry). - -When the file IO thread executes a task for a location, the it will -execute the read task first (if it exists), then it will execute the -write task. This ensures that, even when scheduling at different -priorities, that reads/writes for a location act synchronously. - -The downside of the file IO thread is that write failure can only be -indicated to the scheduling thread if: - -- No other thread decides to schedule another write for the location -concurrently -- The scheduling thread blocks on the write to complete (however the -current implementation can be modified to indicate success -asynchronously) - -The file io thread can be modified easily to provide indications -of write failure and write overwriting if needed. - -The upside of the file IO thread is that if a write failures, then -chunk data is not lost until server restart. This leaves more room -for spurious failure. - -Finally, the io thread will indicate to the console when reads -or writes fail - with relevant detail. - -Asynchronous chunk data serialization for unloading chunks - -When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). -Even if I make the IO asynchronous for this call, the data serialization -still hits pretty hard. And given that now the chunk system will -aggressively unload chunks more often (queued immediately at -ticket level 45 or higher), unloads occur more often, and -combined with our changes to the unload queue to make it -significantly more aggresive - chunk unloads can hit pretty hard. -Especially players running around with elytras and fireworks. - -For serializing chunk data off main, there are some tasks which cannot be -done asynchronously. Lighting data must be saved beforehand as well as -potentially some tick lists. These are completed before scheduling the -asynchronous save. - -However serializing chunk data off of the main thread is still risky. -Even though this patch schedules the save to occur after ALL references -of the chunk are removed from the world, plugins can still technically -access entities inside the chunks. For this, if the serialization task -fails for any reason, it will be re-scheduled to be serialized on the -main thread - with the hopes that the reason it failed was due to a plugin -and not an error with the save code itself. Like vanilla code - if the -serialization fails, the chunk data is lost. - -Asynchronous chunk io/loading - -Mojang's current implementation for loading chunk data off disk is -to return a CompletableFuture that will be completed by scheduling a -task to be executed on the world's chunk queue (which is only drained -on the main thread). This task will read the IO off disk and it will -apply data conversions & deserialization synchronously. Obviously -all 3 of these operations are expensive however all can be completed -asynchronously instead. - -The solution this patch uses is as follows: - -0. If an asynchronous chunk save is in progress (see above), wait -for that task to complete. It will use the serialized NBTTagCompound -created by the task. If the task fails to complete, then we would continue -with step 1. If it does not, we skip step 1. (Note: We actually load -POI data no matter what in this case). -1. Schedule an IO task to read chunk & poi data off disk. -2. The IO task will schedule a chunk load task. -3. The chunk load task executes on the async chunk loader threads -and will apply datafixers & de-serialize the chunk into a ProtoChunk -or ProtoChunkExtension. -4. The in progress chunk is then passed on to the world's chunk queue -to complete the ComletableFuture and execute any of the synchronous -tasks required to be executed by the chunk load task (i.e lighting -and some poi tasks). - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index fa154ed68187a2020e814db6345a8cc1119ab4ba..2da28784ee427001b1137c859f0b4c350abd3110 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -58,6 +58,17 @@ public class WorldTimingsHandler { - - public final Timing miscMobSpawning; - -+ public final Timing poiUnload; -+ public final Timing chunkUnload; -+ public final Timing poiSaveDataSerialization; -+ public final Timing chunkSave; -+ public final Timing chunkSaveOverwriteCheck; -+ public final Timing chunkSaveDataSerialization; -+ public final Timing chunkSaveIOWait; -+ public final Timing chunkUnloadPrepareSave; -+ public final Timing chunkUnloadPOISerialization; -+ public final Timing chunkUnloadDataSave; -+ - public WorldTimingsHandler(World server) { - String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; - -@@ -111,6 +122,17 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ -+ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); -+ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -+ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); -+ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); -+ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); -+ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); -+ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); -+ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); -+ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); -+ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); - } - - public static Timing getTickList(WorldServer worldserver, String timingsType) { -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index a7a02072e5c7ce62cbecbb638fcc74abf2fb57ee..f657e9b6bb3d24a6c77ef584711a003d1eea0341 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -43,7 +44,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); - - public PaperCommand(String name) { - super(name); -@@ -155,6 +156,9 @@ public class PaperCommand extends Command { - case "debug": - doDebug(sender, args); - break; -+ case "dumpwaiting": -+ ChunkTaskManager.dumpAllChunkLoadInfo(); -+ break; - case "chunkinfo": - doChunkInfo(sender, args); - break; -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 469f78775b03cf363d88e35c69c0dc185c22547c..8bf4d2b8c38c02d6a5b2fea37113689a252f1571 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -1,5 +1,6 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Strings; - import com.google.common.base.Throwables; - -@@ -352,4 +353,54 @@ public class PaperConfig { - maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } -+ -+ public static boolean asyncChunks = false; -+ private static void asyncChunks() { -+ ConfigurationSection section; -+ if (version < 15) { -+ section = config.createSection("settings.async-chunks"); -+ section.set("threads", -1); -+ } else { -+ section = config.getConfigurationSection("settings.async-chunks"); -+ if (section == null) { -+ section = config.createSection("settings.async-chunks"); -+ } -+ } -+ // Clean up old configs -+ if (section.contains("load-threads")) { -+ if (!section.contains("threads")) { -+ section.set("threads", section.get("load-threads")); -+ } -+ section.set("load-threads", null); -+ } -+ section.set("generation", null); -+ section.set("enabled", null); -+ section.set("thread-per-world-generation", null); -+ -+ int threads = getInt("settings.async-chunks.threads", -1); -+ int cpus = Runtime.getRuntime().availableProcessors(); -+ if (threads <= 0) { -+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); -+ } -+ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { -+ asyncChunks = false; -+ } else { -+ asyncChunks = true; -+ } -+ -+ // Let Shared Host set some limits -+ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); -+ if (sharedHostThreads != null) { -+ try { -+ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); -+ } catch (NumberFormatException ignored) {} -+ } -+ -+ if (!asyncChunks) { -+ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); -+ } else { -+ ChunkTaskManager.initGlobalLoadThreads(threads); -+ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..5af0ac3d9e87c06053e65433060f15779c156c2a ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.io; -+ -+import org.bukkit.Bukkit; -+ -+public final class IOUtil { -+ -+ /* Copied from concrete or concurrentutil */ -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getRegionCoordinate(final int chunkCoordinate) { -+ return chunkCoordinate >> 5; -+ } -+ -+ public static int getChunkInRegion(final int chunkCoordinate) { -+ return chunkCoordinate & 31; -+ } -+ -+ public static String genericToString(final Object object) { -+ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); -+ } -+ -+ public static T notNull(final T obj) { -+ if (obj == null) { -+ throw new NullPointerException(); -+ } -+ return obj; -+ } -+ -+ public static T notNull(final T obj, final String msgIfNull) { -+ if (obj == null) { -+ throw new NullPointerException(msgIfNull); -+ } -+ return obj; -+ } -+ -+ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { -+ if (off < 0 || len < 0 || (arrayLength - off) < len) { -+ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); -+ } -+ } -+ -+ public static int getPriorityForCurrentThread() { -+ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public static void rethrow(final Throwable throwable) throws T { -+ throw (T)throwable; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9fe91f9512ee8c2589fc8da76bda5f6d70c9fac4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -@@ -0,0 +1,606 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.RegionFile; -+import org.apache.logging.log4j.Logger; -+ -+import java.io.IOException; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Consumer; -+import java.util.function.Function; -+ -+/** -+ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. -+ * -+ *

-+ * Singleton access: {@link Holder#INSTANCE} -+ *

-+ * -+ *

-+ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): -+ *

  • -+ * Chunk saves may not occur for unloaded chunks. -+ *
  • -+ *
  • -+ * Tasks must be scheduled on the main thread. -+ *
  • -+ *

    -+ * -+ * @see Holder#INSTANCE -+ * @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int) -+ * @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean) -+ */ -+public final class PaperFileIOThread extends QueueExecutorThread { -+ -+ public static final Logger LOGGER = MinecraftServer.LOGGER; -+ public static final NBTTagCompound FAILURE_VALUE = new NBTTagCompound(); -+ -+ public static final class Holder { -+ -+ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); -+ -+ static { -+ INSTANCE.start(); -+ } -+ } -+ -+ private final AtomicLong writeCounter = new AtomicLong(); -+ -+ private PaperFileIOThread() { -+ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time -+ this.setName("Paper RegionFile IO Thread"); -+ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us -+ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { -+ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); -+ }); -+ } -+ -+ /* run() is implemented by superclass */ -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually -+ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. -+ * -+ */ -+ -+ /** -+ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to try to bump to -+ */ -+ public void bumpPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.raisePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.raisePriority(priority); -+ } -+ } -+ -+ public NBTTagCompound getPendingWrite(final WorldServer world, final int chunkX, final int chunkZ, final boolean poiData) { -+ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; -+ -+ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ -+ if (dataTask == null) { -+ return null; -+ } -+ -+ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; -+ -+ if (write == null) { -+ return null; -+ } -+ -+ return write.data; -+ } -+ -+ /** -+ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to set to -+ */ -+ public void setPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.updatePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.updatePriority(priority); -+ } -+ } -+ -+ /** -+ * Schedules the chunk data to be written asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means -+ * saves must be scheduled before a chunk is unloaded. -+ *
  • -+ *
  • -+ * Writes may be called concurrently, although only the "later" write will go through. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. -+ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. -+ * @throws IllegalStateException If the file io thread has shutdown. -+ */ -+ public void scheduleSave(final WorldServer world, final int chunkX, final int chunkZ, -+ final NBTTagCompound poiData, final NBTTagCompound chunkData, -+ final int priority) throws IllegalArgumentException { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final long writeCounter = this.writeCounter.getAndIncrement(); -+ -+ if (poiData != null) { -+ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); -+ } -+ if (chunkData != null) { -+ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); -+ } -+ } -+ -+ private void scheduleWrite(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final NBTTagCompound data, final int priority, final long writeCounter) { -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { -+ if (taskRunning == null) { -+ // no task is scheduled -+ -+ // create task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ newTask.inProgressWrite.writeCounter = writeCounter; -+ newTask.inProgressWrite.data = data; -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule -+ return newTask; -+ } -+ -+ taskRunning.raisePriority(priority); -+ -+ if (taskRunning.inProgressWrite == null) { -+ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ } -+ -+ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; -+ -+ // synchronize for readers -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (taskRunning) { -+ taskRunning.inProgressWrite.data = data; -+ taskRunning.inProgressWrite.writeCounter = writeCounter; -+ } -+ -+ if (reschedule) { -+ // We need to reschedule this task since the previous one is not currently scheduled since it failed -+ taskRunning.reschedule(priority); -+ } -+ -+ return taskRunning; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task -+ * has completed. -+ *

    -+ * Note that if the chunk fails to load the returned future is completed with {@code null}. -+ *

    -+ */ -+ public CompletableFuture loadChunkDataAsyncFuture(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ final CompletableFuture future = new CompletableFuture<>(); -+ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); -+ return future; -+ } -+ -+ /** -+ * Schedules a load to be executed asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. -+ *
  • -+ *
  • -+ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data -+ * this call did not request. -+ *
  • -+ *
  • -+ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may -+ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of -+ * data is undefined behaviour, and can cause deadlock. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @param onComplete Consumer to execute once this task has completed -+ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support -+ * cancellation. -+ */ -+ public void loadChunkDataAsync(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final Consumer onComplete, -+ final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ if (!(readPoiData | readChunkData)) { -+ throw new IllegalArgumentException("Must read chunk data or poi data"); -+ } -+ -+ final ChunkData complete = new ChunkData(); -+ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; -+ -+ if (readPoiData) { -+ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final NBTTagCompound poiData) -> { -+ complete.poiData = poiData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[0] = false; // 0 -> poi data -+ finished = !requireCompletion[1]; // 1 -> chunk data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ if (readChunkData) { -+ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final NBTTagCompound chunkData) -> { -+ complete.chunkData = chunkData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[1] = false; // 1 -> chunk data -+ finished = !requireCompletion[0]; // 0 -> poi data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ } -+ -+ // Note: the onComplete may be called asynchronously or synchronously here. -+ private void scheduleRead(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, -+ final boolean intendingToBlock) { -+ -+ Function tryLoadFunction = (final RegionFile file) -> { -+ if (file == null) { -+ return Boolean.TRUE; -+ } -+ return Boolean.valueOf(file.chunkExists(new ChunkCoordIntPair(chunkX, chunkZ))); -+ }; -+ -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { -+ if (running == null) { -+ // not scheduled -+ -+ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : -+ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); -+ -+ if (shouldSchedule == Boolean.FALSE) { -+ // not on disk -+ onComplete.accept(null); -+ return null; -+ } -+ -+ // set up task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressRead = new ChunkDataController.InProgressRead(); -+ newTask.inProgressRead.readFuture.thenAccept(onComplete); -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule task -+ return newTask; -+ } -+ -+ running.raisePriority(priority); -+ -+ if (running.inProgressWrite == null) { -+ // chain to the read future -+ running.inProgressRead.readFuture.thenAccept(onComplete); -+ return running; -+ } -+ -+ // at this stage we have to use the in progress write's data to avoid an order issue -+ // we don't synchronize since all writes to data occur in the compute() call -+ onComplete.accept(running.inProgressWrite.data); -+ return running; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * the {@link ChunkData} associated with the specified chunk when the task is complete. -+ * @return The chunk data, or {@code null} if the chunk failed to load. -+ */ -+ public ChunkData loadChunkData(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final boolean readPoiData, final boolean readChunkData) { -+ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); -+ } -+ -+ /** -+ * Schedules the given task at the specified priority to be executed on the IO thread. -+ *

    -+ * Internal api. Do not use. -+ *

    -+ */ -+ public void runTask(final int priority, final Runnable runnable) { -+ this.queueTask(new GeneralTask(priority, runnable)); -+ } -+ -+ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ private final Runnable run; -+ -+ public GeneralTask(final int priority, final Runnable run) { -+ super(priority); -+ this.run = IOUtil.notNull(run, "Task may not be null"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.run.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); -+ } -+ } -+ } -+ -+ public static final class ChunkData { -+ -+ public NBTTagCompound poiData; -+ public NBTTagCompound chunkData; -+ -+ public ChunkData() {} -+ -+ public ChunkData(final NBTTagCompound poiData, final NBTTagCompound chunkData) { -+ this.poiData = poiData; -+ this.chunkData = chunkData; -+ } -+ } -+ -+ public static abstract class ChunkDataController { -+ -+ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. -+ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ public abstract void writeData(final int x, final int z, final NBTTagCompound compound) throws IOException; -+ public abstract NBTTagCompound readData(final int x, final int z) throws IOException; -+ -+ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); -+ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); -+ -+ public static final class InProgressWrite { -+ public long writeCounter; -+ public NBTTagCompound data; -+ } -+ -+ public static final class InProgressRead { -+ public final CompletableFuture readFuture = new CompletableFuture<>(); -+ } -+ } -+ -+ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public ChunkDataController.InProgressWrite inProgressWrite; -+ public ChunkDataController.InProgressRead inProgressRead; -+ -+ private final WorldServer world; -+ private final int x; -+ private final int z; -+ private final ChunkDataController taskController; -+ -+ public ChunkDataTask(final int priority, final WorldServer world, final int x, final int z, final ChunkDataController taskController) { -+ super(priority); -+ this.world = world; -+ this.x = x; -+ this.z = z; -+ this.taskController = taskController; -+ } -+ -+ @Override -+ public String toString() { -+ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + -+ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); -+ } -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures -+ * -+ */ -+ -+ void reschedule(final int priority) { -+ // priority is checked before this stage // TODO what -+ this.queue.lazySet(null); -+ this.priority.lazySet(priority); -+ PaperFileIOThread.Holder.INSTANCE.queueTask(this); -+ } -+ -+ @Override -+ public void run() { -+ ChunkDataController.InProgressRead read = this.inProgressRead; -+ if (read != null) { -+ NBTTagCompound compound = PaperFileIOThread.FAILURE_VALUE; -+ try { -+ compound = this.taskController.readData(this.x, this.z); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); -+ // fall through to complete with null data -+ } -+ read.readFuture.complete(compound); -+ } -+ -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); -+ -+ ChunkDataController.InProgressWrite write = this.inProgressWrite; -+ -+ if (write == null) { -+ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ return valueInMap.inProgressWrite == null ? null : valueInMap; -+ }); -+ -+ if (inMap == null) { -+ return; // set the task value to null, indicating we're done -+ } -+ -+ // not null, which means there was a concurrent write -+ write = this.inProgressWrite; -+ } -+ -+ // check if another process is writing -+ /*try { TODO: Can we restore this? -+ ((WorldServer)this.world).checkSession(); -+ } catch (final Exception ex) { -+ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); -+ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling -+ // writes since they'll fail anyways. -+ return; -+ } -+*/ -+ for (;;) { -+ final long writeCounter; -+ final NBTTagCompound data; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (write) { -+ writeCounter = write.writeCounter; -+ data = write.data; -+ } -+ -+ boolean failedWrite = false; -+ -+ try { -+ this.taskController.writeData(this.x, this.z, data); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); -+ failedWrite = true; -+ } -+ -+ boolean finalFailWrite = failedWrite; -+ -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { -+ if (finalFailWrite) { -+ valueInMap.inProgressWrite.writeCounter = -1L; -+ } -+ -+ return null; -+ } -+ return valueInMap; -+ // Hack end -+ }); -+ -+ if (inMap == null) { -+ // write counter matched, so we wrote the most up-to-date pending data, we're done here -+ // or we failed to write and successfully set the write counter to -1 -+ return; // we're done here -+ } -+ -+ // fetch & write new data -+ continue; -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..97f2e433c483f1ebd7500ae142269e144ef5fda4 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -@@ -0,0 +1,277 @@ -+package com.destroystokyo.paper.io; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicReference; -+ -+public class PrioritizedTaskQueue { -+ -+ // lower numbers are a higher priority (except < 0) -+ // higher priorities are always executed before lower priorities -+ -+ /** -+ * Priority value indicating the task has completed or is being completed. -+ */ -+ public static final int COMPLETING_PRIORITY = -1; -+ -+ /** -+ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. -+ */ -+ public static final int HIGHEST_PRIORITY = 0; -+ -+ /** -+ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. -+ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. -+ */ -+ public static final int HIGHER_PRIORITY = 1; -+ -+ /** -+ * Should be used for scheduling chunk loads/generation that would increase response times to users. -+ */ -+ public static final int HIGH_PRIORITY = 2; -+ -+ /** -+ * Default priority. -+ */ -+ public static final int NORMAL_PRIORITY = 3; -+ -+ /** -+ * Use for tasks not at all critical and can potentially be delayed. -+ */ -+ public static final int LOW_PRIORITY = 4; -+ -+ /** -+ * Use for tasks that should "eventually" execute. -+ */ -+ public static final int LOWEST_PRIORITY = 5; -+ -+ private static final int TOTAL_PRIORITIES = 6; -+ -+ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; -+ -+ private final AtomicBoolean shutdown = new AtomicBoolean(); -+ -+ { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ this.queues[i] = new ConcurrentLinkedQueue<>(); -+ } -+ } -+ -+ /** -+ * Returns whether the specified priority is valid -+ */ -+ public static boolean validPriority(final int priority) { -+ return priority >= 0 && priority < TOTAL_PRIORITIES; -+ } -+ -+ /** -+ * Queues a task. -+ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to -+ * raise a task's priority. -+ * This can also be thrown if the queue has shutdown. -+ */ -+ public void add(final T task) throws IllegalStateException { -+ int priority = task.getPriority(); -+ if (priority != COMPLETING_PRIORITY) { -+ task.setQueue(this); -+ this.queues[priority].add(task); -+ } -+ if (this.shutdown.get()) { -+ // note: we're not actually sure at this point if our task will go through -+ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); -+ } -+ } -+ -+ /** -+ * Polls the highest priority task currently available. {@code null} if none. -+ */ -+ public T poll() { -+ T task; -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ while ((task = queue.poll()) != null) { -+ final int prevPriority = task.tryComplete(i); -+ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { -+ // if the prev priority was greater-than or equal to our current priority -+ return task; -+ } -+ } -+ } -+ -+ return null; -+ } -+ -+ /** -+ * Returns whether this queue may have tasks queued. -+ *

    -+ * This operation is not atomic, but is MT-Safe. -+ *

    -+ * @return {@code true} if tasks may be queued, {@code false} otherwise -+ */ -+ public boolean hasTasks() { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ if (queue.peek() != null) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ /** -+ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will -+ * result in {@link IllegalStateException} being thrown. -+ *

    -+ * This operation is atomic with respect to other shutdown calls -+ *

    -+ *

    -+ * After this call has completed, regardless of return value, this queue will be shutdown. -+ *

    -+ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already -+ */ -+ public boolean shutdown() { -+ return this.shutdown.getAndSet(false); -+ } -+ -+ public abstract static class PrioritizedTask { -+ -+ protected final AtomicReference queue = new AtomicReference<>(); -+ -+ protected final AtomicInteger priority; -+ -+ protected PrioritizedTask() { -+ this(PrioritizedTaskQueue.NORMAL_PRIORITY); -+ } -+ -+ protected PrioritizedTask(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority " + priority); -+ } -+ this.priority = new AtomicInteger(priority); -+ } -+ -+ /** -+ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned -+ * if this task is completing or has completed. -+ */ -+ public final int getPriority() { -+ return this.priority.get(); -+ } -+ -+ /** -+ * Returns whether this task is scheduled to execute, or has been already executed. -+ */ -+ public boolean isScheduled() { -+ return this.queue.get() != null; -+ } -+ -+ final int tryComplete(final int minPriority) { -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return COMPLETING_PRIORITY; -+ } -+ if (curr > minPriority) { -+ // curr is lower priority -+ return curr; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { -+ return curr; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Forces this task to be completed. -+ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. -+ */ -+ public boolean cancel() { -+ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; -+ } -+ -+ /** -+ * Attempts to raise the priority to the priority level specified. -+ * @param priority Priority specified -+ * @return {@code true} if successful, {@code false} otherwise. -+ */ -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (priority >= curr) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Attempts to set this task's priority level to the level specified. -+ * @param priority Specified priority level. -+ * @return {@code true} if successful, {@code false} if this task is completing or has completed. -+ */ -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (curr == priority) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ void setQueue(final PrioritizedTaskQueue queue) { -+ this.queue.set(queue); -+ } -+ -+ /* priority */ -+ -+ protected final int getPriorityVolatile() { -+ return this.priority.get(); -+ } -+ -+ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { -+ if (this.priority.compareAndSet(expect, update)) { -+ return expect; -+ } -+ return this.priority.get(); -+ } -+ -+ protected final int exchangePriorityVolatile(final int value) { -+ return this.priority.getAndSet(value); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ee906b594b306906c170180a29a8b61997d05168 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.locks.LockSupport; -+ -+public class QueueExecutorThread extends Thread { -+ -+ private static final Logger LOGGER = MinecraftServer.LOGGER; -+ -+ protected final PrioritizedTaskQueue queue; -+ protected final long spinWaitTime; -+ -+ protected volatile boolean closed; -+ -+ protected final AtomicBoolean parked = new AtomicBoolean(); -+ -+ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); -+ protected volatile long flushCycles; -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue) { -+ this(queue, (int)(1.e6)); // 1.0ms -+ } -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms -+ this.queue = queue; -+ this.spinWaitTime = spinWaitTime; -+ } -+ -+ @Override -+ public void run() { -+ final long spinWaitTime = this.spinWaitTime; -+ main_loop: -+ for (;;) { -+ this.pollTasks(true); -+ -+ // spinwait -+ -+ final long start = System.nanoTime(); -+ -+ for (;;) { -+ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. -+ Thread.interrupted(); -+ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us -+ -+ if (this.pollTasks(true)) { -+ // restart loop, found tasks -+ continue main_loop; -+ } -+ -+ if (this.handleClose()) { -+ return; // we're done -+ } -+ -+ if ((System.nanoTime() - start) >= spinWaitTime) { -+ break; -+ } -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ this.parked.set(true); -+ -+ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true -+ // (i.e it will not notify us) -+ if (this.pollTasks(true)) { -+ this.parked.set(false); -+ continue; -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop -+ // LockSupport.park() can fail for any reason -+ do { -+ Thread.interrupted(); -+ LockSupport.park("Waiting on tasks"); -+ } while (this.parked.get()); -+ } -+ } -+ -+ protected boolean handleClose() { -+ if (this.closed) { -+ this.pollTasks(true); // this ensures we've emptied the queue -+ this.handleFlushThreads(true); -+ return true; -+ } -+ return false; -+ } -+ -+ protected boolean pollTasks(boolean flushTasks) { -+ Runnable task; -+ boolean ret = false; -+ -+ while ((task = this.queue.poll()) != null) { -+ ret = true; -+ try { -+ task.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); -+ } -+ } -+ -+ if (flushTasks) { -+ this.handleFlushThreads(false); -+ } -+ -+ return ret; -+ } -+ -+ protected void handleFlushThreads(final boolean shutdown) { -+ Thread parking; -+ ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ do { -+ ++flushCycles; // may be plain read opaque write -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } while (this.pollTasks(false)); -+ -+ if (shutdown) { -+ this.flushQueue = null; -+ -+ // defend against a race condition where a flush thread double-checks right before we set to null -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } -+ } -+ -+ /** -+ * Notify's this thread that a task has been added to its queue -+ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks -+ */ -+ public boolean notifyTasks() { -+ if (this.parked.get() && this.parked.getAndSet(false)) { -+ LockSupport.unpark(this); -+ return true; -+ } -+ return false; -+ } -+ -+ protected void queueTask(final T task) { -+ this.queue.add(task); -+ this.notifyTasks(); -+ } -+ -+ /** -+ * Waits until this thread's queue is empty. -+ * -+ * @throws IllegalStateException If the current thread is {@code this} thread. -+ */ -+ public void flush() { -+ final Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread == this) { -+ // avoid deadlock -+ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); -+ } -+ -+ // order is important -+ -+ int successes = 0; -+ long lastCycle = -1L; -+ -+ do { -+ final ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ if (flushQueue == null) { -+ return; -+ } -+ -+ flushQueue.add(currentThread); -+ -+ // double check flush queue -+ if (this.flushQueue == null) { -+ return; -+ } -+ -+ final long currentCycle = this.flushCycles; // may be opaque read -+ -+ if (currentCycle == lastCycle) { -+ Thread.yield(); -+ continue; -+ } -+ -+ // force response -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ LockSupport.park("flushing queue executor thread"); -+ -+ // returns whether there are tasks queued, does not return whether there are tasks executing -+ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) -+ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave -+ // tasks queued concurrently that are unsychronized with this thread as undefined behavior -+ if (this.queue.hasTasks()) { -+ successes = 0; -+ } else { -+ ++successes; -+ } -+ -+ } while (successes != 2); -+ -+ } -+ -+ /** -+ * Closes this queue executor's queue and optionally waits for it to empty. -+ *

    -+ * If wait is {@code true}, then the queue will be empty by the time this call completes. -+ *

    -+ *

    -+ * This function is MT-Safe. -+ *

    -+ * @param wait If this call is to wait until the queue is empty -+ * @param killQueue Whether to shutdown this thread's queue -+ * @return whether this thread shut down the queue -+ */ -+ public boolean close(final boolean wait, final boolean killQueue) { -+ boolean ret = !killQueue ? false : this.queue.shutdown(); -+ this.closed = true; -+ -+ // force thread to respond to the shutdown -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ if (wait) { -+ this.flush(); -+ } -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9a2b51d005efc9d31b3685e8298fd00b341c7dc7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -@@ -0,0 +1,146 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+ -+public final class ChunkLoadTask extends ChunkTask { -+ -+ public boolean cancelled; -+ -+ Consumer onComplete; -+ public PaperFileIOThread.ChunkData chunkData; -+ -+ private boolean hasCompleted; -+ -+ public ChunkLoadTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, -+ final Consumer onComplete) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.onComplete = onComplete; -+ } -+ -+ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); -+ -+ private static ChunkRegionLoader.InProgressChunkHolder createEmptyHolder() { -+ return new ChunkRegionLoader.InProgressChunkHolder(null, EMPTY_QUEUE); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.executeTask(); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); -+ if (!this.hasCompleted) { -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ } -+ } -+ -+ private boolean checkCancelled() { -+ if (this.cancelled) { -+ // IntelliJ does not understand writes may occur to cancelled concurrently. -+ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ return valueInMap; -+ }) == null; -+ } -+ return false; -+ } -+ -+ public void executeTask() { -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ // either executed synchronously or asynchronously -+ final PaperFileIOThread.ChunkData chunkData = this.chunkData; -+ -+ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ if (chunkData.chunkData == null) { -+ // not on disk -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(this.chunkX, this.chunkZ); -+ -+ final PlayerChunkMap chunkManager = this.world.getChunkProvider().playerChunkMap; -+ -+ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { -+ final ChunkRegionLoader.InProgressChunkHolder chunkHolder; -+ -+ // apply fixes -+ -+ try { -+ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), -+ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ try { -+ this.world.getChunkProvider().playerChunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); -+ // non-fatal, continue -+ } -+ -+ try { -+ chunkHolder = ChunkRegionLoader.loadChunk(this.world, -+ chunkManager.definedStructureManager, chunkManager.getVillagePlace(), chunkPos, -+ chunkData.chunkData, true); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ this.complete(chunkHolder); -+ } -+ } -+ -+ private void complete(final ChunkRegionLoader.InProgressChunkHolder holder) { -+ this.hasCompleted = true; -+ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; -+ -+ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ try { -+ ChunkLoadTask.this.onComplete.accept(holder); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e3ad8f50b51c4e9bf38ffa5911444cc88d3f67eb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -@@ -0,0 +1,111 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.atomic.AtomicInteger; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+public final class ChunkSaveTask extends ChunkTask { -+ -+ public final ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ public final IChunkAccess chunk; -+ public final CompletableFuture onComplete = new CompletableFuture<>(); -+ -+ private final AtomicInteger attemptedPriority; -+ -+ public ChunkSaveTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.chunk = chunk; -+ this.asyncSaveData = asyncSaveData; -+ this.attemptedPriority = new AtomicInteger(priority); -+ } -+ -+ @Override -+ public void run() { -+ // can be executed asynchronously or synchronously -+ final NBTTagCompound compound; -+ -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { -+ compound = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ } catch (final Throwable ex) { -+ // has a plugin modified something it should not have and made us CME? -+ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); -+ -+ // Note: We add to the server thread queue here since this is what the server will drain tasks from -+ // when waiting for chunks -+ ChunkTaskManager.queueChunkWaitTask(() -> { -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ NBTTagCompound data = PaperFileIOThread.FAILURE_VALUE; -+ -+ try { -+ data = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); -+ } catch (final Throwable ex1) { -+ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); -+ } -+ -+ ChunkSaveTask.this.complete(data); -+ } -+ }); -+ -+ return; // the main thread will now complete the data -+ } -+ -+ this.complete(compound); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ -+ // we know priority is valid here -+ for (int curr = this.attemptedPriority.get();;) { -+ if (curr <= priority) { -+ break; // curr is higher/same priority -+ } -+ if (this.attemptedPriority.compareAndSet(curr, priority)) { -+ break; -+ } -+ curr = this.attemptedPriority.get(); -+ } -+ -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ this.attemptedPriority.set(priority); -+ return super.updatePriority(priority); -+ } -+ -+ private void complete(final NBTTagCompound compound) { -+ try { -+ this.onComplete.complete(compound); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ if (compound != PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); -+ } -+ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != ChunkSaveTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9c1370c7d85262da9d64871e03e5a8a8c5e087d7 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -@@ -0,0 +1,40 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import net.minecraft.server.level.WorldServer; -+ -+abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public final WorldServer world; -+ public final int chunkX; -+ public final int chunkZ; -+ public final ChunkTaskManager taskManager; -+ -+ public ChunkTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager) { -+ super(priority); -+ this.world = world; -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.taskManager = taskManager; -+ } -+ -+ @Override -+ public String toString() { -+ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + -+ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.updatePriority(priority); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8e642f450b974d81f128d26edfd40915554db638 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -0,0 +1,513 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import com.destroystokyo.paper.io.QueueExecutorThread; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.util.thread.IAsyncTaskHandler; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+import org.apache.commons.lang.StringUtils; -+import org.apache.logging.log4j.Level; -+import org.bukkit.Bukkit; -+import org.spigotmc.AsyncCatcher; -+ -+import java.util.ArrayDeque; -+import java.util.HashSet; -+import java.util.Set; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.function.Consumer; -+ -+public final class ChunkTaskManager { -+ -+ private final QueueExecutorThread[] workers; -+ private final WorldServer world; -+ -+ private final PrioritizedTaskQueue queue; -+ private final boolean perWorldQueue; -+ -+ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); -+ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config -+ -+ protected static QueueExecutorThread[] globalWorkers; -+ protected static QueueExecutorThread globalUrgentWorker; -+ protected static PrioritizedTaskQueue globalQueue; -+ protected static PrioritizedTaskQueue globalUrgentQueue; -+ -+ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); -+ -+ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack -+ -+ private static final class ChunkInfo { -+ -+ public final int chunkX; -+ public final int chunkZ; -+ public final WorldServer world; -+ -+ public ChunkInfo(final int chunkX, final int chunkZ, final WorldServer world) { -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.world = world; -+ } -+ -+ @Override -+ public String toString() { -+ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; -+ } -+ } -+ -+ public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); -+ } -+ } -+ -+ public static void popChunkWait() { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.pop(); -+ } -+ } -+ -+ private static ChunkInfo[] getChunkInfos() { -+ ChunkInfo[] chunks; -+ synchronized (WAITING_CHUNKS) { -+ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); -+ } -+ return chunks; -+ } -+ -+ public static void dumpAllChunkLoadInfo() { -+ ChunkInfo[] chunks = getChunkInfos(); -+ if (chunks.length > 0) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); -+ -+ for (final ChunkInfo chunkInfo : chunks) { -+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); -+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); -+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); -+ -+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); -+ // log current status of chunk to indicate whether we're waiting on generation or loading -+ PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key); -+ -+ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); -+ } -+ } -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -+ if (seenChunks.contains(chunkHolder)) { -+ return; -+ } -+ if (indent > maxDepth) { -+ return; -+ } -+ seenChunks.add(chunkHolder); -+ String indentStr = StringUtils.repeat(" ", indent); -+ if (chunkHolder == null) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); -+ } else { -+ IChunkAccess chunk = chunkHolder.getAvailableChunkNow(); -+ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ } -+ } -+ -+ public static void initGlobalLoadThreads(int threads) { -+ if (threads <= 0 || globalWorkers != null) { -+ return; -+ } -+ -+ globalWorkers = new QueueExecutorThread[threads]; -+ globalQueue = new PrioritizedTaskQueue<>(); -+ globalUrgentQueue = new PrioritizedTaskQueue<>(); -+ -+ for (int i = 0; i < threads; ++i) { -+ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms -+ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); -+ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalWorkers[i].start(); -+ } -+ -+ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms -+ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); -+ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); -+ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalUrgentWorker.start(); -+ } -+ -+ /** -+ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is -+ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. -+ * @param world Specified world. -+ * @param threads Specified number of threads. -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world, final int threads) { -+ this.world = world; -+ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; -+ this.queue = new PrioritizedTaskQueue<>(); -+ this.perWorldQueue = true; -+ -+ for (int i = 0; i < threads; ++i) { -+ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms -+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); -+ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ this.workers[i].start(); -+ } -+ } -+ -+ /** -+ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, -+ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then -+ * this chunk task manager will operate off of the world's chunk task queue. -+ * @param world The world that this task manager is responsible for -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world) { -+ this.world = world; -+ this.workers = globalWorkers; -+ this.queue = globalQueue; -+ this.perWorldQueue = false; -+ } -+ -+ public boolean pollNextChunkTask() { -+ final ChunkTask task = this.chunkTasks.poll(); -+ -+ if (task != null) { -+ task.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. -+ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) -+ */ -+ public static boolean pollChunkWaitQueue() { -+ final Runnable run = CHUNK_WAIT_QUEUE.poll(); -+ if (run != null) { -+ run.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's -+ * chunk task queue, since this is the global chunk wait queue. -+ */ -+ public static void queueChunkWaitTask(final Runnable runnable) { -+ CHUNK_WAIT_QUEUE.add(runnable); -+ } -+ -+ private static void drainChunkWaitQueue() { -+ Runnable run; -+ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { -+ run.run(); -+ } -+ } -+ -+ /** -+ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as -+ * the {@code data} parameter. -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock, final CompletableFuture dataFuture) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ dataFuture.thenAccept((final NBTTagCompound data) -> { -+ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ if (!failed) { -+ chunkData.chunkData = data; -+ } -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, failed, intendingToBlock); // read data off disk if the future fails -+ }); -+ -+ return ret; -+ }); -+ } -+ -+ public void cancelChunkLoad(final int chunkX, final int chunkZ) { -+ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap == null) { -+ return null; -+ } -+ -+ if (valueInMap.cancelled) { -+ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); -+ } -+ valueInMap.cancelled = true; -+ if (valueInMap.cancel()) { -+ return null; -+ } -+ -+ return valueInMap; -+ }); -+ } -+ -+ /** -+ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously -+ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be -+ * carefully chosen. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param onComplete The consumer to invoke with the {@link ChunkRegionLoader.InProgressChunkHolder} object once this task is complete -+ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) -+ * @return The {@link ChunkLoadTask} associated with -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, true, intendingToBlock); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded -+ * from the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param asyncSaveData Async save data. See {@link ChunkRegionLoader#getAsyncSaveData(WorldServer, IChunkAccess)} -+ * @param chunk Chunk to save -+ * @return The {@link ChunkSaveTask} associated with the save task. -+ */ -+ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, -+ final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ AsyncCatcher.catchOp("chunk save schedule"); -+ -+ final WorldServer world = this.world; -+ -+ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != null) { -+ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); -+ } -+ -+ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); -+ -+ ChunkTaskManager.this.internalSchedule(ret); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. -+ * Returns {@code null} if no save is in progress. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ */ -+ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.onComplete; -+ } -+ -+ /** -+ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk -+ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress -+ */ -+ public IChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.chunk; -+ } -+ -+ public void flush() { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks here -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ drainChunkWaitQueue(); -+ -+ if (this.workers == null) { -+ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ } else { -+ CompletableFuture wait = new CompletableFuture<>(); -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ }); -+ wait.join(); -+ } -+ } else { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.flush(); -+ } -+ } -+ if (globalUrgentWorker != null) globalUrgentWorker.flush(); -+ -+ // flush again since tasks we execute async saves -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ } -+ -+ public void close(final boolean wait) { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager -+ // we do this regardless of the wait param since after we invoke close no tasks can be queued -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ -+ if (this.workers == null) { -+ if (wait) { -+ this.flush(); -+ } -+ return; -+ } -+ -+ if (this.workers != globalWorkers) { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.close(false, this.perWorldQueue); -+ } -+ } -+ -+ if (wait) { -+ this.flush(); -+ } -+ } -+ -+ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); -+ if (chunkSaveTask != null) { -+ // don't bump save into urgent queue -+ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); -+ } -+ -+ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); -+ if (chunkLoadTask != null) { -+ raiseTaskPriority(chunkLoadTask, priority); -+ } -+ } -+ -+ private void raiseTaskPriority(ChunkTask task, int priority) { -+ final boolean raised = task.raisePriority(priority); -+ if (task.isScheduled() && raised && this.workers != null) { -+ // only notify if we're in queue to be executed -+ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ // was in another queue but became urgent later, add to urgent queue and the previous -+ // queue will just have to ignore this task if it has already been started. -+ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first -+ // but the urgent queue has dedicated thread(s) so it's likely to win.... -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.internalScheduleNotify(); -+ } -+ } -+ } -+ -+ protected void internalSchedule(final ChunkTask task) { -+ if (this.workers == null) { -+ this.chunkTasks.add(task); -+ return; -+ } -+ -+ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread -+ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) -+ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.queue.add(task); -+ this.internalScheduleNotify(); -+ } -+ -+ } -+ -+ protected void internalScheduleNotify() { -+ if (this.workers == null) { -+ return; -+ } -+ for (final QueueExecutorThread worker : this.workers) { -+ if (worker.notifyTasks()) { -+ // break here since we only want to wake up one worker for scheduling one task -+ break; -+ } -+ } -+ } -+ -+ -+ protected void internalScheduleNotifyUrgent() { -+ if (globalUrgentWorker == null) { -+ return; -+ } -+ globalUrgentWorker.notifyTasks(); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -index e201e4efd4ecc65ec3c38528a4ec5336e2d51ab2..45f3f8964a587c382b6ea82560e9da30be42987f 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -@@ -14,7 +14,7 @@ public class PacketPlayInTabComplete implements Packet { - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { - this.a = packetdataserializer.i(); -- this.b = packetdataserializer.e(32500); -+ this.b = packetdataserializer.e(2048); - } - - @Override -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index fbd33aef21b4539d249c367609a36491530fb7ca..5a410550cfb48505c9de9979465ed1528c8fbf05 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -714,4 +714,9 @@ public final class MCUtil { - out.print(fileData); - } - } -+ -+ public static int getTicketLevelFor(ChunkStatus status) { -+ // TODO make sure the constant `33` is correct on future updates. See getChunkAt(int, int, ChunkStatus, boolean) -+ return 33 + ChunkStatus.getTicketLevelOffset(status); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 191a74bd9b894f9d64d0a55747cb17e07ceef597..1732fc552c290d294b68d6f92f2a58d985fbef21 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -42,6 +42,7 @@ import net.minecraft.server.players.UserCache; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.entity.npc.VillagerTrades; - import net.minecraft.world.level.DataPackConfiguration; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -210,6 +211,7 @@ public class Main { - - convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object); - */ -+ Class.forName(VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async - final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.a((thread) -> { - DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new); - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 571f3860bc31c077c239a32776f6aaf6ff30ce71..ef13e310a8a452d2ba1d9c8bac72f9baf2693de0 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -922,7 +922,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { -+ if (Thread.currentThread() != this.serverThread) { -+ CompletableFuture> future = new CompletableFuture>(); -+ this.serverThreadQueue.execute(() -> { -+ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { -+ if (ex != null) { -+ future.completeExceptionally(ex); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { -+ world.getWorld().loadChunk(x, z, gen); -+ Chunk chunk = getChunkAtIfLoadedMainThread(x, z); -+ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ long k = ChunkCoordIntPair.pair(x, z); -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ -+ IChunkAccess ichunkaccess; -+ -+ // try cache -+ for (int l = 0; l < 4; ++l) { -+ if (k == this.cachePos[l] && ChunkStatus.FULL == this.cacheStatus[l]) { -+ ichunkaccess = this.cacheChunk[l]; -+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime -+ -+ // move to first in cache -+ -+ for (int i1 = 3; i1 > 0; --i1) { -+ this.cachePos[i1] = this.cachePos[i1 - 1]; -+ this.cacheStatus[i1] = this.cacheStatus[i1 - 1]; -+ this.cacheChunk[i1] = this.cacheChunk[i1 - 1]; -+ } -+ -+ this.cachePos[0] = k; -+ this.cacheStatus[0] = ChunkStatus.FULL; -+ this.cacheChunk[0] = ichunkaccess; -+ -+ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); -+ } -+ } -+ } -+ -+ if (gen) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ IChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions -+ if (current != null) { -+ if (!(current instanceof ProtoChunkExtension) && !(current instanceof Chunk)) { -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ // we know the chunk is at full status here (either in read-only mode or the real thing) -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); -+ -+ if (status != null && status != ChunkStatus.FULL) { -+ // does not exist on disk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ if (status == ChunkStatus.FULL) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ // status is null here -+ -+ // here we don't know what status it is and we're not supposed to generate -+ // so we asynchronously load empty status -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { -+ IChunkAccess chunk = either.left().orElse(null); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof Chunk)) { -+ // the chunk on disk was not a full status chunk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ ; // bring to full status if required -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ }); -+ } -+ -+ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, boolean isUrgent) { -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); -+ } -+ -+ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, ChunkStatus status, boolean isUrgent) { -+ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); -+ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); -+ int ticketLevel = MCUtil.getTicketLevelFor(status); -+ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ -+ return future.thenComposeAsync((Either either) -> { -+ // either left -> success -+ // either right -> failure -+ -+ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading -+ -+ Optional failure = either.right(); -+ -+ if (failure.isPresent()) { -+ // failure -+ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); -+ } -+ -+ return CompletableFuture.completedFuture(either); -+ }, this.serverThreadQueue); -+ } -+ -+ public void addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } -+ -+ public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } - // Paper end - - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ final int x = i; final int z = j; // Paper - conflict on variable change - if (Thread.currentThread() != this.serverThread) { - return (IChunkAccess) CompletableFuture.supplyAsync(() -> { - return this.getChunkAt(i, j, chunkstatus, flag); -@@ -359,11 +487,16 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); -+ CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag, true); // Paper - - if (!completablefuture.isDone()) { // Paper -+ // Paper start - async chunk io/loading -+ this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); -+ // Paper end - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -429,6 +562,11 @@ public class ChunkProviderServer extends IChunkProvider { - } - - private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ // Paper start - add isUrgent - old sig left in place for dirty nms plugins -+ return getChunkFutureMainThread(i, j, chunkstatus, flag, false); -+ } -+ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); - long k = chunkcoordintpair.pair(); - int l = 33 + ChunkStatus.a(chunkstatus); -@@ -828,11 +966,12 @@ public class ChunkProviderServer extends IChunkProvider { - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task - try { -+ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask(); // Paper - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { - ChunkProviderServer.this.lightEngine.queueUpdate(); -- return super.executeNext(); -+ return super.executeNext() || execChunkTask; // Paper - } - } finally { - playerChunkMap.callbackExecutor.run(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 75d4a8fc394449ccc006fe67a8842edcd9f36854..6433463938d8bb717840c8f57fe6e7079e1030f2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -158,6 +158,18 @@ public class PlayerChunk { - } - return null; - } -+ -+ public ChunkStatus getChunkHolderStatus() { -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return curr; -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -376,7 +388,7 @@ public class PlayerChunk { - ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); - ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); - boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; -- boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; -+ boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range) - PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel); - PlayerChunk.State playerchunk_state1 = getChunkState(this.ticketLevel); - // CraftBukkit start -@@ -412,6 +424,12 @@ public class PlayerChunk { - } - }); - -+ // Paper start -+ if (!flag1) { -+ playerchunkmap.world.asyncChunkTaskManager.cancelChunkLoad(this.location.x, this.location.z); -+ } -+ // Paper end -+ - for (int i = flag1 ? chunkstatus1.c() + 1 : 0; i <= chunkstatus.c(); ++i) { - completablefuture = (CompletableFuture) this.statusFutures.get(i); - if (completablefuture != null) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 5a11765c8a7d754ec86d829fa5e85d2809dd937e..46c91230ab6f12db77b453c312fa7382b76fad34 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -88,6 +88,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.ProtoChunkExtension; - import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; - import net.minecraft.world.level.chunk.storage.IChunkLoader; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -@@ -112,7 +113,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; - public final ChunkGenerator chunkGenerator; -- private final Supplier l; -+ private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; - public final LongSet unloadQueue; - private boolean updatingChunksModified; -@@ -122,7 +123,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; - private final AtomicInteger u; -- private final DefinedStructureManager definedStructureManager; -+ public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; -@@ -205,7 +206,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); - this.l = supplier; -- this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag); -+ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - } - -@@ -247,12 +248,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- protected PlayerChunk getUpdatingChunk(long i) { -+ public PlayerChunk getUpdatingChunk(long i) { // Paper - return (PlayerChunk) this.updatingChunks.get(i); - } - - @Nullable -- protected PlayerChunk getVisibleChunk(long i) { -+ public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public - return (PlayerChunk) this.visibleChunks.get(i); - } - -@@ -374,6 +375,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public void close() throws IOException { - try { - this.p.close(); -+ this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); - } finally { - super.close(); -@@ -465,7 +467,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.b(() -> { - return true; - }); -- this.i(); -+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour -+// this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { - this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -@@ -481,16 +484,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot -+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more - - protected void unloadChunks(BooleanSupplier booleansupplier) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - -+ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper - gameprofilerfiller.enter("poi"); - this.m.a(booleansupplier); -+ } // Paper - gameprofilerfiller.exitEnter("chunk_unload"); - if (!this.world.isSavingDisabled()) { -+ try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper - this.b(booleansupplier); -+ }// Paper - } - - gameprofilerfiller.exit(); -@@ -511,12 +518,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunk != null) { - this.pendingUnload.put(j, playerchunk); - this.updatingChunksModified = true; -+ this.a(j, playerchunk); // Paper - Move up - don't leak chunks - // Spigot start - if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; - } - // Spigot end -- this.a(j, playerchunk); -+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb - } - } - activityAccountant.endActivity(); // Spigot -@@ -530,6 +538,60 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - async chunk save for unload -+ // Note: This is very unsafe to call if the chunk is still in use. -+ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being -+ // serializing the chunk is left to a worker thread. -+ private void asyncSave(IChunkAccess chunk) { -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ NBTTagCompound poiData; -+ try (Timing ignored = this.world.timings.chunkUnloadPOISerialization.startTiming()) { -+ poiData = this.getVillagePlace().getData(chunk.getPos()); -+ } -+ -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, -+ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ -+ if (!chunk.isNeedsSaving()) { -+ return; -+ } -+ -+ ChunkStatus chunkstatus = chunk.getChunkStatus(); -+ -+ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) -+ if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper -+ // Paper start - Optimize save by using status cache -+ try { -+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); -+ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) { -+ // Paper end -+ return; -+ } -+ -+ if (chunkstatus == ChunkStatus.EMPTY && chunk.h().values().stream().noneMatch(StructureStart::e)) { -+ return; -+ } -+ } catch (IOException ex) { -+ ex.printStackTrace(); -+ return; -+ } -+ } -+ } -+ -+ ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ try (Timing ignored = this.world.timings.chunkUnloadPrepareSave.startTiming()) { -+ asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); -+ } -+ -+ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, -+ asyncSaveData, chunk); -+ -+ chunk.setLastSaved(this.world.getTime()); -+ chunk.setNeedsSaving(false); -+ } -+ // Paper end -+ - private void a(long i, PlayerChunk playerchunk) { - CompletableFuture completablefuture = playerchunk.getChunkSave(); - Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -543,7 +605,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ((Chunk) ichunkaccess).setLoaded(false); - } - -- this.saveChunk(ichunkaccess); -+ //this.saveChunk(ichunkaccess);// Paper - delay - if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -551,6 +613,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - this.autoSaveQueue.remove(playerchunk); // Paper - -+ try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving -+ } catch (Throwable ex) { -+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); -+ this.saveChunk(ichunkaccess); -+ } -+ - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); - this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); -@@ -621,19 +690,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - Async chunk io -+ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound; // Paper -- try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -- nbttagcompound = this.readChunkData(chunkcoordintpair); -- } // Paper end -+ // Paper start -+ if (ioThrowable != null) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); -+ } - -- if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); -+ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); -+ chunkHolder.tasks.forEach(Runnable::run); -+ // Paper end - -- if (flag) { -- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound); -+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async -+ -+ if (true) { -+ ProtoChunk protochunk = chunkHolder.protoChunk; - - protochunk.setLastSaved(this.world.getTime()); - this.a(chunkcoordintpair, protochunk.getChunkStatus().getType()); -@@ -657,7 +730,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.g(chunkcoordintpair); - return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter -- }, this.executor); -+ // Paper start - Async chunk io -+ }; -+ CompletableFuture> ret = new CompletableFuture<>(); -+ -+ Consumer chunkHolderConsumer = (ChunkRegionLoader.InProgressChunkHolder holder) -> { -+ // Go into the chunk load queue and not server task queue so we can be popped out even faster. -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { -+ try { -+ ret.complete(syncLoadComplete.apply(holder, null)); -+ } catch (Exception e) { -+ ret.completeExceptionally(e); -+ } -+ }); -+ }; -+ -+ CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (chunkSaveFuture != null) { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ } else { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ } -+ return ret; -+ // Paper end - } - - private void g(ChunkCoordIntPair chunkcoordintpair) { -@@ -892,6 +990,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public boolean saveChunk(IChunkAccess ichunkaccess) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper - this.m.a(ichunkaccess.getPos()); - if (!ichunkaccess.isNeedsSaving()) { - return false; -@@ -904,6 +1003,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = ichunkaccess.getChunkStatus(); - - if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.h(chunkcoordintpair)) { - return false; - } -@@ -911,12 +1011,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunkstatus == ChunkStatus.EMPTY && ichunkaccess.h().values().stream().noneMatch(StructureStart::e)) { - return false; - } -+ } // Paper - } - - this.world.getMethodProfiler().c("chunkSave"); -- NBTTagCompound nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ NBTTagCompound nbttagcompound; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper -+ nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ } // Paper -+ - -- this.a(chunkcoordintpair, nbttagcompound); -+ // Paper start - async chunk io -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, -+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); -+ // Paper end - async chunk io - this.a(chunkcoordintpair, chunkstatus.getType()); - return true; - } catch (Exception exception) { -@@ -925,6 +1033,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return false; - } - } -+ } // Paper - } - - private boolean h(ChunkCoordIntPair chunkcoordintpair) { -@@ -1054,6 +1163,35 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ // Paper start - Asynchronous chunk io -+ @Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ false, true, true).join().chunkData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - @Nullable - public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -@@ -1075,33 +1213,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - chunk status cache "api" - public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ synchronized (this) { // Paper -+ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); - - return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } // Paper - } - - public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false); - -- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -- return null; -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); - } -+ // Paper end -+ synchronized (this) { // Paper - async io -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } - -- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - -- if (status != null) { -- return status; -+ if (status != null) { -+ return status; -+ } -+ // Paper start - async io - } - -- this.readChunkData(chunkPos); -+ NBTTagCompound compound = this.readChunkData(chunkPos); - -- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ return ChunkRegionLoader.getStatus(compound); -+ // Paper end - } - - public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ synchronized (this) { -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); - -- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } - } - - public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -@@ -1110,6 +1270,39 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ -+ // Paper start - async io -+ // this function will not load chunk data off disk to check for status -+ // ret null for unknown, empty for empty status on disk or absent from disk -+ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(x, z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, x, z, false); -+ -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); -+ } -+ // Paper end -+ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ synchronized (world.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.regionFileCache.getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return !file.chunkExists(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); -+ } -+ } -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -1456,6 +1649,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ public VillagePlace getVillagePlace() { return this.h(); } // Paper - OBFHELPER - protected VillagePlace h() { - return this.m; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 285a03b57431bd6a4d26bb84e916d2c6e1eb0213..218dc900e125a11548485887b1918742072c7a77 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -26,6 +26,7 @@ public class TicketType { - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper -+ public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 9012c837c2f284e9f2f11462e6dc7e2f6e190939..bb6c59237702bf82d2c344c864f233c606fd429f 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -51,6 +51,7 @@ import net.minecraft.core.IRegistry; - import net.minecraft.core.IRegistryCustom; - import net.minecraft.core.SectionPosition; - import net.minecraft.core.particles.ParticleParam; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; -@@ -126,6 +127,7 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.dimension.DimensionManager; - import net.minecraft.world.level.dimension.end.EnderDragonBattle; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -208,6 +210,79 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.chunkProvider.getChunkAt(x, z, false); - } - -+ // Paper start - Asynchronous IO -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -255,6 +330,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.dragonBattle = null; - } - this.getServer().addWorld(this.getWorld()); // CraftBukkit -+ -+ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper - } - - // CraftBukkit start -@@ -1743,7 +1820,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -- getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ getChunkProvider().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { -+ ex.printStackTrace(); -+ return null; -+ }); - }); - } - public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d84d87b0dd01b4d67e55f1b445928285c45a08ca..fa0b7edf42243d53d9dc897903b9b9e902b33cf7 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -730,6 +730,13 @@ public class PlayerConnection implements PacketListenerPlayIn { - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } -+ // Paper start -+ String str = packetplayintabcomplete.c(); int index = -1; -+ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ // Paper end - // CraftBukkit end - StringReader stringreader = new StringReader(packetplayintabcomplete.c()); - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index e5641f2b41d89a57285fc072a48b951aa03a14a7..ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -91,7 +91,7 @@ public abstract class IAsyncTaskHandler implements Mailbox public - while (this.executeNext()) { - ; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index aa1d948e6aebef25f0f4c4c07f5131d2e8387e59..04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -22,7 +22,9 @@ import java.util.stream.Stream; - import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.level.LightEngineGraphSection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.IWorldReader; -@@ -36,8 +38,16 @@ public class VillagePlace extends RegionFileSection { - private final VillagePlace.a a = new VillagePlace.a(); - private final LongSet b = new LongOpenHashSet(); - -+ private final WorldServer world; // Paper -+ - public VillagePlace(File file, DataFixer datafixer, boolean flag) { -+ // Paper start - add world parameter -+ this(file, datafixer, flag, null); -+ } -+ public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { - super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ this.world = world; -+ // Paper end - add world parameter - } - - public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { -@@ -155,7 +165,23 @@ public class VillagePlace extends RegionFileSection { - - @Override - public void a(BooleanSupplier booleansupplier) { -- super.a(booleansupplier); -+ // Paper start - async chunk io -+ if (this.world == null) { -+ super.a(booleansupplier); -+ } else { -+ //super.a(booleansupplier); // re-implement below -+ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); -+ -+ NBTTagCompound data; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ data = this.getData(chunkcoordintpair); -+ } -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ } -+ } -+ // Paper end - this.a.a(); - } - -@@ -255,6 +281,35 @@ public class VillagePlace extends RegionFileSection { - } - } - -+ // Paper start - Asynchronous chunk io -+ @javax.annotation.Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ true, false, true).join().poiData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new java.io.IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - public static enum Occupancy { - - HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> { -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index f3bcb96232d18abbcd86b079a7c5830bb30d75d2..37b7dd82a227a88b720c13a813dd7e8caf803e03 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPosition; - - public class NextTickListEntry { - -- private static long d; -+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading - private final T e; - public final BlockPosition a; - public final long b; -@@ -17,7 +17,7 @@ public class NextTickListEntry { - } - - public NextTickListEntry(BlockPosition blockposition, T t0, long i, TickListPriority ticklistpriority) { -- this.f = (long) (NextTickListEntry.d++); -+ this.f = (long) (NextTickListEntry.COUNTER.getAndIncrement()); // Paper - async chunk loading - this.a = blockposition.immutableCopy(); - this.e = t0; - this.b = i; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 711308cf84a816f09d116a7414f9cbee803c8713..f094ddf6b4d155f3c7a08a3b811c98b0862fd098 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -170,6 +170,7 @@ public class ChunkStatus { - return ChunkStatus.q.size(); - } - -+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.a(status); } // Paper - OBFHELPER - public static int a(ChunkStatus chunkstatus) { - return ChunkStatus.r.getInt(chunkstatus.c()); - } -@@ -185,6 +186,7 @@ public class ChunkStatus { - this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; - } - -+ public final int getStatusIndex() { return c(); } // Paper - OBFHELPER - public int c() { - return this.t; - } -@@ -193,7 +195,7 @@ public class ChunkStatus { - return this.s; - } - -- public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER -+ public final ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -206,6 +208,7 @@ public class ChunkStatus { - return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess); - } - -+ public final int getNeighborRadius() { return this.f(); } // Paper - OBFHELPER - public int f() { - return this.x; - } -@@ -233,6 +236,7 @@ public class ChunkStatus { - return this.z; - } - -+ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return b(chunkstatus); } // Paper - OBFHELPER - public boolean b(ChunkStatus chunkstatus) { - return this.c() >= chunkstatus.c(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index a2518fdadd1d7239e8614f498a5223144f1c2a36..86b4db483787c5fd10461f7d7e90a772ee049599 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -73,6 +73,7 @@ public class NibbleArray { - return this.a; - } - -+ public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { - return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index c652897aae99c48c6cc020b5d64f6a8b02beecb5..c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.shorts.ShortList; - import it.unimi.dsi.fastutil.shorts.ShortListIterator; -+import java.util.ArrayDeque; // Paper - import java.util.Arrays; - import java.util.BitSet; - import java.util.EnumSet; -@@ -66,7 +67,29 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start -+ public static final class InProgressChunkHolder { -+ -+ public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; -+ -+ public NBTTagCompound poiData; -+ -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { -+ this.protoChunk = protoChunk; -+ this.tasks = tasks; -+ } -+ } -+ - public static ProtoChunk loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -+ InProgressChunkHolder holder = loadChunk(worldserver, definedstructuremanager, villageplace, chunkcoordintpair, nbttagcompound, true); -+ holder.tasks.forEach(Runnable::run); -+ return holder.protoChunk; -+ } -+ -+ public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { -+ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); -+ // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -@@ -93,7 +116,9 @@ public class ChunkRegionLoader { - LightEngine lightengine = chunkproviderserver.getLightEngine(); - - if (flag) { -- lightengine.b(chunkcoordintpair, true); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ lightengine.b(chunkcoordintpair, true); -+ }); // Paper - delay this task since we're executing off-main - } - - for (int i = 0; i < nbttaglist.size(); ++i) { -@@ -109,16 +134,28 @@ public class ChunkRegionLoader { - achunksection[b0] = chunksection; - } - -- villageplace.a(chunkcoordintpair, chunksection); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.a(chunkcoordintpair, chunksection); -+ }); // Paper - delay this task since we're executing off-main - } - - if (flag) { - if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { -- lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("BlockLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - - if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { -- lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("SkyLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - } - } -@@ -227,7 +264,7 @@ public class ChunkRegionLoader { - } - - if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { -- return new ProtoChunkExtension((Chunk) object); -+ return new InProgressChunkHolder(new ProtoChunkExtension((Chunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading - } else { - ProtoChunk protochunk1 = (ProtoChunk) object; - -@@ -266,11 +303,83 @@ public class ChunkRegionLoader { - protochunk1.a(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); - } - -- return protochunk1; -+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading -+ } -+ } -+ -+ // Paper start - async chunk save for unload -+ public static final class AsyncSaveData { -+ public final NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15) -+ public final NibbleArray[] skyLight; -+ -+ public final NBTTagList blockTickList; // non-null if we had to go to the server's tick list -+ public final NBTTagList fluidTickList; // non-null if we had to go to the server's tick list -+ -+ public final long worldTime; -+ -+ public AsyncSaveData(NibbleArray[] blockLight, NibbleArray[] skyLight, NBTTagList blockTickList, NBTTagList fluidTickList, -+ long worldTime) { -+ this.blockLight = blockLight; -+ this.skyLight = skyLight; -+ this.blockTickList = blockTickList; -+ this.fluidTickList = fluidTickList; -+ this.worldTime = worldTime; - } - } - -+ // must be called sync -+ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { -+ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ -+ LightEngineThreaded lightenginethreaded = world.getChunkProvider().getLightEngine(); -+ -+ NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; -+ NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; -+ -+ for (int i = -1; i < 17; ++i) { -+ NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); -+ NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); -+ -+ // copy data for safety -+ if (blockArray != null) { -+ blockArray = blockArray.copy(); -+ } -+ if (skyArray != null) { -+ skyArray = skyArray.copy(); -+ } -+ -+ // apply offset of 1 for -1 starting index -+ blockLight[i + 1] = blockArray; -+ skyLight[i + 1] = skyArray; -+ } -+ -+ TickList blockTickList = chunk.n(); -+ -+ NBTTagList blockTickListSerialized; -+ if (blockTickList instanceof ProtoChunkTickList || blockTickList instanceof TickListChunk) { -+ blockTickListSerialized = null; -+ } else { -+ blockTickListSerialized = world.getBlockTickList().a(chunkPos); -+ } -+ -+ TickList fluidTickList = chunk.o(); -+ -+ NBTTagList fluidTickListSerialized; -+ if (fluidTickList instanceof ProtoChunkTickList || fluidTickList instanceof TickListChunk) { -+ fluidTickListSerialized = null; -+ } else { -+ fluidTickListSerialized = world.getFluidTickList().a(chunkPos); -+ } -+ -+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getTime()); -+ } -+ - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { -+ return saveChunk(worldserver, ichunkaccess, null); -+ } -+ public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); -@@ -279,7 +388,7 @@ public class ChunkRegionLoader { - nbttagcompound.set("Level", nbttagcompound1); - nbttagcompound1.setInt("xPos", chunkcoordintpair.x); - nbttagcompound1.setInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.setLong("LastUpdate", worldserver.getTime()); -+ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading - nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); - nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); - ChunkConverter chunkconverter = ichunkaccess.p(); -@@ -295,14 +404,22 @@ public class ChunkRegionLoader { - - NBTTagCompound nbttagcompound2; - -- for (int i = -1; i < 17; ++i) { -+ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors - ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && chunksection1.getYPosition() >> 4 == finalI; // CraftBukkit - decompile errors - }).findFirst().orElse(Chunk.a); -- NibbleArray nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); -- NibbleArray nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); -- -+ // Paper start - async chunk save for unload -+ NibbleArray nibblearray; // block light -+ NibbleArray nibblearray1; // sky light -+ if (asyncsavedata == null) { -+ nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) -+ nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) -+ } else { -+ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index -+ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index -+ } -+ // Paper end - if (chunksection != Chunk.a || nibblearray != null || nibblearray1 != null) { - nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setByte("Y", (byte) (i & 255)); -@@ -369,7 +486,7 @@ public class ChunkRegionLoader { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start -- if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { - toUpdate.add(entity); - continue; - } -@@ -412,24 +529,32 @@ public class ChunkRegionLoader { - } - - nbttagcompound1.set("Entities", nbttaglist2); -- TickList ticklist = ichunkaccess.n(); -+ TickList ticklist = ichunkaccess.n(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist instanceof ProtoChunkTickList) { - nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); - } else if (ticklist instanceof TickListChunk) { - nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); -+ // Paper end - } else { -- nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - -- TickList ticklist1 = ichunkaccess.o(); -+ TickList ticklist1 = ichunkaccess.o(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist1 instanceof ProtoChunkTickList) { - nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b()); - } else if (ticklist1 instanceof TickListChunk) { - nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); -+ // Paper end - } else { -- nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - - nbttagcompound1.set("PostProcessing", a(ichunkaccess.l())); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index d785f44cd503d4d91589f3fc4bc8dc805dff3d41..01ae13385dd0208c9f34da8b3897b571f86305d0 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -3,6 +3,10 @@ package net.minecraft.world.level.chunk.storage; - import com.mojang.datafixers.DataFixer; - import java.io.File; - import java.io.IOException; -+// Paper start -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.CompletionException; -+// Paper end - import java.util.function.Supplier; - import javax.annotation.Nullable; - import net.minecraft.SharedConstants; -@@ -25,32 +29,41 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker - protected final DataFixer b; - @Nullable -- private PersistentStructureLegacy c; -+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading -+ -+ private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileCache regionFileCache; - - public IChunkLoader(File file, DataFixer datafixer, boolean flag) { -+ this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker - this.b = datafixer; -- this.a = new IOWorker(file, flag, "chunk"); -+ // Paper - nuke IOWorker - } - - // CraftBukkit start - private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { - ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); - if (cps != null) { -- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); -- if (cps.isLoaded(x, z)) { -+ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe -+ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! - return true; - } - } - -- NBTTagCompound nbt = read(pos); -- if (nbt != null) { -- NBTTagCompound level = nbt.getCompound("Level"); -- if (level.getBoolean("TerrainPopulated")) { -- return true; -- } -+ -+ // Paper start - prioritize -+ NBTTagCompound nbt = cps == null ? read(pos) : -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((WorldServer)cps.getWorld(), x, z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; -+ // Paper end -+ if (nbt != null) { -+ NBTTagCompound level = nbt.getCompound("Level"); -+ if (level.getBoolean("TerrainPopulated")) { -+ return true; -+ } - - ChunkStatus status = ChunkStatus.a(level.getString("Status")); - if (status != null && status.b(ChunkStatus.FEATURES)) { -@@ -81,11 +94,13 @@ public class IChunkLoader implements AutoCloseable { - if (i < 1493) { - nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); - if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - if (this.c == null) { - this.c = PersistentStructureLegacy.a(resourcekey, (WorldPersistentData) supplier.get()); - } - - nbttagcompound = this.c.a(nbttagcompound); -+ } // Paper - Async chunk loading - } - } - -@@ -103,22 +118,20 @@ public class IChunkLoader implements AutoCloseable { - - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -- return this.a.a(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); - } - -- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -- this.a.a(chunkcoordintpair, nbttagcompound); -+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.c.a(chunkcoordintpair.pair()); -+ } // Paper - Async chunk loading} - } -- -- } -- -- public void i() { -- this.a.a().join(); - } - - public void close() throws IOException { -- this.a.close(); -+ this.regionFileCache.close(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index d50b9c9d030016f951e2ed7fb519250b7408c833..1b0535ba211904b2384cc80c02c21ed1a606e752 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -45,6 +45,8 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ - // Paper start - Cache chunk status - private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; - -@@ -251,7 +253,7 @@ public class RegionFile implements AutoCloseable { - return (i + 4096 - 1) / 4096; - } - -- public boolean b(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized - int i = this.getOffset(chunkcoordintpair); - - if (i == 0) { -@@ -411,6 +413,11 @@ public class RegionFile implements AutoCloseable { - } - - public void close() throws IOException { -+ // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.lock(); -+ synchronized (this) { -+ try { -+ // Paper end - this.closed = true; // Paper - try { - this.d(); -@@ -421,6 +428,10 @@ public class RegionFile implements AutoCloseable { - this.dataFile.close(); - } - } -+ } finally { // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.unlock(); -+ } -+ } // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 55e7e983d2c760a8052d7b3ddbdc8447f619a60f..ebb0d6988f87013ea5d523ab4a1b31cb669ccc43 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -17,7 +17,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - --public final class RegionFileCache implements AutoCloseable { -+public class RegionFileCache implements AutoCloseable { // Paper - no final - - public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); - private final File b; -@@ -30,16 +30,27 @@ public final class RegionFileCache implements AutoCloseable { - - - // Paper start -- public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io - return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } - - // Paper end -- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize -+ // Paper start - add lock parameter -+ return this.getFile(chunkcoordintpair, existingOnly, false); -+ } -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { -+ // Paper end - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - - if (regionfile != null) { -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile.fileLock.lock(); -+ } -+ // Paper end - return regionfile; - } else { - if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -55,6 +66,12 @@ public final class RegionFileCache implements AutoCloseable { - RegionFile regionfile1 = new RegionFile(file, this.b, this.c); - - this.cache.putAndMoveToFirst(i, regionfile1); -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile1.fileLock.lock(); -+ } -+ // Paper end - return regionfile1; - } - } -@@ -130,11 +147,12 @@ public final class RegionFileCache implements AutoCloseable { - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -- RegionFile regionfile = this.getFile(chunkcoordintpair, true); -+ RegionFile regionfile = this.getFile(chunkcoordintpair, true, true); // Paper - if (regionfile == null) { - return null; - } - // CraftBukkit end -+ try { // Paper - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); - // Paper start - if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -@@ -172,10 +190,14 @@ public final class RegionFileCache implements AutoCloseable { - } - - return nbttagcompound; -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -- RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ RegionFile regionfile = this.getFile(chunkcoordintpair, false, true); // CraftBukkit // Paper -+ try { // Paper - int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; -@@ -214,9 +236,12 @@ public final class RegionFileCache implements AutoCloseable { - MinecraftServer.LOGGER.error("Failed to save chunk", laste); - } - // Paper end -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - -- public void close() throws IOException { -+ public synchronized void close() throws IOException { // Paper -> synchronized - ExceptionSuppressor exceptionsuppressor = new ExceptionSuppressor<>(); - ObjectIterator objectiterator = this.cache.values().iterator(); - -@@ -243,4 +268,12 @@ public final class RegionFileCache implements AutoCloseable { - } - - } -+ -+ // CraftBukkit start -+ public synchronized boolean chunkExists(ChunkCoordIntPair pos) throws IOException { // Paper - synchronize -+ RegionFile regionfile = getFile(pos, true); -+ -+ return regionfile != null ? regionfile.chunkExists(pos) : false; -+ } -+ // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -index 8ad97a8a2189553da88810380b1c240079eacc93..d3b9a9e4695655860c72db5f2188472681e8d37a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -@@ -30,28 +30,29 @@ import net.minecraft.world.level.World; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - --public class RegionFileSection implements AutoCloseable { -+public class RegionFileSection extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker - - private static final Logger LOGGER = LogManager.getLogger(); -- private final IOWorker b; -+ // Paper - nuke IOWorker - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); -- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); -+ public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> public - private final Function> e; - private final Function f; - private final DataFixer g; - private final DataFixTypes h; - - public RegionFileSection(File file, Function> function, Function function1, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { -+ super(file, flag); // Paper - nuke IOWorker - this.e = function; - this.f = function1; - this.g = datafixer; - this.h = datafixtypes; -- this.b = new IOWorker(file, flag, file.getName()); -+ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker - } - - protected void a(BooleanSupplier booleansupplier) { - while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { -- ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers - - this.d(chunkcoordintpair); - } -@@ -105,13 +106,18 @@ public class RegionFileSection implements AutoCloseable { - } - - private void b(ChunkCoordIntPair chunkcoordintpair) { -- this.a(chunkcoordintpair, DynamicOpsNBT.a, this.c(chunkcoordintpair)); -+ // Paper start - load data in function -+ this.loadInData(chunkcoordintpair, this.c(chunkcoordintpair)); -+ } -+ public void loadInData(ChunkCoordIntPair chunkPos, NBTTagCompound compound) { -+ this.a(chunkPos, DynamicOpsNBT.a, compound); -+ // Paper end - } - - @Nullable - private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) { - try { -- return this.b.a(chunkcoordintpair); -+ return this.read(chunkcoordintpair); // Paper - nuke IOWorker - } catch (IOException ioexception) { - RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception); - return null; -@@ -157,17 +163,31 @@ public class RegionFileSection implements AutoCloseable { - } - - private void d(ChunkCoordIntPair chunkcoordintpair) { -- Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); // Paper - conflict here to avoid adding obfhelpers :) - NBTBase nbtbase = (NBTBase) dynamic.getValue(); - - if (nbtbase instanceof NBTTagCompound) { -- this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase); -+ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async - } else { - RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); - } - - } - -+ // Paper start - internal get data function, copied from above -+ private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) { -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ NBTBase nbtbase = (NBTBase) dynamic.getValue(); -+ -+ if (nbtbase instanceof NBTTagCompound) { -+ return (NBTTagCompound)nbtbase; -+ } else { -+ RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); -+ } -+ return null; -+ } -+ // Paper end -+ - private Dynamic a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops) { - Map map = Maps.newHashMap(); - -@@ -213,9 +233,9 @@ public class RegionFileSection implements AutoCloseable { - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (!this.d.isEmpty()) { - for (int i = 0; i < 16; ++i) { -- long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); // Paper - conflict here to avoid obfhelpers - -- if (this.d.contains(j)) { -+ if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers - this.d(chunkcoordintpair); - return; - } -@@ -224,7 +244,26 @@ public class RegionFileSection implements AutoCloseable { - - } - -- public void close() throws IOException { -- this.b.close(); -+// Paper start - nuke IOWorker -+// public void close() throws IOException { -+// this.b.close(); -+// } -+// Paper end -+ -+ // Paper start - get data function -+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { -+ // Note: Copied from above -+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) -+ if (!this.d.isEmpty()) { -+ for (int i = 0; i < 16; ++i) { -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ -+ if (this.d.contains(j)) { -+ return this.getDataInternal(chunkcoordintpair); -+ } -+ } -+ } -+ return null; - } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d46c513512c25e55ccdb0be16524f19444c358c5..6aaf868cf3213e1935080c64c652c3055cb58e0c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -563,22 +563,23 @@ public class CraftWorld implements World { - return true; - } - -- net.minecraft.world.level.chunk.storage.RegionFile file; -- try { -- file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -- } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method - -- ChunkStatus status = file.getStatusIfCached(x, z); -- if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ // Paper start - async io -+ if (status == ChunkStatus.EMPTY) { -+ // does not exist on disk - return false; - } - -+ if (status == null) { // at this stage we don't know what it is on disk - IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); - if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; - } -+ } else if (status != ChunkStatus.FULL) { -+ return false; // not full status on disk -+ } -+ // Paper end - - // fall through to load - // we do this so we do not re-read the chunk data on disk -@@ -2501,6 +2502,34 @@ public class CraftWorld implements World { - public DragonBattle getEnderDragonBattle() { - return (getHandle().getDragonBattle() == null) ? null : new CraftDragonBattle(getHandle().getDragonBattle()); - } -+ // Paper start -+ @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { -+ if (Bukkit.isPrimaryThread()) { -+ net.minecraft.world.level.chunk.Chunk immediate = this.world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); -+ } -+ } else { -+ CompletableFuture future = new CompletableFuture(); -+ world.getMinecraftServer().execute(() -> { -+ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { -+ if (err != null) { -+ future.completeExceptionally(err); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { -+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -+ }, net.minecraft.server.MinecraftServer.getServer()); -+ } -+ // Paper end - - // Spigot start - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 93bbf63e9d38f32d5528c7693633d4b65655bb9d..266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -12,6 +12,9 @@ import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityAreaEffectCloud; -@@ -144,6 +147,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartHopper; - import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; -@@ -508,6 +512,28 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - entity.setHeadRotation(yaw); - } - -+ @Override// Paper start -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -+ PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -+ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); -+ } -+ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index abaefa0b71104756e4b458abefe13d179e7a1724..58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -6,6 +6,7 @@ import java.lang.management.ThreadInfo; - import java.util.logging.Level; - import java.util.logging.Logger; - import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - -@@ -116,6 +117,7 @@ public class WatchdogThread extends Thread - // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper -+ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch b/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch deleted file mode 100644 index 797e054aa8f9..000000000000 --- a/Spigot-Server-Patches/0369-Use-getChunkIfLoadedImmediately-in-places.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 8 Jul 2019 00:13:36 -0700 -Subject: [PATCH] Use getChunkIfLoadedImmediately in places - -This prevents us from hitting chunk loads for chunks at or less-than -ticket level 33 (yes getChunkIfLoaded will actually perform a chunk -load in that case). - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index bb6c59237702bf82d2c344c864f233c606fd429f..96723cac5723ea97780dd3b8697c4ba598788afc 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -207,7 +207,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI -- return this.chunkProvider.getChunkAt(x, z, false); -+ return this.chunkProvider.getChunkAtIfLoadedImmediately(x, z); // Paper - } - - // Paper start - Asynchronous IO -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index fa0b7edf42243d53d9dc897903b9b9e902b33cf7..eee5b3e4645ae41f63aba8898c58f43402d31b73 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1244,7 +1244,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - speed = player.abilities.walkSpeed * 10f; - } - // Paper start - Prevent moving into unloaded chunks -- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately - this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); - return; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 15da3511a9e57c320f4cf409852bee07109095bc..b620d7e0d824c8d0758a66a8fbe872c3e45103d2 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -164,6 +164,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return (CraftServer) Bukkit.getServer(); - } - -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return ((WorldServer)this).getChunkIfLoaded(x, z) != null; -+ } -+ // Paper end -+ - public ResourceKey getTypeKey() { - return typeKey; - } -@@ -1062,14 +1069,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public boolean p(BlockPosition blockposition) { -- return isOutsideWorld(blockposition) ? false : this.getChunkProvider().b(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - } - - public boolean a(BlockPosition blockposition, Entity entity, EnumDirection enumdirection) { - if (isOutsideWorld(blockposition)) { - return false; - } else { -- IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity, enumdirection); - } -@@ -1190,7 +1197,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.a(i1, j1); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 58d22363124a9343188d8c19476e5a92f2f0b80b..53d0541aba207b5eaea2e49edbb56df918d30333 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -140,9 +140,10 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) -+ Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ if ( chunk != null ) - { -- activateChunkEntities( world.getChunkAt( i1, j1 ) ); -+ activateChunkEntities( chunk ); - } - } - } diff --git a/Spigot-Server-Patches/0370-Reduce-sync-loads.patch b/Spigot-Server-Patches/0370-Reduce-sync-loads.patch deleted file mode 100644 index 5bdc3d95e4b4..000000000000 --- a/Spigot-Server-Patches/0370-Reduce-sync-loads.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 19 Jul 2019 03:29:14 -0700 -Subject: [PATCH] Reduce sync loads - -This reduces calls to getChunkAt which would load chunks. - -This patch also adds a tool to find calls which are doing this, however -it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true - -To get a debug log for sync loads, the command is /paper syncloadinfo - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index f657e9b6bb3d24a6c77ef584711a003d1eea0341..eb1e86e8bb0f421e3686ffa02a4015a588107863 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -1,6 +1,7 @@ - package com.destroystokyo.paper; - - import com.destroystokyo.paper.io.chunk.ChunkTaskManager; -+import com.destroystokyo.paper.io.SyncLoadFinder; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -8,6 +9,10 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; -@@ -29,6 +34,9 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.entity.Player; - - import java.io.File; -+import java.io.FileOutputStream; -+import java.io.PrintStream; -+import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; - import java.util.ArrayList; -@@ -44,7 +52,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -162,6 +170,9 @@ public class PaperCommand extends Command { - case "chunkinfo": - doChunkInfo(sender, args); - break; -+ case "syncloadinfo": -+ this.doSyncLoadInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -179,6 +190,40 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doSyncLoadInfo(CommandSender sender, String[] args) { -+ if (!SyncLoadFinder.ENABLED) { -+ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -+ return; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ file.getParentFile().mkdirs(); -+ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); -+ -+ -+ try { -+ final JsonObject data = SyncLoadFinder.serialize(); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try ( -+ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") -+ ) { -+ out.print(fileData); -+ } -+ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); -+ } catch (Throwable thr) { -+ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); -+ thr.printStackTrace(); -+ } -+ } -+ - private void doChunkInfo(CommandSender sender, String[] args) { - List worlds; - if (args.length < 2 || args[1].equals("*")) { -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d381f91cf105bfc01846ada90da8971a3618e784 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -0,0 +1,171 @@ -+package com.destroystokyo.paper.io; -+ -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+ -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Map; -+import java.util.WeakHashMap; -+import net.minecraft.world.level.World; -+ -+public class SyncLoadFinder { -+ -+ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); -+ -+ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); -+ -+ private static final class SyncLoadInformation { -+ -+ public int times; -+ -+ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); -+ } -+ -+ public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { -+ if (!ENABLED) { -+ return; -+ } -+ -+ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); -+ -+ SYNC_LOADS.compute(world, (final World keyInMap, Object2ObjectOpenHashMap map) -> { -+ if (map == null) { -+ map = new Object2ObjectOpenHashMap<>(); -+ } -+ -+ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { -+ if (valueInMap == null) { -+ valueInMap = new SyncLoadInformation(); -+ } -+ -+ ++valueInMap.times; -+ -+ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { -+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); -+ }); -+ -+ return valueInMap; -+ }); -+ -+ return map; -+ }); -+ } -+ -+ public static JsonObject serialize() { -+ final JsonObject ret = new JsonObject(); -+ -+ final JsonArray worldsData = new JsonArray(); -+ -+ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { -+ final World world = entry.getKey(); -+ -+ final JsonObject worldData = new JsonObject(); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ -+ final List> data = new ArrayList<>(); -+ -+ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { -+ data.add(new Pair<>(stacktrace, times)); -+ }); -+ -+ data.sort((Pair pair1, Pair pair2) -> { -+ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order -+ }); -+ -+ final JsonArray stacktraces = new JsonArray(); -+ -+ for (Pair pair : data) { -+ final JsonObject stacktrace = new JsonObject(); -+ -+ stacktrace.addProperty("times", pair.getSecond().times); -+ -+ final JsonArray traces = new JsonArray(); -+ -+ for (StackTraceElement element : pair.getFirst().stacktrace) { -+ traces.add(String.valueOf(element)); -+ } -+ -+ stacktrace.add("stacktrace", traces); -+ -+ final JsonArray coordinates = new JsonArray(); -+ -+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { -+ final long key = coordinate.getLongKey(); -+ final int times = coordinate.getIntValue(); -+ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); -+ } -+ -+ stacktrace.add("coordinates", coordinates); -+ -+ stacktraces.add(stacktrace); -+ } -+ -+ -+ worldData.add("stacktraces", stacktraces); -+ worldsData.add(worldData); -+ } -+ -+ ret.add("worlds", worldsData); -+ -+ return ret; -+ } -+ -+ static final class ThrowableWithEquals { -+ -+ private final StackTraceElement[] stacktrace; -+ private final int hash; -+ -+ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { -+ this.stacktrace = stacktrace; -+ this.hash = ThrowableWithEquals.hash(stacktrace); -+ } -+ -+ public static int hash(final StackTraceElement[] stacktrace) { -+ int hash = 0; -+ -+ for (int i = 0; i < stacktrace.length; ++i) { -+ hash *= 31; -+ hash += stacktrace[i].hashCode(); -+ } -+ -+ return hash; -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object obj) { -+ if (obj == null || obj.getClass() != this.getClass()) { -+ return false; -+ } -+ -+ final ThrowableWithEquals other = (ThrowableWithEquals)obj; -+ final StackTraceElement[] otherStackTrace = other.stacktrace; -+ -+ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { -+ return false; -+ } -+ -+ if (this == obj) { -+ return true; -+ } -+ -+ for (int i = 0; i < this.stacktrace.length; ++i) { -+ if (!this.stacktrace[i].equals(otherStackTrace[i])) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 1e74299bb3a368dcbc813408804d25cf58a75b0b..662d7f418e8acc9503ebf43e09410e7bd50f6bb3 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -494,6 +494,7 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.world, x, z); // Paper - sync load info - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 96723cac5723ea97780dd3b8697c4ba598788afc..02a64a132502fff19a41d4fa5ffafd61992865a4 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -282,6 +282,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }; - public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; - // Paper end -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return this.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; -+ } -+ // Paper end - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index b620d7e0d824c8d0758a66a8fbe872c3e45103d2..6781b25cc8e15be2556bb1bb8dc8c18c106b40ec 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1130,7 +1130,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 <= j; ++i1) { - for (int j1 = k; j1 <= l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entity, axisalignedbb, list, predicate); -@@ -1151,7 +1151,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = this.getChunkProvider().getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entitytypes, axisalignedbb, list, predicate); -@@ -1174,7 +1174,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); diff --git a/Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch b/Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch deleted file mode 100644 index 4af6ed58d8e4..000000000000 --- a/Spigot-Server-Patches/0371-Implement-alternative-item-despawn-rate.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 3 Jun 2019 02:02:39 -0400 -Subject: [PATCH] Implement alternative item-despawn-rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1ee2cced100626e48eb36ee14f84b9257c79a2f8..b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1,10 +1,15 @@ - package com.destroystokyo.paper; - - import java.util.Arrays; -+import java.util.EnumMap; -+import java.util.HashMap; - import java.util.List; -+import java.util.Map; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -512,4 +517,52 @@ public class PaperWorldConfig { - private void disableRelativeProjectileVelocity() { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); - } -+ -+ public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; -+ private void altItemDespawnRate() { -+ String path = "alt-item-despawn-rate"; -+ -+ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); -+ -+ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); -+ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); -+ for (Material key : altItemDespawnRateMapDefault.keySet()) { -+ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); -+ } -+ -+ Map rawMap = new HashMap<>(); -+ try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); -+ if (mapSection == null) { -+ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); -+ } -+ for (String key : mapSection.getKeys(false)) { -+ int val = mapSection.getInt(key); -+ rawMap.put(key, val); -+ } -+ } -+ catch (Exception e) { -+ logError("alt-item-despawn-rate was malformatted"); -+ altItemDespawnRateEnabled = false; -+ } -+ -+ altItemDespawnRateMap = new EnumMap<>(Material.class); -+ if (!altItemDespawnRateEnabled) { -+ return; -+ } -+ -+ for(String key : rawMap.keySet()) { -+ try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); -+ } catch (Exception e) { -+ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); -+ } -+ } -+ if(altItemDespawnRateEnabled) { -+ for(Material key : altItemDespawnRateMap.keySet()) { -+ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 02e4d6891adc902f73ed349f15dae3a429bd283a..0b2e6e72a85e05f239d56afb6785c91da5b25d55 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -33,6 +33,7 @@ import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -+import org.bukkit.Material; // Paper - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -@@ -161,7 +162,7 @@ public class EntityItem extends Entity { - } - } - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -185,7 +186,7 @@ public class EntityItem extends Entity { - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -535,9 +536,16 @@ public class EntityItem extends Entity { - - public void s() { - this.o(); -- this.age = world.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper - } - -+ // Paper start -+ public int getDespawnRate(){ -+ Material material = this.getItemStack().getBukkitStack().getType(); -+ return world.paperConfig.altItemDespawnRateMap.getOrDefault(material, world.spigotConfig.itemDespawnRate); -+ } -+ // Paper end -+ - @Override - public Packet P() { - return new PacketPlayOutSpawnEntity(this); diff --git a/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch deleted file mode 100644 index be87abbafa5a..000000000000 --- a/Spigot-Server-Patches/0372-Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Sauve -Date: Sun, 14 Jul 2019 21:05:03 -0500 -Subject: [PATCH] Do less work if we have a custom Bukkit generator - -If the Bukkit generator already has a spawn, use it immediately instead -of spending time generating one that we won't use - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ef13e310a8a452d2ba1d9c8bac72f9baf2693de0..a118187e86238fd4019ba5c25269d5ee80fc56f2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -630,12 +630,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return biomebase.b().b(); -- }, random); -- ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper start - moved down - // CraftBukkit start - if (worldserver.generator != null) { - Random rand = new Random(worldserver.getSeed()); -@@ -651,6 +646,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return biomebase.b().b(); -+ }, random); -+ ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper end - - if (blockposition == null) { - MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/Spigot-Server-Patches/0373-Fix-MC-158900.patch b/Spigot-Server-Patches/0373-Fix-MC-158900.patch deleted file mode 100644 index 023ce89b9168..000000000000 --- a/Spigot-Server-Patches/0373-Fix-MC-158900.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 13 Aug 2019 06:35:17 -0700 -Subject: [PATCH] Fix MC-158900 - -The problem was we were checking isExpired() on the entry, but if it -was expired at that point, then it would be null. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ec4e84f6275f8b305fb5a64f9c0cff24729d73ec..553b14f7167673938d1bc83d79c730692a4ef105 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -607,8 +607,10 @@ public abstract class PlayerList { - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -- if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { -- GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); -+ // Paper start - Fix MC-158900 -+ GameProfileBanEntry gameprofilebanentry; -+ if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { -+ // Paper end - - chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); - if (gameprofilebanentry.getExpires() != null) { diff --git a/Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch b/Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch deleted file mode 100644 index 2fa303ef925f..000000000000 --- a/Spigot-Server-Patches/0374-implement-optional-per-player-mob-spawns.patch +++ /dev/null @@ -1,848 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 01:27:58 +0500 -Subject: [PATCH] implement optional per player mob spawns - - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 2da28784ee427001b1137c859f0b4c350abd3110..c5f594d45012016d99b83a778a2b9d20a7c086ac 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -57,6 +57,7 @@ public class WorldTimingsHandler { - - - public final Timing miscMobSpawning; -+ public final Timing playerMobDistanceMapUpdate; - - public final Timing poiUnload; - public final Timing chunkUnload; -@@ -122,6 +123,7 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); - - poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); - chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b913cd2dd0cd1b369b3f7b5a9d8b1be73f6d7920..6aec502eb529d4090306e12e837117cde7e114eb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -565,4 +565,9 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean perPlayerMobSpawns = false; -+ private void perPlayerMobSpawns() { -+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6124b54d99adbb2a5bb9bb09dfd02522a67ab3ba ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -@@ -0,0 +1,252 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.util.List; -+import java.util.Map; -+import net.minecraft.core.SectionPosition; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.spigotmc.AsyncCatcher; -+import java.util.HashMap; -+ -+/** @author Spottedleaf */ -+public final class PlayerMobDistanceMap { -+ -+ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); -+ -+ private final Map players = new HashMap<>(); -+ // we use linked for better iteration. -+ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); -+ private int viewDistance; -+ -+ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkCoordIntPair chunkPos) { -+ return this.getPlayersInRange(chunkPos.x, chunkPos.z); -+ } -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { -+ return this.playerMap.getOrDefault(ChunkCoordIntPair.pair(chunkX, chunkZ), EMPTY_SET); -+ } -+ -+ public void update(final List currentPlayers, final int newViewDistance) { -+ AsyncCatcher.catchOp("Distance map update"); -+ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); -+ -+ final int oldViewDistance = this.viewDistance; -+ this.viewDistance = newViewDistance; -+ -+ for (final EntityPlayer player : currentPlayers) { -+ if (player.isSpectator() || !player.affectsSpawning) { -+ continue; // will be left in 'gone' (or not added at all) -+ } -+ -+ gone.remove(player); -+ -+ final SectionPosition newPosition = player.getPlayerMapSection(); -+ final SectionPosition oldPosition = this.players.put(player, newPosition); -+ -+ if (oldPosition == null) { -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } else { -+ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); -+ } -+ //this.validatePlayer(player, newViewDistance); // debug only -+ } -+ -+ for (final EntityPlayer player : gone) { -+ final SectionPosition oldPosition = this.players.remove(player); -+ if (oldPosition != null) { -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ } -+ } -+ } -+ -+ // expensive op, only for debug -+ private void validatePlayer(final EntityPlayer player, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ -+ final SectionPosition currPosition = player.getPlayerMapSection(); -+ -+ final int centerX = currPosition.getX(); -+ final int centerZ = currPosition.getZ(); -+ -+ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { -+ final long key = entry.getLongKey(); -+ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.set.contains(player)) { -+ ++entiesGot; -+ -+ final int chunkX = ChunkCoordIntPair.getX(key); -+ final int chunkZ = ChunkCoordIntPair.getZ(key); -+ -+ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addPlayerTo(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ if (players == null) { -+ return player.cachedSingleMobDistanceMap; -+ } else { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); -+ } -+ }); -+ } -+ -+ private void removePlayerFrom(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map -+ }); -+ } -+ -+ private void updatePlayer(final EntityPlayer player, final SectionPosition oldPosition, final SectionPosition newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = newPosition.getX(); -+ final int toZ = newPosition.getZ(); -+ final int fromX = oldPosition.getX(); -+ final int fromZ = oldPosition.getZ(); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = Math.abs(fromX - toX); -+ final int totalZ = Math.abs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { -+ // teleported? -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ if (oldViewDistance == newViewDistance) { -+ // same view distance -+ -+ // used for relative positioning -+ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise -+ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ } else { -+ // different view distance -+ // for now :) -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } -+ } -+ -+ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.removePlayerFrom(player, x + xoff, z + zoff); -+ } -+ } -+ } -+ -+ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.addPlayerTo(player, x + xoff, z + zoff); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..4f13d3ff8391793a99f067189f854078334499c6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -@@ -0,0 +1,241 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.lang.ref.WeakReference; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public class PooledHashSets { -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet implements Iterable { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference(null); -+ -+ final ObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet() { -+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this(); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return this.set.iterator(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 662d7f418e8acc9503ebf43e09410e7bd50f6bb3..372e5268783a84effa8f9f06c3f85b182e209cb8 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -767,7 +767,22 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().enter("naturalSpawnCount"); - this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); -- SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ // Paper start - per player mob spawning -+ SpawnerCreature.d spawnercreature_d; // moved down -+ if (this.playerChunkMap.playerMobDistanceMap != null) { -+ // update distance map -+ this.world.timings.playerMobDistanceMapUpdate.startTiming(); -+ this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); -+ this.world.timings.playerMobDistanceMapUpdate.stopTiming(); -+ // re-set mob counts -+ for (EntityPlayer player : this.world.players) { -+ Arrays.fill(player.mobCounts, 0); -+ } -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true); -+ } else { -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false); -+ } -+ // Paper end - this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index a15b119b24090ffc607bfc9003d5b95f3acf3b2f..f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -94,6 +94,7 @@ import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.EnumMainHand; - import net.minecraft.world.entity.IEntityAngerable; - import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -@@ -219,6 +220,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; - // Paper end -+ // Paper start - mob spawning rework -+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length; -+ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper -+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -257,6 +263,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); -+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. -@@ -2061,6 +2068,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - } - -+ public final SectionPosition getPlayerMapSection() { return this.O(); } // Paper - OBFHELPER - public SectionPosition O() { - return this.cj; - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 46c91230ab6f12db77b453c312fa7382b76fad34..d00dc8d7933be61f1401f598e5d675f5ae5d7029 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -72,6 +72,7 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.ai.village.poi.VillagePlace; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; -@@ -129,7 +130,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; - private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER -- private int viewDistance; -+ int viewDistance; // Paper - private -> package private -+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -208,6 +210,24 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ } -+ -+ public void updatePlayerMobTypeMap(Entity entity) { -+ if (!this.world.paperConfig.perPlayerMobSpawns) { -+ return; -+ } -+ int chunkX = (int)Math.floor(entity.locX()) >> 4; -+ int chunkZ = (int)Math.floor(entity.locZ()) >> 4; -+ int index = entity.getEntityType().getEnumCreatureType().ordinal(); -+ -+ for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { -+ ++player.mobCounts[index]; -+ } -+ } -+ -+ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) { -+ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 1355c074353611669c947cb0f06c67be0ab418aa..9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -426,6 +426,7 @@ public class EntityTypes { - return this.bl; - } - -+ public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER - public EnumCreatureType e() { - return this.bg; - } -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index d30a3de84dc75a57680052904337af02b6b80636..24771c3522ea74ac12058591137eafc21adf3762 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -16,6 +16,7 @@ import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -62,6 +63,11 @@ public final class SpawnerCreature { - }); - - public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { -+ // Paper start - add countMobs parameter -+ return countMobs(i, iterable, spawnercreature_b, false); -+ } -+ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { -+ // Paper end - add countMobs parameter - SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); - Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); - Iterator iterator = iterable.iterator(); -@@ -99,6 +105,11 @@ public final class SpawnerCreature { - } - - object2intopenhashmap.addTo(enumcreaturetype, 1); -+ // Paper start -+ if (countMobs) { -+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); -+ } -+ // Paper end - }); - } - } -@@ -157,13 +168,31 @@ public final class SpawnerCreature { - continue; - } - -- if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) { -+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype); -+ int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b; -+ int difference = k1 - currEntityCount; -+ -+ if (worldserver.paperConfig.perPlayerMobSpawns) { -+ int minDiff = Integer.MAX_VALUE; -+ for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { -+ minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); -+ } -+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; -+ } -+ // Paper end -+ -+ // Paper start - per player mob spawning -+ if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && difference > 0) { - // CraftBukkit end -- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { -+ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { - return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess); - }, (entityinsentient, ichunkaccess) -> { - spawnercreature_d.a(entityinsentient, ichunkaccess); -- }); -+ }, -+ difference, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null); -+ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); -+ // Paper end - per player mob spawning - } - } - -@@ -172,22 +201,34 @@ public final class SpawnerCreature { - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add parameters and int ret type -+ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add parameters and int ret type - BlockPosition blockposition = getRandomPosition(worldserver, chunk); - - if (blockposition.getY() >= 1) { -- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a); -+ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); - } -+ return 0; // Paper - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add maxSpawns parameter and return spawned mobs -+ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add maxSpawns parameter and return spawned mobs - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); - IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn -+ int j = 0; // Paper - moved up - - if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); -- int j = 0; -+ // Paper - moved up - int k = 0; - - while (k < 3) { -@@ -227,7 +268,7 @@ public final class SpawnerCreature { - // Paper start - Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); - if (doSpawning == null) { -- return; -+ return j; // Paper - } - if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { - // Paper end -@@ -235,7 +276,7 @@ public final class SpawnerCreature { - - - if (entityinsentient == null) { -- return; -+ return j; // Paper - } - - entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); -@@ -244,13 +285,18 @@ public final class SpawnerCreature { - // CraftBukkit start - worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); - if (!entityinsentient.dead) { -- ++j; -+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned - ++k1; - spawnercreature_a.run(entityinsentient, ichunkaccess); -+ // Paper start -+ if (trackEntity != null) { -+ trackEntity.accept(entityinsentient); -+ } -+ // Paper end - } - // CraftBukkit end -- if (j >= entityinsentient.getMaxSpawnGroup()) { -- return; -+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper -+ return j; // Paper - } - - if (entityinsentient.c(k1)) { -@@ -272,6 +318,7 @@ public final class SpawnerCreature { - } - - } -+ return j; // Paper - } - - private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -@@ -512,8 +559,8 @@ public final class SpawnerCreature { - - public static class d { - -- private final int a; -- private final Object2IntOpenHashMap b; -+ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER -+ private final Object2IntOpenHashMap b; final Object2IntMap getEntityCountsByType() { return this.b; } // Paper - OBFHELPER - private final SpawnerCreatureProbabilities c; - private final Object2IntMap d; - @Nullable -@@ -574,7 +621,7 @@ public final class SpawnerCreature { - - // CraftBukkit start - private boolean a(EnumCreatureType enumcreaturetype, int limit) { -- int i = limit * this.a / SpawnerCreature.b; -+ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method - // CraftBukkit end - - return this.b.getInt(enumcreaturetype) < i; diff --git a/Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch b/Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch deleted file mode 100644 index 0f8ff9bd80f7..000000000000 --- a/Spigot-Server-Patches/0375-Prevent-consuming-the-wrong-itemstack.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 19:42:35 +0500 -Subject: [PATCH] Prevent consuming the wrong itemstack - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index c98562980ca02c85f2f777a31983c164f2dd5e1e..06119a87338d48128ddd71fe8396e10b6e83744a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3201,10 +3201,13 @@ public abstract class EntityLiving extends Entity { - this.datawatcher.set(EntityLiving.ag, (byte) j); - } - -- public void c(EnumHand enumhand) { -+ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter -+ public void c(EnumHand enumhand) { this.updateActiveItem(enumhand, false); } -+ public void updateActiveItem(EnumHand enumhand, boolean forceUpdate) { -+ // Paper end - ItemStack itemstack = this.b(enumhand); - -- if (!itemstack.isEmpty() && !this.isHandRaised()) { -+ if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; - this.bd = itemstack.k(); - if (!this.world.isClientSide) { -@@ -3282,6 +3285,7 @@ public abstract class EntityLiving extends Entity { - this.releaseActiveItem(); - } else { - if (!this.activeItem.isEmpty() && this.isHandRaised()) { -+ this.updateActiveItem(this.getRaisedHand(), true); // Paper - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -@@ -3316,8 +3320,8 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -- // Paper start - if the replacement is anything but the default, update the client inventory -- if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ // Paper start -+ if (this instanceof EntityPlayer) { - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - } - // Paper end diff --git a/Spigot-Server-Patches/0376-Generator-Settings.patch b/Spigot-Server-Patches/0376-Generator-Settings.patch deleted file mode 100644 index 35a2520f5f15..000000000000 --- a/Spigot-Server-Patches/0376-Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6aec502eb529d4090306e12e837117cde7e114eb..290e49cf0077909ad7ab8127c01ef93cf7b70b51 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -570,4 +570,9 @@ public class PaperWorldConfig { - private void perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index e570dc58efa56bd0aa5ada5575b4054ee38d505e..cdf612d7553a8f4aaebb5e0e66bd2a47a280457a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -25,6 +25,18 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof Chunk) { -+ return ((Chunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 9b308a10554b037ede0c455fbd3e906021218ddc..7bfac4e852c4a6697435647dab173913df6034e9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -64,7 +64,7 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -- private final World world; // Paper - Anti-Xray - Add world -+ final World world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index b137d65953fe1e44709e9a6dab3a4533df644d06..700b32322e8d0fbb8ec2824e50a340be16b48f81 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -408,8 +408,8 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - int i = ichunkaccess.getPos().d(); - int j = ichunkaccess.getPos().e(); - GeneratorSettingBase generatorsettingbase = (GeneratorSettingBase) this.h.get(); -- int k = generatorsettingbase.f(); -- int l = this.x - 1 - generatorsettingbase.e(); -+ int k = generatorsettingbase.f(); final int floorHeight = k; // Paper -+ int l = this.x - 1 - generatorsettingbase.e(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.x; - boolean flag2 = k + 4 >= 0 && k < this.x; -@@ -423,7 +423,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } -@@ -431,7 +431,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } diff --git a/Spigot-Server-Patches/0377-Fix-MC-161754.patch b/Spigot-Server-Patches/0377-Fix-MC-161754.patch deleted file mode 100644 index 8ef2ece0bd1f..000000000000 --- a/Spigot-Server-Patches/0377-Fix-MC-161754.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 24 Sep 2019 16:03:00 -0700 -Subject: [PATCH] Fix MC-161754 - -Fixes https://github.com/PaperMC/Paper/issues/2580 - -We can use an entity valid check since this method is invoked for -each inventory iteraction (thanks to CB) and on player tick (vanilla). - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -index ecabe8e52865b71b6f89d09850b37741e7e79b50..ea64ef313a8378fa7dee086e137e1e5f43376804 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -@@ -85,7 +85,7 @@ public class ContainerHorse extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -- return this.c.a(entityhuman) && this.d.isAlive() && this.d.g((Entity) entityhuman) < 8.0F; -+ return this.c.a(entityhuman) && (this.d.isAlive() && this.d.valid) && this.d.g((Entity) entityhuman) < 8.0F; // Paper - Fix MC-161754 - } - - @Override diff --git a/Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch b/Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch deleted file mode 100644 index 0b09feb060a5..000000000000 --- a/Spigot-Server-Patches/0378-Performance-improvement-for-Chunk.getEntities.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: wea_ondara -Date: Thu, 10 Oct 2019 11:29:42 +0200 -Subject: [PATCH] Performance improvement for Chunk.getEntities - -This patch aims to reduce performance cost used by collecting the -entities of a chunk. Previously the entitySlices were copied into an -extra array with List.toArray() with is a costly and unneccessary -operation. This patch will reduce the load of plugins which for example -implement custom moblimits and depend on Chunk.getEntities(). - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index c36f55f178166eb099cc5c64784be5a9f4750199..8ade81a693286cdf65f8c0eeca2121a217c90350 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -117,14 +117,14 @@ public class CraftChunk implements Chunk { - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { -- -- for (Object obj : chunk.entitySlices[i].toArray()) { -- if (!(obj instanceof net.minecraft.world.entity.Entity)) { -+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) -+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { -+ if (entity == null) { - continue; - } -- -- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); -+ entities[index++] = entity.getBukkitEntity(); - } -+ // Paper end - } - - return entities; diff --git a/Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch deleted file mode 100644 index 225102e634df..000000000000 --- a/Spigot-Server-Patches/0379-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterErwin -Date: Wed, 30 Oct 2019 16:57:54 +0100 -Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and - can not face UP or DOWN - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6aaf868cf3213e1935080c64c652c3055cb58e0c..fcad64fcfc22af227be19741b634b773aca7a98d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1886,7 +1886,12 @@ public class CraftWorld implements World { - height = 9; - } - -- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames -+ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) -+ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} -+ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; -+ // Paper end - final BlockPosition pos = new BlockPosition(x, y, z); - for (BlockFace dir : faces) { - IBlockData nmsBlock = world.getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); diff --git a/Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch b/Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch deleted file mode 100644 index 5b782b0348b1..000000000000 --- a/Spigot-Server-Patches/0380-Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:34 -0500 -Subject: [PATCH] Expose the internal current tick - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7b2326922415ae55dd930654defb09f736c1f781..3cb67cfe8b69da722709ebdde250add88c19fee3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2365,5 +2365,10 @@ public final class CraftServer implements Server { - } - return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); - } -+ -+ @Override -+ public int getCurrentTick() { -+ return net.minecraft.server.MinecraftServer.currentTick; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch deleted file mode 100644 index 5535fda04ec8..000000000000 --- a/Spigot-Server-Patches/0381-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:51:43 -0500 -Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f0c3bfb0e641b9f1a22fb6873ab3645be6e481c4..a0c426afaa7a18f7596d56699f02dcd665f7aa9d 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1073,6 +1073,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - -+ setSneaking(false); // Paper - fix MC-10657 -+ - // CraftBukkit start - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); - this.world.getServer().getPluginManager().callEvent(changeEvent); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 553b14f7167673938d1bc83d79c730692a4ef105..9af1d81475d2def60a682ed23e88f1afbbc4c7e6 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -846,6 +846,8 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); - } - -+ entityplayer.setSneaking(false); // Paper - fix MC-10657 -+ - // Fire advancement trigger - entityplayer.triggerDimensionAdvancements(((CraftWorld) fromWorld).getHandle()); - diff --git a/Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch b/Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch deleted file mode 100644 index 7adaa55dec57..000000000000 --- a/Spigot-Server-Patches/0382-Add-option-to-disable-pillager-patrols.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:46:15 -0500 -Subject: [PATCH] Add option to disable pillager patrols - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 290e49cf0077909ad7ab8127c01ef93cf7b70b51..e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -575,4 +575,9 @@ public class PaperWorldConfig { - private void generatorSettings() { - generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); - } -+ -+ public boolean disablePillagerPatrols = false; -+ private void pillagerSettings() { -+ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index 04a1af9c6742f7aa944dec80e75ff8a4ca4bf57f..cba98adb7f2711fb97c7e4120d962f46a59682e7 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -26,6 +26,7 @@ public class MobSpawnerPatrol implements MobSpawner { - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { diff --git a/Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch deleted file mode 100644 index b2d5dc358794..000000000000 --- a/Spigot-Server-Patches/0383-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lukasz Derlatka -Date: Mon, 11 Nov 2019 16:08:13 +0100 -Subject: [PATCH] Fix AssertionError when player hand set to empty type - -Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent -Fixes GH-2718 - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index eee5b3e4645ae41f63aba8898c58f43402d31b73..cfdfa3ea95a525af25c7aa830f8e31d5afe56d65 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1707,6 +1707,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 - return; - } -+ // Paper start -+ itemstack = this.player.getItemInHand(enumhand); -+ if (itemstack.isEmpty()) return; -+ // Paper end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand); - - if (enuminteractionresult.b()) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 06119a87338d48128ddd71fe8396e10b6e83744a..ec31585099c8376f61496f02f9454cb600104918 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2156,6 +2156,7 @@ public abstract class EntityLiving extends Entity { - return predicate.test(this.getItemInMainHand().getItem()) || predicate.test(this.getItemInOffHand().getItem()); - } - -+ public final ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER - public ItemStack b(EnumHand enumhand) { - if (enumhand == EnumHand.MAIN_HAND) { - return this.getEquipment(EnumItemSlot.MAINHAND); diff --git a/Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch b/Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch deleted file mode 100644 index ceeb9bcd0e4c..000000000000 --- a/Spigot-Server-Patches/0384-PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:11:03 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/net/minecraft/world/InteractionResultWrapper.java b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -index dd17c111670e637b574f5c7f38d27848900ce194..8cecc3d909a51b1892b4a299a5e6ec3518db9b39 100644 ---- a/src/main/java/net/minecraft/world/InteractionResultWrapper.java -+++ b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -@@ -10,6 +10,7 @@ public class InteractionResultWrapper { - this.b = t0; - } - -+ public EnumInteractionResult getResult() { return this.a(); } // Paper - OBFHELPER - public EnumInteractionResult a() { - return this.a; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEgg.java b/src/main/java/net/minecraft/world/item/ItemEgg.java -index 2083ab6e0dc7e48d409a5ee33e712e34abd6f6bf..4b1a6ee784da4595931396a905f1358b7a13f3dd 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemEgg.java -@@ -25,21 +25,35 @@ public class ItemEgg extends Item { - - entityegg.setItem(itemstack); - entityegg.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- // CraftBukkit start -- if (!world.addEntity(entityegg)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityegg)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } -- // CraftBukkit end -+ // Paper end -+ -+ - } - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.RANDOM.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -index 5349282b9a5b43c4c3539e1677971463e2ca5a17..9896d77381e7fadf1ef2619210713e190c1445d0 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -+++ b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -@@ -25,22 +25,37 @@ public class ItemEnderPearl extends Item { - - entityenderpearl.setItem(itemstack); - entityenderpearl.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (!world.addEntity(entityenderpearl)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityenderpearl)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ entityhuman.getCooldownTracker().setCooldown(this, 20); -+ } else { -+ // Paper end - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } - } - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -- entityhuman.getCooldownTracker().setCooldown(this, 20); -- // CraftBukkit end -- -- entityhuman.b(StatisticList.ITEM_USED.b(this)); -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -- } -+ // Paper start - moved up -+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -+// entityhuman.getCooldownTracker().setCooldown(this, 20); -+// // CraftBukkit end -+// -+// entityhuman.b(StatisticList.ITEM_USED.b(this)); -+// if (!entityhuman.abilities.canInstantlyBuild) { -+// itemstack.subtract(1); -+// } -+ // Paper end - moved up - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemExpBottle.java b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -index 3f41fe5bf1a0cc283d6a72824779026fdad75708..cf36ec4769dc316e3ed16262043cb78cbba340ab 100644 ---- a/src/main/java/net/minecraft/world/item/ItemExpBottle.java -+++ b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -@@ -1,10 +1,13 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.level.World; -@@ -24,19 +27,38 @@ public class ItemExpBottle extends Item { - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { - ItemStack itemstack = entityhuman.b(enumhand); - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down - if (!world.isClientSide) { - EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman); - - entitythrownexpbottle.setItem(itemstack); - entitythrownexpbottle.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.7F, 1.0F); -- world.addEntity(entitythrownexpbottle); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitythrownexpbottle)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 79e9be800385b94c4493bd8970620d76bfbd65ae..e7f958d137257da912ce9b83db017b4423959943 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import java.util.Arrays; - import java.util.Comparator; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -@@ -29,8 +30,12 @@ public class ItemFireworks extends Item { - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); - entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - -- world.addEntity(entityfireworks); -- itemstack.subtract(1); -+ // Paper start - PlayerLaunchProjectileEvent -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) itemactioncontext.getEntity().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (!event.callEvent() || !world.addEntity(entityfireworks)) return EnumInteractionResult.PASS; -+ if (event.shouldConsume() && !itemactioncontext.getEntity().abilities.canInstantlyBuild) itemstack.subtract(1); -+ else if (itemactioncontext.getEntity() instanceof EntityPlayer) ((EntityPlayer) itemactioncontext.getEntity()).getBukkitEntity().updateInventory(); -+ // Paper end - } - - return EnumInteractionResult.a(world.isClientSide); -diff --git a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -index a75f374f0639e8143772aa863666afe25d2020cf..0e073a8c23d24afb8b0198a9cfd8dc7d0b9d0a6b 100644 ---- a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -15,7 +16,12 @@ public class ItemLingeringPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -index d050243946ad7023d5dd3958d7056cddcaf185a4..27c61fc4e61b0d76565ca6893514b3c73247c954 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -@@ -1,7 +1,9 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityPotion; -@@ -22,13 +24,31 @@ public class ItemPotionThrowable extends ItemPotion { - - entitypotion.setItem(itemstack); - entitypotion.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.5F, 1.0F); -- world.addEntity(entitypotion); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitypotion)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemSnowball.java b/src/main/java/net/minecraft/world/item/ItemSnowball.java -index e5200b2a7d6d5c2d549e585ed157ec5217edae8e..8a1d59cb1ea5a8959c52272aa762ec35307246d7 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSnowball.java -+++ b/src/main/java/net/minecraft/world/item/ItemSnowball.java -@@ -26,14 +26,20 @@ public class ItemSnowball extends Item { - - entitysnowball.setItem(itemstack); - entitysnowball.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (world.addEntity(entitysnowball)) { -- if (!entityhuman.abilities.canInstantlyBuild) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitysnowball)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ // Paper end - itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { // Paper -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper - } - - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.RANDOM.nextFloat() * 0.4F + 0.8F)); -- } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -- ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else { // Paper -+ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -index 98f29fac4bf087ad15f1cc7e85b408e22ec07efd..971491a461ccb7a707c6ca1a5b7c16d8823a7a80 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -@@ -3,6 +3,7 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -15,7 +16,12 @@ public class ItemSplashPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ } -+ return wrapper; -+ // Paper end - } - } diff --git a/Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch deleted file mode 100644 index abf6eb1d92c2..000000000000 --- a/Spigot-Server-Patches/0385-Add-CraftMagicNumbers.isSupportedApiVersion.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BlackHole -Date: Sun, 15 Dec 2019 19:12:39 +0100 -Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8aa9e7796ea39c09a965750d06c3d358250f33b8..7e4cceff7ce9ffaff00caf21088fd7bc59e66933 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -375,6 +375,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.PaperVersionFetcher(); - } -+ -+ @Override -+ public boolean isSupportedApiVersion(String apiVersion) { -+ return apiVersion != null && SUPPORTED_API.contains(apiVersion); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch deleted file mode 100644 index 0188a5ae7f92..000000000000 --- a/Spigot-Server-Patches/0386-Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Mon, 13 Jan 2020 23:47:28 -0600 -Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -index 84eba4c91e8e608b84623d6c71233e2512b77a54..ce86301723d20e79f95207cce1084bac091742fe 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -@@ -46,7 +46,8 @@ public class BehaviorSleep extends Behavior { - } - } - -- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition()); -+ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a((Tag) TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED); - } diff --git a/Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch b/Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch deleted file mode 100644 index 342a7deea1c7..000000000000 --- a/Spigot-Server-Patches/0387-MC-145656-Fix-Follow-Range-Initial-Target.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 18 Dec 2019 22:21:35 -0600 -Subject: [PATCH] MC-145656 Fix Follow Range Initial Target - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e726b6213cf2e8f5b326f05c0438b8f1ee2b73c5..edda2121f8c1046478beaa77030ebb36d403b334 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -580,4 +580,9 @@ public class PaperWorldConfig { - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); - } -+ -+ public boolean entitiesTargetWithFollowRange = false; -+ private void entitiesTargetWithFollowRange() { -+ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -index 4f0a2cbdd6d42e3e4721345e21bf0ef33ec48e1e..44f21c3f7af17e9d39777a48c6715a22fc085da6 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -@@ -32,6 +32,7 @@ public class PathfinderGoalNearestAttackableTarget exten - this.b = i; - this.a(EnumSet.of(PathfinderGoal.Type.TARGET)); - this.d = (new PathfinderTargetCondition()).a(this.k()).a(predicate); -+ if (entityinsentient.world.paperConfig.entitiesTargetWithFollowRange) this.d.useFollowRange(); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -index 0de32bcf24a94efe5af922b877d4cdc3578e0cbd..e6988f7ea428f1503e3db63876b13e57f898ee30 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -@@ -4,6 +4,8 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.ai.attributes.AttributeModifiable; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - - public class PathfinderTargetCondition { - -@@ -82,7 +84,7 @@ public class PathfinderTargetCondition { - - if (this.b > 0.0D) { - double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; -- double d1 = Math.max(this.b * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper - double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); - - if (d2 > d1 * d1) { -@@ -98,4 +100,18 @@ public class PathfinderTargetCondition { - return true; - } - } -+ -+ // Paper start -+ private boolean useFollowRange = false; -+ -+ public PathfinderTargetCondition useFollowRange() { -+ this.useFollowRange = true; -+ return this; -+ } -+ -+ private double getFollowRange(EntityLiving entityliving) { -+ AttributeModifiable attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); -+ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0388-Optimize-Hoppers.patch b/Spigot-Server-Patches/0388-Optimize-Hoppers.patch deleted file mode 100644 index 14f5affd0b70..000000000000 --- a/Spigot-Server-Patches/0388-Optimize-Hoppers.patch +++ /dev/null @@ -1,517 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Apr 2016 22:09:52 -0400 -Subject: [PATCH] Optimize Hoppers - -* Removes unnecessary extra calls to .update() that are very expensive -* Lots of itemstack cloning removed. Only clone if the item is actually moved -* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. - However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. -* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory -* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration -* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) -* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -585,4 +585,13 @@ public class PaperWorldConfig { - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); - } -+ -+ public boolean cooldownHopperWhenFull = true; -+ public boolean disableHopperMoveEvents = false; -+ private void hopperOptimizations() { -+ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); -+ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); -+ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); -+ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a118187e86238fd4019ba5c25269d5ee80fc56f2..94525c8bd49334fb5aa1b113ed992e857e44ab96 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -129,6 +129,7 @@ import net.minecraft.world.level.WorldSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.WorldChunkManager; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntityHopper; - import net.minecraft.world.level.border.IWorldBorderListener; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -1362,6 +1363,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 852f9d99001b35f8c97f4445d8f605533d7f6f2f..7b1df591007b9c50bcaf4bcd30562396a9549193 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -540,11 +540,12 @@ public final class ItemStack { - return this.getItem().a(this, entityhuman, entityliving, enumhand); - } - -- public ItemStack cloneItemStack() { -- if (this.isEmpty()) { -+ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper -+ public ItemStack cloneItemStack(boolean origItem) { // Paper -+ if (!origItem && this.isEmpty()) { // Paper - return ItemStack.b; - } else { -- ItemStack itemstack = new ItemStack(this.getItem(), this.count); -+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper - - itemstack.d(this.D()); - if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 6781b25cc8e15be2556bb1bb8dc8c18c106b40ec..d1738b57efd3f5e6c51603553a773173e4b09bb5 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1162,8 +1162,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return list; - } - -- @Override -- public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { return a(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { - this.getMethodProfiler().c("getEntities"); - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -index d0943ae1f372784716195666212ff83e6ee4873e..1db7b7bfe98658d0b20800a4178556f8daaf881a 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.world.IInventory; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -@@ -17,12 +18,13 @@ public interface IHopper extends IInventory { - return IHopper.c; - } - -- @Nullable -+ //@Nullable // Paper - it's annoying - World getWorld(); -+ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper - -- double x(); -+ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER - -- double z(); -+ double z(); default double getY() { return this.z(); } // Paper - OBFHELPER - -- double A(); -+ double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 48daa039ffa8ccb7b6f3ca47bdc56394addf9254..f1e586754396439dfb70a4d63e3b8b34fb36ebf4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -77,6 +77,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void setCurrentChunk(Chunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; - } -+ static boolean IGNORE_TILE_UPDATES = false; - // Paper end - - @Nullable -@@ -155,6 +156,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - - public void update() { - if (this.world != null) { -+ if (IGNORE_TILE_UPDATES) return; // Paper - this.c = this.world.getType(this.position); - this.world.b(this.position, this); - if (!this.c.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -index 5fe715e8dbe9d925170acce6e0f18312d9f998f2..537dc52e5ff3325555ee6049bc7f277952983b76 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -@@ -196,6 +196,160 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return false; - } - -+ // Paper start - Optimize Hoppers -+ private static boolean skipPullModeEventFire = false; -+ private static boolean skipPushModeEventFire = false; -+ public static boolean skipHopperEvents = false; -+ -+ private boolean hopperPush(IInventory iinventory, EnumDirection enumdirection) { -+ skipPushModeEventFire = skipHopperEvents; -+ boolean foundItem = false; -+ for (int i = 0; i < this.getSize(); ++i) { -+ ItemStack item = this.getItem(i); -+ if (!item.isEmpty()) { -+ foundItem = true; -+ ItemStack origItemStack = item; -+ ItemStack itemstack = origItemStack; -+ -+ final int origCount = origItemStack.getCount(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ origItemStack.setCount(moved); -+ -+ // We only need to fire the event once to give protection plugins a chance to cancel this event -+ // Because nothing uses getItem, every event call should end up the same result. -+ if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ return false; -+ } -+ } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ this.setItem(i, origItemStack); -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ } -+ } -+ if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(world.spigotConfig.hopperTransfer); -+ } -+ return false; -+ } -+ -+ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) { -+ ItemStack itemstack = origItemStack; -+ final int origCount = origItemStack.getCount(); -+ final World world = ihopper.getWorld(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ itemstack.setCount(moved); -+ -+ if (!skipPullModeEventFire) { -+ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ // Drastically improve performance by returning true. -+ // No plugin could of relied on the behavior of false as the other call -+ // site for IMIE did not exhibit the same behavior -+ return true; -+ } -+ } -+ -+ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ IGNORE_TILE_UPDATES = true; -+ iinventory.setItem(i, origItemStack); -+ IGNORE_TILE_UPDATES = false; -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ -+ if (world.paperConfig.cooldownHopperWhenFull) { -+ cooldownHopper(ihopper); -+ } -+ -+ return false; -+ } -+ -+ private ItemStack callPushMoveEvent(IInventory iinventory, ItemStack itemstack) { -+ Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), -+ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPushModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(this); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static ItemStack callPullMoveEvent(IHopper hopper, IInventory iinventory, ItemStack itemstack) { -+ Inventory sourceInventory = getInventory(iinventory); -+ Inventory destination = getInventory(hopper); -+ -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, -+ // Mirror is safe as we no plugins ever use this item -+ CraftItemStack.asCraftMirror(itemstack), destination, false); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPullModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(hopper); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static Inventory getInventory(IInventory iinventory) { -+ Inventory sourceInventory;// Have to special case large chests as they work oddly -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); -+ } else if (iinventory instanceof TileEntity) { -+ sourceInventory = ((TileEntity) iinventory).getOwner(false).getInventory(); -+ } else { -+ sourceInventory = iinventory.getOwner().getInventory(); -+ } -+ return sourceInventory; -+ } -+ -+ private static void cooldownHopper(IHopper hopper) { -+ if (hopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer); -+ } else if (hopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer / 2); -+ } -+ } -+ // Paper end -+ - private boolean k() { - IInventory iinventory = this.l(); - -@@ -207,6 +361,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (this.b(iinventory, enumdirection)) { - return false; - } else { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest - for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { - ItemStack itemstack = this.getItem(i).cloneItemStack(); -@@ -244,7 +399,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- return false; -+ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - } - } -@@ -253,18 +408,54 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return iinventory instanceof IWorldInventory ? IntStream.of(((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) : IntStream.range(0, iinventory.getSize()); - } - -- private boolean b(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- ItemStack itemstack = iinventory.getItem(i); -+ private static boolean allMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } -+ return true; -+ } - -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); -+ private static boolean anyMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } -+ return true; -+ } -+ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); -+ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ -+ // Paper end -+ -+ private boolean b(IInventory iinventory, EnumDirection enumdirection) { -+ // Paper start - no streams -+ return allMatch(iinventory, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } - - private static boolean c(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- return iinventory.getItem(i).isEmpty(); -- }); -+ return allMatch(iinventory, enumdirection, IS_EMPTY_TEST); - } - - public static boolean a(IHopper ihopper) { -@@ -273,9 +464,17 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (iinventory != null) { - EnumDirection enumdirection = EnumDirection.DOWN; - -- return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { -- return a(ihopper, iinventory, i, enumdirection); -+ // Paper start - optimize hoppers and remove streams -+ skipPullModeEventFire = skipHopperEvents; -+ return !c(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { -+ // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { -+ return hopperPull(ihopper, iinventory, item, i); -+ } else { -+ return false; -+ } - }); -+ // Paper end - } else { - Iterator iterator = c(ihopper).iterator(); - -@@ -293,10 +492,11 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) { -+ private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {// Paper - method unused as logic is inlined above - ItemStack itemstack = iinventory.getItem(i); - -- if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { -+ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest - ItemStack itemstack1 = itemstack.cloneItemStack(); - // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); - // CraftBukkit start - Call event on collection of items from inventories into the hopper -@@ -333,7 +533,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot -- iinventory.setItem(i, itemstack1); -+ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - - return false; -@@ -342,7 +542,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - public static boolean a(IInventory iinventory, EntityItem entityitem) { - boolean flag = false; - // CraftBukkit start -- InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); -+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(iinventory), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation - entityitem.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; -@@ -384,6 +584,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, enumdirection); - } - -+ private static boolean canTakeItem(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { return b(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean b(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { - return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, enumdirection); - } -@@ -396,7 +597,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - boolean flag1 = iinventory1.isEmpty(); - - if (itemstack1.isEmpty()) { -+ IGNORE_TILE_UPDATES = true; // Paper - iinventory1.setItem(i, itemstack); -+ IGNORE_TILE_UPDATES = false; // Paper - itemstack = ItemStack.b; - flag = true; - } else if (a(itemstack1, itemstack)) { -@@ -447,18 +650,24 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - public static List c(IHopper ihopper) { -- return (List) ihopper.aa_().d().stream().flatMap((axisalignedbb) -> { -- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream(); -- }).collect(Collectors.toList()); -+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ World world = ihopper.getWorld(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); -+ AxisAlignedBB bb = new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(EntityItem.class, bb, Entity::isAlive); -+ // Paper end - } - - @Nullable - public static IInventory b(World world, BlockPosition blockposition) { -- return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper - } - - @Nullable -- public static IInventory a(World world, double d0, double d1, double d2) { -+ public static IInventory a(World world, double d0, double d1, double d2) { return a(world, d0, d1, d2, false); } // Paper - overload to default false -+ public static IInventory a(World world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper - Object object = null; - BlockPosition blockposition = new BlockPosition(d0, d1, d2); - if ( !world.isLoaded( blockposition ) ) return null; // Spigot -@@ -478,7 +687,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- if (object == null) { -+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper - List list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d); - - if (!list.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 1508e267a38555820e2d31f3075adca185fbd4b6..f0da819627035bed83561128a11059424d2b7e30 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -97,12 +97,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Override - public boolean isEmpty() { - this.d((EntityHuman) null); -- return this.f().stream().allMatch(ItemStack::isEmpty); -+ // Paper start -+ for (ItemStack itemStack : this.f()) { -+ if (!itemStack.isEmpty()) { -+ return false; -+ } -+ } -+ // Paper end -+ return true; - } - - @Override - public ItemStack getItem(int i) { -- this.d((EntityHuman) null); -+ if (i == 0) this.d((EntityHuman) null); // Paper - return (ItemStack) this.f().get(i); - } - diff --git a/Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch b/Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index 805bed130223..000000000000 --- a/Spigot-Server-Patches/0389-PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:42 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index a0c426afaa7a18f7596d56699f02dcd665f7aa9d..f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -822,7 +822,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.eW(); - } - // SPIGOT-5478 must be called manually now -- this.dropExperience(); -+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { - // Paper start - replace logic diff --git a/Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch b/Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch deleted file mode 100644 index 224000580dbd..000000000000 --- a/Spigot-Server-Patches/0390-Prevent-bees-loading-chunks-checking-hive-position.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Jan 2020 17:24:34 -0600 -Subject: [PATCH] Prevent bees loading chunks checking hive position - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 1554f1d1d35084c283b573b3e58e48c6747fe7d6..1ecf73f874f404f58a99316ae027f76db6b557db 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -442,6 +442,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (!this.hasHivePos()) { - return false; - } else { -+ if (world.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity != null && tileentity.getTileType() == TileEntityTypes.BEEHIVE; diff --git a/Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch deleted file mode 100644 index 34cdbbb71652..000000000000 --- a/Spigot-Server-Patches/0391-Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Nov 2016 20:28:12 -0400 -Subject: [PATCH] Don't load Chunks from Hoppers and other things - -Hoppers call this to I guess "get the primary side" of a double sided chest. - -If the double sided chest crosses chunk lines, it causes the chunk to load. -This will end up causing sync chunk loads, which will unload with Chunk GC, -only to be reloaded again the next tick. - -This of course is undesirable, so just return the loaded side as "primary" -and treat it as a single chest if the other sides are unloaded - -diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -index d51f89fed6129c4b37ef63971f8f61dc14e8032d..efa98e87eead036246348f3915b401f0f52f2242 100644 ---- a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -@@ -29,7 +29,12 @@ public class DoubleBlockFinder { - return new DoubleBlockFinder.Result.Single<>(s0); - } else { - BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata)); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ // Paper start -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockFinder.Result.Single<>(s0); -+ } -+ // Paper end - - if (iblockdata1.a(iblockdata.getBlock())) { - DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1); diff --git a/Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch b/Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch deleted file mode 100644 index 1c55da068cb5..000000000000 --- a/Spigot-Server-Patches/0392-Guard-against-serializing-mismatching-chunk-coordina.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 27 Dec 2019 09:42:26 -0800 -Subject: [PATCH] Guard against serializing mismatching chunk coordinate - -Should help if something dumb happens - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index c95fcdf47db8bfe59a83c0d28f4744b4d8540ef8..e16e046d165330326ed220c9c440a637007f3137 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -67,6 +67,13 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start - guard against serializing mismatching coordinates -+ // TODO Note: This needs to be re-checked each update -+ public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { -+ NBTTagCompound levelData = chunkData.getCompound("Level"); -+ return new ChunkCoordIntPair(levelData.getInt("xPos"), levelData.getInt("zPos")); -+ } -+ // Paper end - // Paper start - public static final class InProgressChunkHolder { - -@@ -92,8 +99,8 @@ public class ChunkRegionLoader { - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); -- NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -- ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkRegionLoader.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 01ae13385dd0208c9f34da8b3897b571f86305d0..890362d28ab9cb760c73fe5014e144fb08ada6b8 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -13,6 +13,7 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.World; -@@ -123,6 +124,13 @@ public class IChunkLoader implements AutoCloseable { - - public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ // Paper start -+ if (!chunkcoordintpair.equals(ChunkRegionLoader.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof PlayerChunkMap) ? ((PlayerChunkMap)this).world.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); -+ } -+ // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch b/Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch deleted file mode 100644 index aaf887304c95..000000000000 --- a/Spigot-Server-Patches/0393-Optimise-IEntityAccess-getPlayerByUUID.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 11 Jan 2020 21:50:56 -0800 -Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID - -Use the world entity map instead of iterating over all players - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 02a64a132502fff19a41d4fa5ffafd61992865a4..6cbf8d00da6d99719f9ece14aa46c0abf38666e3 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -289,6 +289,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - optimise getPlayerByUUID -+ @Nullable -+ @Override -+ public EntityHuman getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUUID.get(uuid); -+ return (player instanceof EntityHuman) ? (EntityHuman)player : null; -+ } -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 8fdc4b22e8c99d653bd213fe64339c133b46b4e9..1ff9e771788a4ab52129070e355ca48df2949470 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -277,6 +277,12 @@ public interface IEntityAccess { - - @Nullable - default EntityHuman b(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default EntityHuman getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.getPlayers().size(); ++i) { - EntityHuman entityhuman = (EntityHuman) this.getPlayers().get(i); - diff --git a/Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch b/Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch deleted file mode 100644 index f9047f957bcb..000000000000 --- a/Spigot-Server-Patches/0394-Fix-items-not-falling-correctly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Fri, 17 Jan 2020 17:17:54 -0600 -Subject: [PATCH] Fix items not falling correctly - -Since 1.14, Mojang has added an optimization which skips checking if -an item should fall every fourth tick. - -However, Spigot's entity activation range class also has an -optimization which skips ticking active entities every fourth tick. -This can result in a state where an item will never properly fall -due to its move method never being called. - -This patch resolves the conflict by offsetting checking an item's -move method from Spigot's entity activation range check. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0b2e6e72a85e05f239d56afb6785c91da5b25d55..11e029f6f97f1dd9c32e311d1a3800f2fa54b91f 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -116,7 +116,7 @@ public class EntityItem extends Entity { - } - } - -- if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || (this.ticksLived + this.getId()) % 4 == 0) { -+ if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || this.ticksLived % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check - this.move(EnumMoveType.SELF, this.getMot()); - float f1 = 0.98F; - diff --git a/Spigot-Server-Patches/0395-Lag-compensate-eating.patch b/Spigot-Server-Patches/0395-Lag-compensate-eating.patch deleted file mode 100644 index 674e071d421c..000000000000 --- a/Spigot-Server-Patches/0395-Lag-compensate-eating.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 15:28:28 -0800 -Subject: [PATCH] Lag compensate eating - -When the server is lagging, players will wait longer when eating. -Change to also use a time check instead if it passes. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index ec31585099c8376f61496f02f9454cb600104918..f851a9806e3b936093275cf404caca82c6662ab4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -214,7 +214,7 @@ public abstract class EntityLiving extends Entity { - private int jumpTicks; - private float bw; - public ItemStack activeItem; // Paper - public -- protected int bd; -+ protected int bd; protected final int getEatTimeTicks() { return this.bd; } protected final void setEatTimeTicks(int value) { this.bd = value; } // Paper - OBFHELPER - protected int be; - private BlockPosition bx; - private Optional by; -@@ -3151,6 +3151,11 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; - } - -+ // Paper start - lag compensate eating -+ protected long eatStartTime; -+ protected int totalEatTimeTicks; -+ // Paper end -+ - private void t() { - if (this.isHandRaised()) { - if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) { -@@ -3160,7 +3165,12 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 5); - } - -- if (--this.bd == 0 && !this.world.isClientSide && !this.activeItem.m()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.bd == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.s(); - } - } else { -@@ -3210,7 +3220,10 @@ public abstract class EntityLiving extends Entity { - - if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; -- this.bd = itemstack.k(); -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = itemstack.k(); -+ this.eatStartTime = System.nanoTime(); -+ // Paper end - if (!this.world.isClientSide) { - this.c(1, true); - this.c(2, enumhand == EnumHand.OFF_HAND); -@@ -3234,7 +3247,10 @@ public abstract class EntityLiving extends Entity { - } - } else if (!this.isHandRaised() && !this.activeItem.isEmpty()) { - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - } - -@@ -3362,7 +3378,10 @@ public abstract class EntityLiving extends Entity { - } - - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - - public boolean isBlocking() { diff --git a/Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch b/Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch deleted file mode 100644 index aa68e86bd8ba..000000000000 --- a/Spigot-Server-Patches/0396-Optimize-call-to-getFluid-for-explosions.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Tue, 14 Jan 2020 17:49:03 -0500 -Subject: [PATCH] Optimize call to getFluid for explosions - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 618cf4e0d71b4b04085807314e79a02785f8a498..a9ecc2b4da587ca3d3c99f8c8af38092a02fb572 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -153,7 +153,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -- Fluid fluid = this.world.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - - if (optional.isPresent()) { diff --git a/Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch deleted file mode 100644 index 9bb8424860c5..000000000000 --- a/Spigot-Server-Patches/0397-Fix-last-firework-in-stack-not-having-effects-when-d.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 17 Jan 2020 18:44:55 -0800 -Subject: [PATCH] Fix last firework in stack not having effects when dispensed - - #2871 - -CB used the resulting item in the dispenser rather than the item -dispensed. The resulting item would have size == 0 and therefore -be convertered to air, hence why the effects disappeared. - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index 50911632341d1b861c00f01077cae43884147fe0..0055a96b51a1d38d31e129c417c97bcfc9d0b745 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -427,7 +427,7 @@ public interface IDispenseBehavior { - } - - itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); -- EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); -+ EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed - - IDispenseBehavior.a(isourceblock, entityfireworks, enumdirection); - entityfireworks.shoot((double) enumdirection.getAdjacentX(), (double) enumdirection.getAdjacentY(), (double) enumdirection.getAdjacentZ(), 0.5F, 1.0F); diff --git a/Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch b/Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch deleted file mode 100644 index e1c6127f7bd1..000000000000 --- a/Spigot-Server-Patches/0398-Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:07 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 724b230259b1b44bc9fdde6c4fcbcdde5f690e05..e3ab0b76e5003553b29215a43bc5a762f2663648 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -633,6 +633,13 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally(ItemStack item) { -+ // Paper start -+ return breakNaturally(item, false); -+ } -+ -+ @Override -+ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { -+ // Paper end - // Order matters here, need to drop before setting to air so skulls can get their data - net.minecraft.world.level.block.state.IBlockData iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -642,6 +649,7 @@ public class CraftBlock implements Block { - // Modelled off EntityHuman#hasBlock - if (block != Blocks.AIR && (item == null || !iblockdata.isRequiresSpecialTool() || nmsItem.canDestroySpecialBlock(iblockdata))) { - net.minecraft.world.level.block.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem); -+ if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getCombinedId(block.getBlockData())); // Paper - result = true; - } - diff --git a/Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch b/Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch deleted file mode 100644 index 8754eec0d1b8..000000000000 --- a/Spigot-Server-Patches/0399-Tracking-Range-Improvements.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 21 Dec 2019 15:22:09 -0500 -Subject: [PATCH] Tracking Range Improvements - -Sets tracking range of watermobs to animals instead of misc and simplifies code - -Also ignores Enderdragon, defaulting it to Mojang's setting - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d00dc8d7933be61f1401f598e5d675f5ae5d7029..baef98331c07b0f8c95351f39c5e471f96a59c05 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1797,6 +1797,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - int j = entity.getEntityType().getChunkRange() * 16; -+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - - if (j > i) { - i = j; -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 0449451142d59e828a32fe237751c7d8484894a2..3277a8aaffb6a25624967aa0c62f61309a517739 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -25,26 +25,26 @@ public class TrackingRange - if ( entity instanceof EntityPlayer ) - { - return config.playerTrackingRange; -- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) -- { -- return config.monsterTrackingRange; -- } else if ( entity instanceof EntityGhast ) -- { -- if ( config.monsterTrackingRange > config.monsterActivationRange ) -- { -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: - return config.monsterTrackingRange; -- } else -- { -- return config.monsterActivationRange; -- } -- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) -- { -- return config.animalTrackingRange; -- } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return config.animalTrackingRange; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end - { - return config.miscTrackingRange; - } else - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } diff --git a/Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch b/Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch deleted file mode 100644 index 68bbadaef877..000000000000 --- a/Spigot-Server-Patches/0400-Entity-Activation-Range-2.0.patch +++ /dev/null @@ -1,869 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Entity Activation Range 2.0 - -Optimizes performance of Activation Range - -Adds many new configurations and a new wake up inactive system - -Fixes and adds new Immunities to improve gameplay behavior - -Adds water Mobs to activation range config and nerfs fish -Adds flying monsters to control ghast and phantoms -Adds villagers as separate config - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 6cbf8d00da6d99719f9ece14aa46c0abf38666e3..fda19e1639cfbae00c8ba946b41c16faa09acbd5 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -861,17 +861,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below - entity.ticksLived++; - timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getEntityType().tickTimer.startTiming() : entity.getEntityType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); -@@ -885,12 +885,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.exit(); - } - - this.chunkCheck(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); - -@@ -900,7 +904,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up - - } - } -@@ -908,6 +912,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public void a(Entity entity, Entity entity1) { - if (!entity1.dead && entity1.getVehicle() == entity) { - if (entity1 instanceof EntityHuman || this.getChunkProvider().a(entity1)) { -+ // Paper - EAR 2 -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity1); -+ co.aikar.timings.Timing timer = isActive ? entity1.getEntityType().passengerTickTimer.startTiming() : entity1.getEntityType().passengerInactiveTickTimer.startTiming(); // Paper -+ try { -+ // Paper end - entity1.g(entity1.locX(), entity1.locY(), entity1.locZ()); - entity1.lastYaw = entity1.yaw; - entity1.lastPitch = entity1.pitch; -@@ -919,8 +928,17 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity1.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - entity1.passengerTick(); - entity1.postTick(); // CraftBukkit -+ } else { -+ entity1.setMot(Vec3D.ORIGIN); -+ entity1.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ entity.syncPositionOf(entity1); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.exit(); - } - -@@ -933,7 +951,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.a(entity1, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - - } - } else { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 5acf61ece9ca38a262387fd0395bd464312501fd..bc136276cad4e87d8658072b2f62f608670f39ca 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -68,6 +68,7 @@ import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -+import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.EnchantmentProtection; -@@ -251,7 +252,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public boolean Y; - public boolean impulse; - public int portalCooldown; -- protected boolean inPortal; -+ public boolean inPortal; // Paper - public - protected int portalTicks; - protected BlockPosition ac; - private boolean invulnerable; -@@ -275,6 +276,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } -@@ -665,6 +667,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.recalcPosition(); - } else { - if (enummovetype == EnumMoveType.PISTON) { -+ this.activatedTick = MinecraftServer.currentTick + 20; // Paper - vec3d = this.b(vec3d); - if (vec3d.equals(Vec3D.ORIGIN)) { - return; -@@ -677,6 +680,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.setMot(Vec3D.ORIGIN); - } -+ // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof EntityItem || this instanceof EntityMinecartAbstract) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { -+ setMot(Vec3D.ORIGIN); -+ this.world.getMethodProfiler().exit(); -+ return; -+ } -+ // Paper end - - vec3d = this.a(vec3d, enummovetype); - Vec3D vec3d1 = this.g(vec3d); -@@ -2007,6 +2017,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - -+ public void syncPositionOf(Entity entity) { k(entity); } // Paper - OBFHELPER - public void k(Entity entity) { - this.a(entity, Entity::setPosition); - } -@@ -2817,6 +2828,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.ae; - } - -+ public final boolean isPushedByWater() { return this.bV(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean bV() { - // Paper start - return this.pushedByWater(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index a9322e7cd8e07a2d5578c861991d53ec85fbfbcc..bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -14,6 +14,7 @@ import org.bukkit.event.entity.EntityUnleashEvent; - public abstract class EntityCreature extends EntityInsentient { - - public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper -+ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper - - protected EntityCreature(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index db72b685f4a4b95f345f1d34f9eeb83b8731120a..89d24d7532a256434513a45c901946e28db396bd 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -115,7 +115,7 @@ public abstract class EntityInsentient extends EntityLiving { - public MinecraftKey lootTableKey; - public long lootTableSeed; - @Nullable -- private Entity leashHolder; -+ public Entity leashHolder; // Paper - private -> public - private int bx; - @Nullable - private NBTTagCompound by; -@@ -196,6 +196,19 @@ public abstract class EntityInsentient extends EntityLiving { - return this.lookController; - } - -+ // Paper start -+ @Override -+ public void inactiveTick() { -+ super.inactiveTick(); -+ if (this.goalSelector.inactiveTick()) { -+ this.goalSelector.doTick(); -+ } -+ if (this.targetSelector.inactiveTick()) { -+ this.targetSelector.doTick(); -+ } -+ } -+ // Paper end -+ - public ControllerMove getControllerMove() { - if (this.isPassenger() && this.getVehicle() instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) this.getVehicle(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index f851a9806e3b936093275cf404caca82c6662ab4..02d3b792cc9769b5daa6fcac57f5cda320a2a29e 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -192,7 +192,7 @@ public abstract class EntityLiving extends Entity { - protected float aN; - protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; -- protected boolean jumping; -+ public boolean jumping; // Paper protected -> public - public float aR; - public float aS; - public float aT; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 5e599d88a150c907f50acbb58ad1725c3fe361e4..b505c23c57a4b84faf5906c6295455b4720c4426 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -20,7 +20,10 @@ public abstract class PathfinderGoal { - - public void c() {} - -- public void d() {} -+ public void d() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void e() {} - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 6a156a488bc073b3b60f4d1081e3f2ab65ba9e96..8a0515ae03c9081b03e9c2a312826345038b8fa7 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -9,12 +9,12 @@ import net.minecraft.world.level.IWorldReader; - - public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - -- protected final EntityCreature a; -+ protected final EntityCreature a;public EntityCreature getEntity() { return a; } // Paper - OBFHELPER - public final double b; - protected int c; - protected int d; - private int g; -- protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER -+ protected BlockPosition e; public final BlockPosition getTargetPosition() { return this.e; } public void setTargetPosition(BlockPosition pos) { this.e = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -@@ -23,6 +23,13 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i) { - this(entitycreature, d0, i, 1); - } -+ // Paper start - activation range improvements -+ @Override -+ public void onTaskReset() { -+ super.onTaskReset(); -+ setTargetPosition(BlockPosition.ZERO); -+ } -+ // Paper end - - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) { - this.e = BlockPosition.ZERO; -@@ -111,6 +118,7 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, i1, k - 1, j1); - if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) { - this.e = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutableCopy()); // Paper - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index c9aaa63fcb0abe5628798827003c677c883c2a18..8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -26,10 +26,11 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); -+ private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -- private int g = 3; -+ private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - - public PathfinderGoalSelector(Supplier supplier) { - this.e = supplier; -@@ -39,6 +40,21 @@ public class PathfinderGoalSelector { - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -+ // Paper start -+ public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; -+ } -+ public boolean hasTasks() { -+ for (PathfinderGoalWrapped task : getTasks()) { -+ if (task.isRunning()) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end -+ - public void a(PathfinderGoal pathfindergoal) { - this.d.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.j() == pathfindergoal; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 7395335ee97237376d34e315ea1d7d46766b278a..7bb531e47668cf445083c4dedb03ccafe6a9c96b 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -64,6 +64,7 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - return this.a.i(); - } - -+ public boolean isRunning() { return this.g(); } // Paper - OBFHELPER - public boolean g() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -index 8b09aaa30dd753fd34bea155890bdd9e5cb180f5..2005cb484ba6b5929ad81d3d120521f247f3d4cf 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -@@ -454,6 +454,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - return this.bC != null; - } - -+ public final boolean inCaravan() { return this.fC(); } // Paper - OBFHELPER - public boolean fC() { - return this.bB != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 858bbfbc08a5f2e1ef93ff52d6708059b32fbbbf..d7e152f7147bb599ce21dc605ebbd76e82eced26 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -213,17 +213,29 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void inactiveTick() { - // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( -- if (world.spigotConfig.tickInactiveVillagers && this.doAITick()) { -- this.mobTick(); -+ // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } -+ if (this.doAITick()) { -+ if (world.spigotConfig.tickInactiveVillagers) { -+ this.mobTick(); -+ } else { -+ this.mobTick(true); -+ } -+ } -+ doReputationTick(); -+ // Paper end -+ - super.inactiveTick(); - } - // Spigot End - - @Override -- protected void mobTick() { -+ protected void mobTick() { mobTick(false); } -+ protected void mobTick(boolean inactive) { - this.world.getMethodProfiler().enter("villagerBrain"); -- this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error -+ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper - this.world.getMethodProfiler().exit(); - if (this.bF) { - this.bF = false; -@@ -247,7 +259,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bv = null; - } - -- if (!this.isNoAI() && this.random.nextInt(100) == 0) { -+ if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper - Raid raid = ((WorldServer) this.world).b_(this.getChunkCoordinates()); - - if (raid != null && raid.v() && !raid.a()) { -@@ -258,6 +270,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.eN()) { - this.eT(); - } -+ if (inactive) return; // Paper - - super.mobTick(); - } -@@ -901,6 +914,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - } - -+ private void doReputationTick() { fw(); } // Paper - OBFHELPER - private void fw() { - long i = this.world.getTime(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 190411d6fcee8bed686a2bcfd088aa7c2513fc26..3dd80fcf9237f15bb3bf38d1529340e178f09388 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -72,10 +72,12 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); - } - -+ public final int getUnhappy() { return eK(); } // Paper - OBFHELPER - public int eK() { - return (Integer) this.datawatcher.get(EntityVillagerAbstract.bp); - } - -+ public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER - public void s(int i) { - this.datawatcher.set(EntityVillagerAbstract.bp, i); - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index d1738b57efd3f5e6c51603553a773173e4b09bb5..c4680142bf23d30169555abe7db78d85811e042b 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -142,6 +142,12 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public long ticksPerWaterSpawns; - public long ticksPerWaterAmbientSpawns; - public long ticksPerAmbientSpawns; -+ // Paper start -+ public int wakeupInactiveRemainingAnimals; -+ public int wakeupInactiveRemainingFlying; -+ public int wakeupInactiveRemainingMonsters; -+ public int wakeupInactiveRemainingVillagers; -+ // Paper end - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 53d0541aba207b5eaea2e49edbb56df918d30333..663127e6e6ec507959142b18a11a5a4790d4b98b 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -31,11 +31,30 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; - import co.aikar.timings.MinecraftTimings; - -+// Paper start -+import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.BehaviorController; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.IMonster; -+import net.minecraft.world.entity.schedule.Activity; -+import net.minecraft.world.entity.item.EntityFallingBlock; -+import net.minecraft.world.entity.projectile.EntityEnderSignal; -+// Paper end -+ - public class ActivationRange - { - - public enum ActivationType - { -+ WATER, // Paper -+ FLYING_MONSTER, // Paper -+ VILLAGER, // Paper - MONSTER, - ANIMAL, - RAIDER, -@@ -43,6 +62,43 @@ public class ActivationRange - - AxisAlignedBB boundingBox = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - } -+ // Paper start -+ -+ static Activity[] VILLAGER_PANIC_IMMUNITIES = { -+ Activity.HIDE, -+ Activity.PRE_RAID, -+ Activity.RAID, -+ Activity.PANIC -+ }; -+ -+ private static int checkInactiveWakeup(Entity entity) { -+ World world = entity.world; -+ SpigotWorldConfig config = world.spigotConfig; -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ if (entity.activationType == ActivationType.VILLAGER) { -+ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { -+ world.wakeupInactiveRemainingVillagers--; -+ return config.wakeUpInactiveVillagersFor; -+ } -+ } else if (entity.activationType == ActivationType.ANIMAL) { -+ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { -+ world.wakeupInactiveRemainingAnimals--; -+ return config.wakeUpInactiveAnimalsFor; -+ } -+ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { -+ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { -+ world.wakeupInactiveRemainingFlying--; -+ return config.wakeUpInactiveFlyingFor; -+ } -+ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { -+ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { -+ world.wakeupInactiveRemainingMonsters--; -+ return config.wakeUpInactiveMonstersFor; -+ } -+ } -+ return -1; -+ } -+ // Paper end - - static AxisAlignedBB maxBB = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - -@@ -55,10 +111,13 @@ public class ActivationRange - */ - public static ActivationType initializeEntityActivationType(Entity entity) - { -+ if (entity instanceof EntityWaterAnimal) { return ActivationType.WATER; } // Paper -+ else if (entity instanceof EntityVillager) { return ActivationType.VILLAGER; } // Paper -+ else if (entity instanceof EntityFlying && entity instanceof IMonster) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future - if ( entity instanceof EntityRaider ) - { - return ActivationType.RAIDER; -- } else if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) -+ } else if ( entity instanceof IMonster ) // Paper - correct monster check - { - return ActivationType.MONSTER; - } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) -@@ -79,10 +138,14 @@ public class ActivationRange - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) - { -- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) -- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) -- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) -- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) -+ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper -+ || entity instanceof EntityEnderSignal // Paper - || entity instanceof EntityHuman - || entity instanceof EntityProjectile - || entity instanceof EntityEnderDragon -@@ -115,10 +178,25 @@ public class ActivationRange - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; - final int monsterActivationRange = world.spigotConfig.monsterActivationRange; -+ // Paper start -+ final int waterActivationRange = world.spigotConfig.waterActivationRange; -+ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; -+ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; -+ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); -+ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); -+ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); -+ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); -+ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); -+ // Paper end - - int maxRange = Math.max( monsterActivationRange, animalActivationRange ); - maxRange = Math.max( maxRange, raiderActivationRange ); - maxRange = Math.max( maxRange, miscActivationRange ); -+ // Paper start -+ maxRange = Math.max( maxRange, flyingActivationRange ); -+ maxRange = Math.max( maxRange, waterActivationRange ); -+ maxRange = Math.max( maxRange, villagerActivationRange ); -+ // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); - - for ( EntityHuman player : world.getPlayers() ) -@@ -130,6 +208,11 @@ public class ActivationRange - ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange ); - ActivationType.ANIMAL.boundingBox = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); - ActivationType.MONSTER.boundingBox = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); -+ // Paper start -+ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); -+ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().grow( flyingActivationRange, 256, flyingActivationRange ); -+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().grow( villagerActivationRange, 256, waterActivationRange ); -+ // Paper end - - int i = MathHelper.floor( maxBB.minX / 16.0D ); - int j = MathHelper.floor( maxBB.maxX / 16.0D ); -@@ -140,7 +223,7 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -158,19 +241,15 @@ public class ActivationRange - */ - private static void activateChunkEntities(Chunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.c( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -185,56 +264,105 @@ public class ActivationRange - * @param entity - * @return - */ -- public static boolean checkEntityImmunities(Entity entity) -+ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity - { -+ // Paper start -+ SpigotWorldConfig config = entity.world.spigotConfig; -+ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); -+ if (inactiveWakeUpImmunity > -1) { -+ return inactiveWakeUpImmunity; -+ } -+ if (entity.fireTicks > 0) { -+ return 2; -+ } -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ // Paper end - // quick checks. -- if ( entity.inWater || entity.fireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.isPushedByWater()) ) // Paper - { -- return true; -+ return 100; // Paper - } - if ( !( entity instanceof EntityArrow ) ) - { -- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) -+ if ( (!entity.isOnGround() && !(entity instanceof EntityFlying)) ) // Paper - remove passengers logic - { -- return true; -+ return 10; // Paper - } - } else if ( !( (EntityArrow) entity ).inGround ) - { -- return true; -+ return 1; // Paper - } - // special cases. - if ( entity instanceof EntityLiving ) - { - EntityLiving living = (EntityLiving) entity; -- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) -+ if ( living.isClimbing() || living.jumping || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper - { -- return true; -+ return 1; // Paper - } -- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) -+ if ( entity instanceof EntityInsentient && ((EntityInsentient) entity ).getGoalTarget() != null) // Paper - { -- return true; -+ return 20; // Paper - } -- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) -+ // Paper start -+ if (entity instanceof EntityBee) { -+ EntityBee bee = (EntityBee)entity; -+ BlockPosition movingTarget = bee.getMovingTarget(); -+ if (bee.isAngry() || -+ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || -+ (bee.getFlowerPos() != null && bee.getFlowerPos().equals(movingTarget)) -+ ) { -+ return 20; -+ } -+ } -+ if ( entity instanceof EntityVillager ) { -+ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); -+ -+ if (config.villagersActiveForPanic) { -+ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { -+ if (behaviorController.c(activity)) { -+ return 20*5; -+ } -+ } -+ } -+ -+ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { -+ if (behaviorController.c(Activity.WORK)) { -+ return config.villagersWorkImmunityFor; -+ } -+ } -+ } -+ if ( entity instanceof EntityLlama && ( (EntityLlama) entity ).inCaravan() ) - { -- return true; -+ return 1; - } -+ // Paper end - if ( entity instanceof EntityAnimal ) - { - EntityAnimal animal = (EntityAnimal) entity; - if ( animal.isBaby() || animal.isInLove() ) - { -- return true; -+ return 5; // Paper - } - if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) - { -- return true; -+ return 1; // Paper - } - } - if (entity instanceof EntityCreeper && ((EntityCreeper) entity).isIgnited()) { // isExplosive -- return true; -+ return 20; // Paper - } -+ // Paper start -+ if (entity instanceof EntityInsentient && ((EntityInsentient) entity).targetSelector.hasTasks() ) { -+ return 0; -+ } -+ if (entity instanceof EntityPillager) { -+ EntityPillager pillager = (EntityPillager) entity; -+ // TODO:? -+ } -+ // Paper end - } -- return false; -+ return -1; // Paper - } - - /** -@@ -249,8 +377,19 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof EntityFireworks ) { - return true; - } -+ // Paper start - special case always immunities -+ // immunize brand new entities, dead entities, and portal scenarios -+ if (entity.defaultActivationState || entity.ticksLived < 20*10 || !entity.isAlive() || entity.inPortal || entity.portalCooldown > 0) { -+ return true; -+ } -+ // immunize leashed entities -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).leashHolder instanceof EntityHuman) { -+ return true; -+ } -+ // Paper end - -- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; -+ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; -+ entity.isTemporarilyActive = false; // Paper - - // Should this entity tick? - if ( !isActive ) -@@ -258,15 +397,19 @@ public class ActivationRange - if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) - { - // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) -- { -- // Triggered some sort of immunity, give 20 full ticks before we check again. -- entity.activatedTick = MinecraftServer.currentTick + 20; -+ // Paper start -+ int immunity = checkEntityImmunities(entity); -+ if (immunity >= 0) { -+ entity.activatedTick = MinecraftServer.currentTick + immunity; -+ } else { -+ entity.isTemporarilyActive = true; - } -+ // Paper end - isActive = true; -+ - } - // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper - { - isActive = false; - } -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 34ee684901906fc2ef5f0d09680d2686b813e52b..6b015c1f26facb4e82d75b252164dec05731ca6c 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -180,13 +180,59 @@ public class SpigotWorldConfig - public int monsterActivationRange = 32; - public int raiderActivationRange = 48; - public int miscActivationRange = 16; -+ // Paper start -+ public int flyingMonsterActivationRange = 32; -+ public int waterActivationRange = 16; -+ public int villagerActivationRange = 32; -+ public int wakeUpInactiveAnimals = 4; -+ public int wakeUpInactiveAnimalsEvery = 60*20; -+ public int wakeUpInactiveAnimalsFor = 5*20; -+ public int wakeUpInactiveMonsters = 8; -+ public int wakeUpInactiveMonstersEvery = 20*20; -+ public int wakeUpInactiveMonstersFor = 5*20; -+ public int wakeUpInactiveVillagers = 4; -+ public int wakeUpInactiveVillagersEvery = 30*20; -+ public int wakeUpInactiveVillagersFor = 5*20; -+ public int wakeUpInactiveFlying = 8; -+ public int wakeUpInactiveFlyingEvery = 10*20; -+ public int wakeUpInactiveFlyingFor = 5*20; -+ public int villagersWorkImmunityAfter = 5*20; -+ public int villagersWorkImmunityFor = 20; -+ public boolean villagersActiveForPanic = true; -+ // Paper end - public boolean tickInactiveVillagers = true; - private void activationRange() - { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); -+ // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); -+ -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); -+ -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); -+ -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); -+ -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); -+ -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); -+ // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); - } diff --git a/Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch b/Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch deleted file mode 100644 index 60a54b1c944f..000000000000 --- a/Spigot-Server-Patches/0401-Fix-items-vanishing-through-end-portal.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Wed, 22 Jan 2020 19:52:28 -0600 -Subject: [PATCH] Fix items vanishing through end portal - -If the Paper configuration option "keep-spawn-loaded" is set to false, -items entering the overworld from the end will spawn at Y = 0. - -This is due to logic in the getHighestBlockYAt method in World.java -only searching the heightmap if the chunk is loaded. - -Quickly loading the exact world spawn chunk before searching the -heightmap resolves the issue without having to load all spawn chunks. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index bc136276cad4e87d8658072b2f62f608670f39ca..d676eaad8179cdeae410038e58ddafe0fe541ccc 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2730,6 +2730,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - BlockPosition blockposition1; - - if (flag1) { -+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.world.getChunkAtWorldCoords(this.world.getSpawn()); -+ // Paper end - blockposition1 = WorldServer.a; - } else { - blockposition1 = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()); diff --git a/Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index 7fbf667ed7d5..000000000000 --- a/Spigot-Server-Patches/0402-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -index 4044861622294a317fef7e93aa86e96e8474b513..2aa5789437ba7eb20579da238c407a65a25b1d44 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class ControllerMove { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER - protected double b; - protected double c; - protected double d; -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -index 80cba36bc59e89c40c96ca556594a4285f06fc6f..d0cbc429144b89498a7f4dc6ff64924c5ba54ad8 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -@@ -16,7 +16,7 @@ public class ControllerMoveFlying extends ControllerMove { - } - - @Override -- public void a() { -+ public void a() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.h == ControllerMove.Operation.MOVE_TO) { - this.h = ControllerMove.Operation.WAIT; - this.a.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 1ecf73f874f404f58a99316ae027f76db6b557db..7ce8eaeb9af3547869f467910b6a458118c63c1f 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -111,7 +111,17 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - public EntityBee(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.moveController = new ControllerMoveFlying(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveController = new ControllerMoveFlying(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().locY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookController = new EntityBee.j(this); - this.a(PathType.DANGER_FIRE, -1.0F); - this.a(PathType.WATER, -1.0F); diff --git a/Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch deleted file mode 100644 index 771f7d9a623c..000000000000 --- a/Spigot-Server-Patches/0403-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Jan 2020 17:04:35 -0800 -Subject: [PATCH] Optimise getChunkAt calls for loaded chunks - -bypass the need to get a player chunk, then get the either, -then unwrap it... - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 372e5268783a84effa8f9f06c3f85b182e209cb8..0c8864eeae6e3b449514f52d95c17f2e4a304f0e 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -470,6 +470,12 @@ public class ChunkProviderServer extends IChunkProvider { - return this.getChunkAt(i, j, chunkstatus, flag); - }, this.serverThreadQueue).join(); - } else { -+ // Paper start - optimise for loaded chunks -+ Chunk ifLoaded = this.getChunkAtIfLoadedMainThread(i, j); -+ if (ifLoaded != null) { -+ return ifLoaded; -+ } -+ // Paper end - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.c("getChunk"); -@@ -520,39 +526,7 @@ public class ChunkProviderServer extends IChunkProvider { - if (Thread.currentThread() != this.serverThread) { - return null; - } else { -- this.world.getMethodProfiler().c("getChunkNow"); -- long k = ChunkCoordIntPair.pair(i, j); -- -- for (int l = 0; l < 4; ++l) { -- if (k == this.cachePos[l] && this.cacheStatus[l] == ChunkStatus.FULL) { -- IChunkAccess ichunkaccess = this.cacheChunk[l]; -- -- return ichunkaccess instanceof Chunk ? (Chunk) ichunkaccess : null; -- } -- } -- -- PlayerChunk playerchunk = this.getChunk(k); -- -- if (playerchunk == null) { -- return null; -- } else { -- Either either = (Either) playerchunk.b(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error -- -- if (either == null) { -- return null; -- } else { -- IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error -- -- if (ichunkaccess1 != null) { -- this.a(k, ichunkaccess1, ChunkStatus.FULL); -- if (ichunkaccess1 instanceof Chunk) { -- return (Chunk) ichunkaccess1; -- } -- } -- -- return null; -- } -- } -+ return this.getChunkAtIfLoadedMainThread(i, j); // Paper - optimise for loaded chunks - } - } - diff --git a/Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch b/Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch deleted file mode 100644 index a57683123cba..000000000000 --- a/Spigot-Server-Patches/0404-Allow-overriding-the-java-version-check.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 8 Feb 2020 18:02:24 -0600 -Subject: [PATCH] Allow overriding the java version check - --DPaper.IgnoreJavaVersion=true - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 463c41454d96e823d1ffd62619fc3b83af3bf168..c3e2d9c4d0ef3de80f5206c6bd234121ee1316cc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -181,7 +181,7 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); - if (javaVersion > 60.0) { - System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); -- return; -+ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper - } - - try { diff --git a/Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch b/Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch deleted file mode 100644 index 60a13170407d..000000000000 --- a/Spigot-Server-Patches/0405-Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:05 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -index 01cee6599f5d21a29310c30a8b1e505023d1a260..dc2e51718395494f60b0376d65d496daf2f76e71 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -@@ -67,6 +67,16 @@ public class EntityEgg extends EntityProjectileThrowable { - hatchingType = event.getHatchingType(); - } - -+ // Paper start -+ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); -+ event.callEvent(); -+ -+ b0 = event.getNumHatches(); -+ hatching = event.isHatching(); -+ hatchingType = event.getHatchingType(); -+ // Paper end -+ -+ - if (hatching) { - for (int i = 0; i < b0; ++i) { - Entity entity = world.getWorld().createEntity(new org.bukkit.Location(world.getWorld(), this.locX(), this.locY(), this.locZ(), this.yaw, 0.0F), hatchingType.getEntityClass()); diff --git a/Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch b/Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch deleted file mode 100644 index 02e11131e92e..000000000000 --- a/Spigot-Server-Patches/0406-Optimise-random-block-ticking.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Jan 2020 21:28:00 -0800 -Subject: [PATCH] Optimise random block ticking - -Massive performance improvement for random block ticking. -The performance increase comes from the fact that the vast -majority of attempted block ticks (~95% in my testing) fail -because the randomly selected block is not tickable. - -Now only tickable blocks are targeted, however this means that -the maximum number of block ticks occurs per chunk. However, -not all chunks are going to be targeted. The percent chance -of a chunk being targeted is based on how many tickable blocks -are in the chunk. -This means that while block ticks are spread out less, the -total number of blocks ticked per world tick remains the same. -Therefore, the chance of a random tickable block being ticked -remains the same. - -diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -@@ -0,0 +1,46 @@ -+package com.destroystokyo.paper.util.math; -+ -+import java.util.Random; -+ -+public final class ThreadUnsafeRandom extends Random { -+ -+ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. -+ private static final long multiplier = 0x5DEECE66DL; -+ private static final long addend = 0xBL; -+ private static final long mask = (1L << 48) - 1; -+ -+ private static long initialScramble(long seed) { -+ return (seed ^ multiplier) & mask; -+ } -+ -+ private long seed; -+ -+ @Override -+ public void setSeed(long seed) { -+ // note: called by Random constructor -+ this.seed = initialScramble(seed); -+ } -+ -+ @Override -+ protected int next(int bits) { -+ // avoid the expensive CAS logic used by superclass -+ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); -+ } -+ -+ // Taken from -+ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ -+ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c -+ // Original license is public domain -+ public static int fastRandomBounded(final long randomInteger, final long limit) { -+ // randomInteger must be [0, pow(2, 32)) -+ // limit must be [0, pow(2, 32)) -+ return (int)((randomInteger * limit) >>> 32); -+ } -+ -+ @Override -+ public int nextInt(int bound) { -+ // yes this breaks random's spec -+ // however there's nothing that uses this class that relies on it -+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 4c9ec211470f95d538d1d95c74796190edf99b87..8c0aeb51f5e230fd6109e750732eb54559bc9637 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -468,6 +468,7 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -+ public final BlockPosition.MutableBlockPosition setValues(final BaseBlockPosition baseblockposition) { return this.g(baseblockposition); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) { - return this.d(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index fda19e1639cfbae00c8ba946b41c16faa09acbd5..cf6e9a949a864df12ca1670dbc456494d2b5e473 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -675,7 +675,12 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - } - -- public void a(Chunk chunk, int i) { -+ // Paper start - optimise random block ticking -+ private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); -+ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); -+ // Paper end -+ -+ public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.d(); -@@ -683,10 +688,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - - gameprofilerfiller.enter("thunder"); -- BlockPosition blockposition; -+ final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - - if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.a(this.a(j, 0, k, 15)); -+ blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -709,59 +714,77 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); -- BlockPosition blockposition1 = blockposition.down(); -+ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking -+ // Paper start - optimise chunk ticking -+ this.getRandomBlockPosition(j, 0, k, 15, blockposition); -+ int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); -+ int downY = normalY - 1; -+ blockposition.setY(normalY); -+ // Paper end - BiomeBase biomebase = this.getBiome(blockposition); - -- if (biomebase.a(this, blockposition1)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (biomebase.a(this, blockposition)) { -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper end - } - -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.b(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit - } - -- if (flag && this.getBiome(blockposition1).c() == BiomeBase.Precipitation.RAIN) { -- this.getType(blockposition1).getBlock().c((World) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { -+ chunk.getType(blockposition).getBlock().c((World) this, blockposition); -+ // Paper end - } - } - -- gameprofilerfiller.exitEnter("tickBlocks"); -- timings.chunkTicksBlocks.startTiming(); // Paper -+ // Paper start - optimise random block ticking -+ gameprofilerfiller.exit(); - if (i > 0) { -- ChunkSection[] achunksection = chunk.getSections(); -- int l = achunksection.length; -+ gameprofilerfiller.enter("randomTick"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - -- for (int i1 = 0; i1 < l; ++i1) { -- ChunkSection chunksection = achunksection[i1]; -+ ChunkSection[] sections = chunk.getSections(); - -- if (chunksection != Chunk.a && chunksection.d()) { -- int j1 = chunksection.getYPosition(); -+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { -+ ChunkSection section = sections[sectionIndex]; -+ if (section == null || section.tickingList.size() == 0) { -+ continue; -+ } - -- for (int k1 = 0; k1 < i; ++k1) { -- BlockPosition blockposition2 = this.a(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - -- gameprofilerfiller.enter("randomTick"); -- IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); -+ for (int a = 0; a < randomTickSpeed; ++a) { -+ int tickingBlocks = section.tickingList.size(); -+ int index = this.randomTickRandom.nextInt(16 * 16 * 16); -+ if (index >= tickingBlocks) { -+ continue; -+ } - -- if (iblockdata.isTicking()) { -- iblockdata.b(this, blockposition2, this.random); -- } -+ long raw = section.tickingList.getRaw(index); -+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); -+ int randomX = location & 15; -+ int randomY = ((location >>> (4 + 4)) & 255) | yPos; -+ int randomZ = (location >>> 4) & 15; - -- Fluid fluid = iblockdata.getFluid(); -+ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); -+ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- if (fluid.f()) { -- fluid.b(this, blockposition2, this.random); -- } -+ iblockdata.b(this, blockposition2, this.randomTickRandom); - -- gameprofilerfiller.exit(); -- } -+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. -+ // TODO CHECK ON UPDATE - } - } -+ gameprofilerfiller.exit(); -+ timings.chunkTicksBlocks.stopTiming(); // Paper -+ // Paper end - } -- timings.chunkTicksBlocks.stopTiming(); // Paper -- gameprofilerfiller.exit(); - } - - protected BlockPosition a(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index c4f3b680512fb15cea01ad12d0a00c6e60bf34b7..cfa444cf384920d446c6dc14b23e5158fc28df3b 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -112,4 +112,32 @@ public class DataBits { - } - - } -+ -+ // Paper start -+ public final void forEach(DataBitConsumer consumer) { -+ int i = 0; -+ long[] along = this.b; -+ int j = along.length; -+ -+ for (int k = 0; k < j; ++k) { -+ long l = along[k]; -+ -+ for (int i1 = 0; i1 < this.f; ++i1) { -+ consumer.accept(i, (int) (l & this.d)); -+ l >>= this.c; -+ ++i; -+ if (i >= this.e) { -+ return; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DataBitConsumer { -+ -+ void accept(int location, int data); -+ -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 09a6310af6712d36c20167256b60dc3235e76021..ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -91,7 +91,7 @@ public class EntityTurtle extends EntityAnimal { - } - - public void setHomePos(BlockPosition blockposition) { -- this.datawatcher.set(EntityTurtle.bp, blockposition); -+ this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... - } - - public BlockPosition getHomePos() { // Paper - public -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index c4680142bf23d30169555abe7db78d85811e042b..cc41dcd85760b57bb8076b37e9a907d1cb4e12c7 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1472,10 +1472,18 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public abstract ITagRegistry p(); - - public BlockPosition a(int i, int j, int k, int l) { -+ // Paper start - allow use of mutable pos -+ BlockPosition.MutableBlockPosition ret = new BlockPosition.MutableBlockPosition(); -+ this.getRandomBlockPosition(i, j, k, l, ret); -+ return ret.immutableCopy(); -+ } -+ public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) { -+ // Paper end - this.n = this.n * 3 + 1013904223; - int i1 = this.n >> 2; - -- return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); -+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call -+ return out; // Paper - } - - public boolean isSavingDisabled() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index e7bb33125a25b9e5a68013b15d7b5b6b6769ab9b..fc55e89260fdec2c5045e8f00e091191980ff1f2 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -640,8 +640,8 @@ public class Chunk implements IChunkAccess { - this.entities.remove(entity); // Paper - } - -- @Override -- public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.getHighestBlock(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { // Paper - return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0b4e346daaea91565fde2f789fafa8b431a7b042..4bc26a7a4ae91aac90c256758ec8868d83027c0c 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.Fluid; - public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); -- private final int yPos; -+ final int yPos; // Paper - private -> package-private - short nonEmptyBlockCount; // Paper - package-private -- private short tickingBlockCount; -+ short tickingBlockCount; // Paper - private -> package-private - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -@@ -74,6 +76,9 @@ public class ChunkSection { - --this.nonEmptyBlockCount; - if (iblockdata1.isTicking()) { - --this.tickingBlockCount; -+ // Paper start -+ this.tickingList.remove(i, j, k); -+ // Paper end - } - } - -@@ -85,6 +90,9 @@ public class ChunkSection { - ++this.nonEmptyBlockCount; - if (iblockdata.isTicking()) { - ++this.tickingBlockCount; -+ // Paper start -+ this.tickingList.add(i, j, k, iblockdata); -+ // Paper end - } - } - -@@ -120,23 +128,29 @@ public class ChunkSection { - } - - public void recalcBlockCounts() { -+ // Paper start -+ this.tickingList.clear(); -+ // Paper end - this.nonEmptyBlockCount = 0; - this.tickingBlockCount = 0; - this.e = 0; -- this.blockIds.a((iblockdata, i) -> { -+ this.blockIds.forEachLocation((iblockdata, location) -> { // Paper - Fluid fluid = iblockdata.getFluid(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); -+ // Paper start -+ this.tickingList.add(location, iblockdata); -+ // Paper end - } - } - - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.f()) { -- this.e = (short) (this.e + i); -+ this.e = (short) (this.e + 1); - } - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 68d53a51acc9790b9cda20ec4d2ec6edd1baac1a..86dfab740883c138a0df8a3da9dfb4eb9acefaa3 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -286,6 +286,14 @@ public class DataPaletteBlock implements DataPaletteExpandable { - }); - } - -+ // Paper start -+ public void forEachLocation(DataPaletteBlock.a datapaletteblock_a) { -+ this.getDataBits().forEach((int location, int data) -> { -+ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); -+ }); -+ } -+ // Paper end -+ - @FunctionalInterface - public interface a { - diff --git a/Spigot-Server-Patches/0407-Entity-Jump-API.patch b/Spigot-Server-Patches/0407-Entity-Jump-API.patch deleted file mode 100644 index 17e2ec967bda..000000000000 --- a/Spigot-Server-Patches/0407-Entity-Jump-API.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:11 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 02d3b792cc9769b5daa6fcac57f5cda320a2a29e..86c6a8fd4511dfe426cc1651d289f38b467d3029 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2876,8 +2876,10 @@ public abstract class EntityLiving extends Entity { - } else if (this.aQ() && (!this.onGround || d7 > d8)) { - this.c((Tag) TagsFluid.LAVA); - } else if ((this.onGround || flag && d7 <= d8) && this.jumpTicks == 0) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - this.jump(); - this.jumpTicks = 10; -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } else { - this.jumpTicks = 0; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -index f755607872920caae1410d38c431c16b5238c00f..711b322007a0973ff0aebf3c25efbae8fc7741d0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -@@ -490,7 +490,9 @@ public class EntityPanda extends EntityAnimal { - EntityPanda entitypanda = (EntityPanda) iterator.next(); - - if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fh()) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - entitypanda.jump(); -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index ff586b8366a6298f1906551b068e8abb26fcabc7..b18292ef2e00b4ef8a0b2da5f63a596dbd04b1fd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -799,5 +799,20 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public boolean isHandRaised() { - return getHandle().isHandRaised(); - } -+ -+ @Override -+ public boolean isJumping() { -+ return getHandle().jumping; -+ } -+ -+ @Override -+ public void setJumping(boolean jumping) { -+ getHandle().setJumping(jumping); -+ if (jumping && getHandle() instanceof EntityInsentient) { -+ // this is needed to actually make a mob jump -+ ((EntityInsentient) getHandle()).getControllerJump().jump(); -+ } -+ } -+ - // Paper end - } diff --git a/Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch b/Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch deleted file mode 100644 index 1a54ef16f66f..000000000000 --- a/Spigot-Server-Patches/0408-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 7 Feb 2020 14:36:56 -0600 -Subject: [PATCH] Add option to nerf pigmen from nether portals - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -594,4 +594,9 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); - log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); - } -+ -+ public boolean nerfNetherPortalPigmen = false; -+ private void nerfNetherPortalPigmen() { -+ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d676eaad8179cdeae410038e58ddafe0fe541ccc..68fdb01c3f11c3b060d3d621099d67f6b29431d6 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -278,6 +278,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public long activatedTick = Integer.MIN_VALUE; - public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one -+ public boolean fromNetherPortal; // Paper - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -1693,6 +1694,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); - } -+ if (fromNetherPortal) { -+ nbttagcompound.setBoolean("Paper.FromNetherPortal", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -1823,6 +1827,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = nbttagcompound.getBoolean("Paper.FromNetherPortal"); - if (nbttagcompound.hasKey("Paper.SpawnReason")) { - String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); - try { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -index e115ff86987c69f5e3571af5d7f034f24a3f6bba..5f797260eff317409a5039b88b01ad79ee2fdd91 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.player.EntityHuman; -@@ -62,6 +63,8 @@ public class BlockPortal extends Block { - - if (entity != null) { - entity.resetPortalCooldown(); -+ entity.fromNetherPortal = true; // Paper -+ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper - } - } - } diff --git a/Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch b/Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch deleted file mode 100644 index ca39b7b640a4..000000000000 --- a/Spigot-Server-Patches/0409-Make-the-GUI-graph-fancier.patch +++ /dev/null @@ -1,436 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 2 Feb 2020 04:00:40 -0600 -Subject: [PATCH] Make the GUI graph fancier - - -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4e641fdcccd3efcd1a2865dc6dc28d50671b995 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -@@ -0,0 +1,44 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphColor { -+ private static final Color[] colorLine = new Color[101]; -+ private static final Color[] colorFill = new Color[101]; -+ -+ static { -+ for (int i = 0; i < 101; i++) { -+ Color color = createColor(i); -+ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); -+ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); -+ } -+ } -+ -+ public static Color getLineColor(int percent) { -+ return colorLine[percent]; -+ } -+ -+ public static Color getFillColor(int percent) { -+ return colorFill[percent]; -+ } -+ -+ private static Color createColor(int percent) { -+ if (percent <= 50) { -+ return new Color(0X00FF00); -+ } -+ -+ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); -+ -+ int red, green; -+ if (value < 255) { -+ red = 255; -+ green = (int) (Math.sqrt(value) * 16); -+ } else { -+ green = 255; -+ value = value - 255; -+ red = 255 - (value * value / 255); -+ } -+ -+ return new Color(red, green, 0); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc34e29049 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -@@ -0,0 +1,47 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphData { -+ private long total; -+ private long free; -+ private long max; -+ private long usedMem; -+ private int usedPercent; -+ -+ public GraphData(long total, long free, long max) { -+ this.total = total; -+ this.free = free; -+ this.max = max; -+ this.usedMem = total - free; -+ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); -+ } -+ -+ public long getTotal() { -+ return total; -+ } -+ -+ public long getFree() { -+ return free; -+ } -+ -+ public long getMax() { -+ return max; -+ } -+ -+ public long getUsedMem() { -+ return usedMem; -+ } -+ -+ public int getUsedPercent() { -+ return usedPercent; -+ } -+ -+ public Color getFillColor() { -+ return GraphColor.getFillColor(usedPercent); -+ } -+ -+ public Color getLineColor() { -+ return GraphColor.getLineColor(usedPercent); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.JPanel; -+import javax.swing.Timer; -+import java.awt.BorderLayout; -+import java.awt.Dimension; -+ -+public class GuiStatsComponent extends JPanel { -+ private final Timer timer; -+ private final RAMGraph ramGraph; -+ -+ public GuiStatsComponent(MinecraftServer server) { -+ super(new BorderLayout()); -+ -+ setOpaque(false); -+ -+ ramGraph = new RAMGraph(); -+ RAMDetails ramDetails = new RAMDetails(server); -+ -+ add(ramGraph, "North"); -+ add(ramDetails, "Center"); -+ -+ timer = new Timer(500, (event) -> { -+ ramGraph.update(); -+ ramDetails.update(); -+ }); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 200); -+ } -+ -+ public void stop() { a(); } public void a() { -+ timer.stop(); -+ ramGraph.stop(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -new file mode 100644 -index 0000000000000000000000000000000000000000..67d064e3959ed8d886df30ce9d97f86c2443fa39 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -0,0 +1,73 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.SystemUtils; -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.DefaultListCellRenderer; -+import javax.swing.DefaultListSelectionModel; -+import javax.swing.JList; -+import javax.swing.border.EmptyBorder; -+import java.awt.Dimension; -+import java.text.DecimalFormat; -+import java.text.DecimalFormatSymbols; -+import java.util.Locale; -+import java.util.Vector; -+ -+public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = SystemUtils.peek(new DecimalFormat("########0.000"), (format) -+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); -+ -+ private final MinecraftServer server; -+ -+ public RAMDetails(MinecraftServer server) { -+ this.server = server; -+ -+ setBorder(new EmptyBorder(0, 10, 0, 0)); -+ setFixedCellHeight(20); -+ setOpaque(false); -+ -+ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); -+ renderer.setOpaque(false); -+ setCellRenderer(renderer); -+ -+ setSelectionModel(new DefaultListSelectionModel() { -+ @Override -+ public void setAnchorSelectionIndex(final int anchorIndex) { -+ } -+ -+ @Override -+ public void setLeadAnchorNotificationEnabled(final boolean flag) { -+ } -+ -+ @Override -+ public void setLeadSelectionIndex(final int leadIndex) { -+ } -+ -+ @Override -+ public void setSelectionInterval(final int index0, final int index1) { -+ } -+ }); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 100); -+ } -+ -+ public void update() { -+ GraphData data = RAMGraph.DATA.peekLast(); -+ Vector vector = new Vector<>(); -+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); -+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ setListData(vector); -+ } -+ -+ public double getAverage(long[] tickTimes) { -+ long total = 0L; -+ for (long value : tickTimes) { -+ total += value; -+ } -+ return ((double) total / (double) tickTimes.length) * 1.0E-6D; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e218802ac13285 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -@@ -0,0 +1,144 @@ -+package com.destroystokyo.paper.gui; -+ -+import javax.swing.JComponent; -+import javax.swing.SwingUtilities; -+import javax.swing.Timer; -+import javax.swing.ToolTipManager; -+import java.awt.Color; -+import java.awt.Dimension; -+import java.awt.Graphics; -+import java.awt.MouseInfo; -+import java.awt.Point; -+import java.awt.PointerInfo; -+import java.awt.event.MouseAdapter; -+import java.awt.event.MouseEvent; -+import java.text.SimpleDateFormat; -+import java.util.Date; -+import java.util.LinkedList; -+import java.util.concurrent.TimeUnit; -+ -+public class RAMGraph extends JComponent { -+ public static final LinkedList DATA = new LinkedList() { -+ @Override -+ public boolean add(GraphData data) { -+ if (size() >= 348) { -+ remove(); -+ } -+ return super.add(data); -+ } -+ }; -+ -+ static { -+ GraphData empty = new GraphData(0, 0, 0); -+ for (int i = 0; i < 350; i++) { -+ DATA.add(empty); -+ } -+ } -+ -+ private final Timer timer; -+ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); -+ -+ private int currentTick; -+ -+ public RAMGraph() { -+ ToolTipManager.sharedInstance().setInitialDelay(0); -+ -+ addMouseListener(new MouseAdapter() { -+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); -+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); -+ -+ @Override -+ public void mouseEntered(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); -+ } -+ -+ @Override -+ public void mouseExited(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); -+ } -+ }); -+ -+ timer = new Timer(50, (event) -> repaint()); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 110); -+ } -+ -+ public void update() { -+ Runtime jvm = Runtime.getRuntime(); -+ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); -+ -+ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); -+ if (pointerInfo != null) { -+ Point point = pointerInfo.getLocation(); -+ if (point != null) { -+ Point loc = new Point(point); -+ SwingUtilities.convertPointFromScreen(loc, this); -+ if (this.contains(loc)) { -+ ToolTipManager.sharedInstance().mouseMoved( -+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, -+ point.x, point.y, 0, false, 0)); -+ } -+ } -+ } -+ -+ currentTick++; -+ } -+ -+ @Override -+ public void paint(Graphics graphics) { -+ graphics.setColor(new Color(0xFFFFFFFF)); -+ graphics.fillRect(0, 0, 350, 100); -+ -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(1, 25, 348, 25); -+ graphics.drawLine(1, 50, 348, 50); -+ graphics.drawLine(1, 75, 348, 75); -+ -+ int i = 0; -+ for (GraphData data : DATA) { -+ i++; -+ if ((i + currentTick) % 120 == 0) { -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(i, 1, i, 99); -+ } -+ int used = data.getUsedPercent(); -+ if (used > 0) { -+ Color color = data.getLineColor(); -+ graphics.setColor(data.getFillColor()); -+ graphics.fillRect(i, 100 - used, 1, used); -+ graphics.setColor(color); -+ graphics.fillRect(i, 100 - used, 1, 1); -+ } -+ } -+ -+ graphics.setColor(new Color(0xFF000000)); -+ graphics.drawRect(0, 0, 348, 100); -+ -+ Point m = getMousePosition(); -+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { -+ GraphData data = DATA.get(m.x); -+ int used = data.getUsedPercent(); -+ graphics.setColor(new Color(0x000000)); -+ graphics.drawLine(m.x, 1, m.x, 99); -+ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); -+ graphics.setColor(data.getLineColor()); -+ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); -+ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", -+ Math.round(data.getUsedMem() / 1024F / 1024F), -+ used, getTime(m.x))); -+ } -+ } -+ -+ public String getTime(int halfSeconds) { -+ int millis = (348 - halfSeconds) / 2 * 1000; -+ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); -+ } -+ -+ public void stop() { -+ timer.stop(); -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 46d82c1548088b8305f758699388edf0d5d4d050..397194b3e90c9df39cfae17b401c7ac891b0dbb7 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -260,6 +260,7 @@ public class SystemUtils { - return supplier.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return a(t0, consumer); } // Paper - OBFHELPER - public static T a(T t0, Consumer consumer) { - consumer.accept(t0); - return t0; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 94525c8bd49334fb5aa1b113ed992e857e44ab96..c86c3cdea77369e3297548c8d5f10674c1100f76 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -218,7 +218,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ private static final DecimalFormat a = (DecimalFormat) SystemUtils.a(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] b = new int[256]; -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index dc2a36f6dbc83ba25bcd59d981f75499adbd22e5..c2c075b9e3b70f863b6c450e4f31d6fde2935be6 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -91,7 +91,7 @@ public class ServerGUI extends JComponent { - - private JComponent c() { - JPanel jpanel = new JPanel(new BorderLayout()); -- GuiStatsComponent guistatscomponent = new GuiStatsComponent(this.c); -+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.c); // Paper - - this.e.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); diff --git a/Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch b/Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index c32ce12185b9..000000000000 --- a/Spigot-Server-Patches/0410-add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:24 +0100 -Subject: [PATCH] add hand to BlockMultiPlaceEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index fbd24e10b1b966898e7e1556c5f9bd607497d970..dbfd500ad18262e4c1af40308229802fa0cb2e5d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -346,13 +346,18 @@ public class CraftEventFactory { - } - - org.bukkit.inventory.ItemStack item; -+ //Paper start - add hand to BlockMultiPlaceEvent -+ EquipmentSlot equipmentSlot; - if (hand == EnumHand.MAIN_HAND) { - item = player.getInventory().getItemInMainHand(); -+ equipmentSlot = EquipmentSlot.HAND; - } else { - item = player.getInventory().getItemInOffHand(); -+ equipmentSlot = EquipmentSlot.OFF_HAND; - } - -- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); -+ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); -+ //Paper end - craftServer.getPluginManager().callEvent(event); - - return event; diff --git a/Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch b/Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch deleted file mode 100644 index 29dc1ca8f12b..000000000000 --- a/Spigot-Server-Patches/0411-Prevent-teleporting-dead-entities.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 3 Mar 2020 05:26:40 +0000 -Subject: [PATCH] Prevent teleporting dead entities - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index cfdfa3ea95a525af25c7aa830f8e31d5afe56d65..f02ddd53df4674a2b5e0bb142db756d1f153d69b 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1469,6 +1469,10 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.dead) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getName()); -+ return; -+ } - // CraftBukkit start - if (Float.isNaN(f)) { - f = 0; diff --git a/Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch b/Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch deleted file mode 100644 index 75c8efe983d5..000000000000 --- a/Spigot-Server-Patches/0412-Validate-tripwire-hook-placement-before-update.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 7 Mar 2020 00:07:51 +0000 -Subject: [PATCH] Validate tripwire hook placement before update - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -index 8b24978cb54f2102d61f27038dedc5e3dc392dbc..5e3cf96b813d2871adf7a7f870af6c6a5dd878c1 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -@@ -170,6 +170,7 @@ public class BlockTripwireHook extends Block { - - this.a(world, blockposition, flag4, flag5, flag2, flag3); - if (!flag) { -+ if (world.getType(blockposition).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate - world.setTypeAndData(blockposition, (IBlockData) iblockdata3.set(BlockTripwireHook.FACING, enumdirection), 3); - if (flag1) { - this.a(world, blockposition, enumdirection); diff --git a/Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch deleted file mode 100644 index bc4517ce5bda..000000000000 --- a/Spigot-Server-Patches/0413-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 13 Apr 2019 16:50:58 -0500 -Subject: [PATCH] Add option to allow iron golems to spawn in air - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,11 @@ public class PaperWorldConfig { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } - -+ public boolean ironGolemsCanSpawnInAir = false; -+ private void ironGolemsCanSpawnInAir() { -+ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); -+ } -+ - public boolean armorStandEntityLookups = true; - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 49495cfbcf9b7742583536b87fc7cbd7c7c4c867..5e2b49d120b724cb5a7ae00940ded4f4875ea8a1 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -297,7 +297,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata = iworldreader.getType(blockposition1); - -- if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this)) { -+ if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this) && !world.paperConfig.ironGolemsCanSpawnInAir) { // Paper - return false; - } else { - for (int i = 1; i < 3; ++i) { diff --git a/Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch b/Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch deleted file mode 100644 index 0a2c05d50a57..000000000000 --- a/Spigot-Server-Patches/0414-Configurable-chance-of-villager-zombie-infection.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zero -Date: Sat, 22 Feb 2020 16:10:31 -0500 -Subject: [PATCH] Configurable chance of villager zombie infection - -This allows you to solve an issue in vanilla behavior where: -* On easy difficulty your villagers will NEVER get infected, meaning they will always die. -* On normal difficulty they will have a 50% of getting infected or dying. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -604,4 +604,9 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { - nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); - } -+ -+ public double zombieVillagerInfectionChance = -1.0; -+ private void zombieVillagerInfectionChance() { -+ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index f406826945dd752e6528743a0c8cad3cfdfc4a95..3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -450,10 +450,14 @@ public class EntityZombie extends EntityMonster { - @Override - public void a(WorldServer worldserver, EntityLiving entityliving) { - super.a(worldserver, entityliving); -- if ((worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -- if (worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -+ if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { - return; - } -+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) { -+ return; -+ } // Paper end - - EntityVillager entityvillager = (EntityVillager) entityliving; - // CraftBukkit start diff --git a/Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch b/Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch deleted file mode 100644 index 593c9aaac671..000000000000 --- a/Spigot-Server-Patches/0415-Optimise-Chunk-getFluid.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 14:59:08 -0800 -Subject: [PATCH] Optimise Chunk#getFluid - -Removing the try catch and generally reducing ops should make it -faster on its own, however removing the try catch makes it -easier to inline due to code size - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index fc55e89260fdec2c5045e8f00e091191980ff1f2..bb2ff043f0d159fa18769c31b08683ee12037c58 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -431,17 +431,20 @@ public class Chunk implements IChunkAccess { - } - - public Fluid a(int i, int j, int k) { -- try { -- if (j >= 0 && j >> 4 < this.sections.length) { -- ChunkSection chunksection = this.sections[j >> 4]; -- -- if (!ChunkSection.a(chunksection)) { -- return chunksection.b(i & 15, j & 15, k & 15); -+ //try { // Paper - remove try catch -+ // Paper start - reduce the number of ops in this call -+ int index = j >> 4; -+ if (index >= 0 && index < this.sections.length) { -+ ChunkSection chunksection = this.sections[index]; -+ -+ if (chunksection != null) { -+ return chunksection.blockIds.a((j & 15) << 8 | (k & 15) << 4 | i & 15).getFluid(); - } -+ // Paper end - } - - return FluidTypes.EMPTY.h(); -- } catch (Throwable throwable) { -+ /*} catch (Throwable throwable) { // Paper - remove try catch - CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -@@ -450,6 +453,7 @@ public class Chunk implements IChunkAccess { - }); - throw new ReportedException(crashreport); - } -+ */ // Paper - remove try catch - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 4bc26a7a4ae91aac90c256758ec8868d83027c0c..973aa060d6964c7d470bc7aff89b879daf1df153 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -45,7 +45,7 @@ public class ChunkSection { - } - - public Fluid b(int i, int j, int k) { -- return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); -+ return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. - } - - public void a() { diff --git a/Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch b/Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch deleted file mode 100644 index 39ac08740ad7..000000000000 --- a/Spigot-Server-Patches/0416-Optimise-TickListServer-by-rewriting-it.patch +++ /dev/null @@ -1,1267 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 14 Feb 2020 01:24:39 -0800 -Subject: [PATCH] Optimise TickListServer by rewriting it - -In my profiling TickListServer showed up as -~10% for saving chunks and ~5% for the scheduling -of items on a server with ~90 players at -view distance = 5. Most of the performance -loss is unneccessary. - -TickListServer has numerous performance issues: - 1. Handling scheduled items is O(nlogn) - 2. Getting scheduled items for a chunk is O(n), - with n being the the number of scheduled items - for all chunks (hits saving very hard) - 3. Checking if an item is scheduled for the current tick is O(n), - with n being the number of items scheduled for current tick - 4. Items not in ticking chunks are churned in the scheduler - -The biggest issues are 4 & 2. - -We solve 1 by splitting up scheduled items into short and long scheduled, -where we expect the vast majority of our entries to be in the short scheduled -set. Handling short scheduled items is O(n) due to how the comparison -process is reduced to mapping. See TickListServerInterval. However, -this isn't memory-efficient - which is why long scheduled exists. -Long scheduled is handled the same as TickListServer. - -2 is solved by mapping what entries are in what chunks. - -3 is solved by mapping what blocks have what scheduled for them. - -4 is solved by moving the items that are not in ticking chunks -into a map of entries for that chunk. Once the chunk is moved -to ticking, the items are re-scheduled. - -This patch has also added two flags to debug excessive tick delays: --Dpaper.ticklist-warn-on-excessive-delay=true (false by default) -and -Dpaper.ticklist-excessive-delay-threshold=ticks which -sets the excessive tick delay to the specified ticks (defaults to -60 * 20 ticks, aka 60 seconds) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f52d97c01 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -354,6 +354,13 @@ public class PaperConfig { - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } - -+ public static boolean useOptimizedTickList = true; -+ private static void useOptimizedTickList() { -+ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config -+ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); -+ } -+ } -+ - public static boolean asyncChunks = false; - private static void asyncChunks() { - ConfigurationSection section; -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8918bad880d6eeed30db39b6326b2f65e24edf45 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -@@ -0,0 +1,628 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import java.util.function.Function; -+import net.minecraft.CrashReport; -+import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ReportedException; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import java.util.ArrayDeque; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.List; -+import java.util.function.Consumer; -+import java.util.function.Predicate; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+import net.minecraft.world.level.TickListServer; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+ -+public final class PaperTickList extends TickListServer { // extend to avoid breaking ABI -+ -+ // in the order the state is expected to change (mostly) -+ public static final int STATE_UNSCHEDULED = 1 << 0; -+ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick -+ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick -+ public static final int STATE_TICKING = 1 << 3; -+ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled -+ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick -+ -+ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds -+ -+ private final WorldServer world; -+ private final Predicate excludeFromScheduling; -+ private final Function getMinecraftKeyFrom; -+ //private final Function getObjectFronMinecraftKey; -+ private final Consumer> tickFunction; -+ -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ private final co.aikar.timings.Timing timingFinished; -+ -+ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... -+ // try to alleviate with a very small load factor -+ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); -+ -+ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) -+ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ -+ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); -+ -+ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; -+ { -+ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { -+ this.shortScheduled[i] = new TickListServerInterval<>(); -+ } -+ } -+ private int shortScheduledIndex; -+ -+ private long currentTick; -+ -+ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); -+ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl -+ -+ // assume index < length -+ private static int getWrappedIndex(final int start, final int length, final int index) { -+ final int next = start + index; -+ return next < length ? next : next - length; -+ } -+ -+ private static int getNextIndex(final int curr, final int length) { -+ final int next = curr + 1; -+ return next < length ? next : 0; -+ } -+ -+ public PaperTickList(final WorldServer world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, -+ final Consumer> tickFunction, final String timingsType) { -+ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); -+ this.world = world; -+ this.excludeFromScheduling = excludeFromScheduling; -+ this.getMinecraftKeyFrom = getMinecraftKeyFrom; -+ this.tickFunction = tickFunction; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper -+ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); -+ this.currentTick = this.world.getTime(); -+ } -+ -+ private void queueEntryForTick(final NextTickListEntry entry, final ChunkProviderServer chunkProvider) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { -+ this.toTickThisTick.add(entry); -+ entry.tickState = STATE_PENDING_TICK; -+ } else { -+ // we dump them to a map to avoid constantly re-scheduling them -+ this.addToNotTickingReady(entry); -+ } -+ } -+ } -+ -+ private void addToNotTickingReady(final NextTickListEntry entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { -+ return new ArrayList<>(); -+ }).add(entry); -+ } -+ -+ private void addToSchedule(final NextTickListEntry entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { -+ if (delay < 0) { -+ // longScheduled orders by tick time, short scheduled does not -+ this.longScheduled.add(entry); -+ } else { -+ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); -+ } -+ } else { -+ this.longScheduled.add(entry); -+ } -+ } -+ -+ private void removeEntry(final NextTickListEntry entry) { -+ entry.tickState = STATE_CANCELLED_TICK; -+ // short/long scheduled will skip the entry -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); -+ -+ if (pendingTickingLoad != null) { -+ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { -+ if (pendingTickingLoad.get(i) == entry) { -+ pendingTickingLoad.remove(i); -+ break; -+ } -+ } -+ -+ if (pendingTickingLoad.isEmpty()) { -+ this.pendingChunkTickLoad.remove(chunkKey); -+ } -+ } -+ -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { -+ this.longScheduled.remove(entry); -+ } -+ } -+ -+ public void onChunkSetTicking(final int chunkX, final int chunkZ) { -+ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ if (pending == null) { -+ return; -+ } -+ -+ for (int i = 0, size = pending.size(); i < size; ++i) { -+ final NextTickListEntry entry = pending.get(i); -+ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled -+ this.addToSchedule(entry); -+ } -+ } -+ -+ private void prepare() { -+ final long currentTick = this.currentTick; -+ -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ // here we setup what's going to tick -+ -+ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of -+ // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { -+ // nothing in longScheduled to worry about -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ this.queueEntryForTick(iterator.next(), chunkProvider); -+ } -+ } -+ } else { -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ -+ // combine interval and longScheduled, keeping order -+ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; -+ final Iterator> longScheduledIterator = this.longScheduled.iterator(); -+ NextTickListEntry longCurrent = longScheduledIterator.next(); -+ -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ final NextTickListEntry shortCurrent = iterator.next(); -+ if (longCurrent != null) { -+ // drain longCurrent until we can add shortCurrent -+ while (comparator.compare(longCurrent, shortCurrent) <= 0) { -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ longScheduledIterator.remove(); -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { -+ longCurrent = null; -+ break; -+ } -+ } else { -+ longCurrent = null; -+ break; -+ } -+ } -+ } -+ this.queueEntryForTick(shortCurrent, chunkProvider); -+ } -+ } -+ -+ // add remaining from long scheduled -+ for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { -+ break; -+ } -+ longScheduledIterator.remove(); -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ } else { -+ break; -+ } -+ } -+ } -+ } -+ -+ private boolean warnedAboutDesync; -+ -+ @Override -+ public void nextTick() { -+ ++this.currentTick; -+ if (this.currentTick != this.world.getTime()) { -+ if (!this.warnedAboutDesync) { -+ this.warnedAboutDesync = true; -+ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); -+ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); -+ } -+ } -+ } -+ -+ @Override -+ public void tick() { -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ this.world.getMethodProfiler().enter("cleaning"); -+ this.timingCleanup.startTiming(); -+ -+ this.prepare(); -+ -+ // this must be done here in case something schedules in the tick code -+ this.shortScheduled[this.shortScheduledIndex].clear(); -+ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); -+ -+ this.timingCleanup.stopTiming(); -+ this.world.getMethodProfiler().exitEnter("ticking"); -+ this.timingTicking.startTiming(); -+ -+ for (final NextTickListEntry toTick : this.toTickThisTick) { -+ if (toTick.tickState != STATE_PENDING_TICK) { -+ // onTickEnd gets called at end of tick -+ continue; -+ } -+ try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { -+ toTick.tickState = STATE_TICKING; -+ this.tickFunction.accept(toTick); -+ if (toTick.tickState == STATE_TICKING) { -+ toTick.tickState = STATE_TICKED; -+ } // else it's STATE_CANCELLED_TICK -+ } else { -+ // re-schedule eventually -+ toTick.tickState = STATE_SCHEDULED; -+ this.addToNotTickingReady(toTick); -+ } -+ } catch (final Throwable thr) { -+ // start copy from TickListServer // TODO check on update -+ CrashReport crashreport = CrashReport.a(thr, "Exception while ticking"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being ticked"); -+ -+ CrashReportSystemDetails.a(crashreportsystemdetails, toTick.getPosition(), (IBlockData) null); -+ throw new ReportedException(crashreport); -+ // end copy from TickListServer -+ } -+ } -+ -+ this.timingTicking.stopTiming(); -+ this.world.getMethodProfiler().exit(); -+ this.timingFinished.startTiming(); -+ -+ // finished ticking, actual cleanup time -+ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { -+ final NextTickListEntry entry = this.toTickThisTick.poll(); -+ if (entry.tickState != STATE_SCHEDULED) { -+ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not -+ // call onTickEnd for them -+ this.onTickEnd(entry); -+ } -+ } -+ -+ this.timingFinished.stopTiming(); -+ } -+ -+ private void onTickEnd(final NextTickListEntry entry) { -+ if (entry.tickState == STATE_CANCELLED_TICK) { -+ return; -+ } -+ entry.tickState = STATE_UNSCHEDULED; -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ // already removed from longScheduled or shortScheduled -+ } -+ -+ @Override -+ public boolean isPendingTickThisTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public boolean isScheduledForTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public void schedule(BlockPosition blockPosition, T t, int i, TickListPriority tickListPriority) { -+ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); -+ } -+ -+ public void schedule(final NextTickListEntry entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); -+ } -+ -+ public void schedule(final BlockPosition pos, final T data, final long targetTick, final TickListPriority priority) { -+ final NextTickListEntry entry = new NextTickListEntry<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { -+ return; -+ } -+ -+ if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; -+ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { -+ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); -+ } -+ } -+ -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); -+ -+ if (currentEntries.isEmpty()) { -+ currentEntries.add(entry); -+ } else { -+ for (int i = 0, size = currentEntries.size(); i < size; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ -+ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { -+ // can't add -+ return; -+ } -+ } -+ currentEntries.add(entry); -+ } -+ -+ entry.tickState = STATE_SCHEDULED; -+ -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { -+ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ }).add(entry); -+ -+ this.addToSchedule(entry); -+ } -+ -+ public void scheduleAll(final Iterator> iterator) { -+ while (iterator.hasNext()) { -+ this.schedule(iterator.next()); -+ } -+ } -+ -+ // this is not the standard interception calculation, but it's the one vanilla uses -+ // i.e the y value is ignored? the x, z calc isn't correct? -+ // however for the copy op they use the correct intersection, after using this one of course... -+ private static boolean isBlockInSortof(final StructureBoundingBox boundingBox, final BlockPosition pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); -+ } -+ -+ @Override -+ public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { -+ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above -+ } -+ -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive -+ -+ final int xChunksLength = (upperChunkX - lowerChunkX + 1); -+ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); -+ -+ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; -+ -+ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); -+ int totalEntries = 0; -+ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { -+ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { -+ // todo optimize -+ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); -+ final int index = offset + currChunkX + xChunksLength * currChunkZ; -+ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); -+ if (set != null) { -+ totalEntries += set.size(); -+ } -+ } -+ } -+ -+ final List> ret = new ArrayList<>(totalEntries); -+ -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ MCUtil.mergeSortedSets((NextTickListEntry entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { -+ return; -+ } -+ final int tickState = entry.tickState; -+ if ((tickState & matchOne) == 0) { -+ return; -+ } -+ -+ ret.add(entry); -+ return; -+ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); -+ Iterator> iterator = list.iterator(); -+ -+ while (iterator.hasNext()) { -+ NextTickListEntry nextticklistentry = iterator.next(); -+ -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPosition blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); -+ -+ this.schedule(new NextTickListEntry<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); -+ } -+ } -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { -+ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks -+ // not at ticking status, and ticking status requires neighbours loaded -+ // so with this method we will reduce scheduler churning -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); -+ -+ if (entries == null) { -+ return Collections.emptyList(); -+ } -+ -+ final List> ret = new ArrayList<>(entries.size()); -+ -+ for (NextTickListEntry entry : entries) { -+ if ((entry.tickState & matchOne) == 0) { -+ continue; -+ } -+ ret.add(entry); -+ } -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); -+ -+ return TickListServer.serialize(this.getMinecraftKeyFrom, list, this.currentTick); -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public int getTotalScheduledEntries() { -+ // good thing this is only used in debug reports // TODO check on update -+ int ret = 0; -+ -+ for (NextTickListEntry entry : this.longScheduled) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ -+ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { -+ ArrayList> list = iterator.next().getValue(); -+ -+ for (NextTickListEntry entry : list) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ -+ for (TickListServerInterval interval : this.shortScheduled) { -+ for (Iterable> set : interval.byPriority) { -+ for (NextTickListEntry entry : set) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ } -+ -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b58432a8b60670562baf00cf5279c702aaad4557 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -@@ -0,0 +1,41 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import com.destroystokyo.paper.util.set.LinkedSortedSet; -+import java.util.Comparator; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+ -+// represents a set of entries to tick at a specified time -+public final class TickListServerInterval { -+ -+ public static final int TOTAL_PRIORITIES = TickListPriority.values().length; -+ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { -+ return Long.compare(entry1.getId(), entry2.getId()); -+ }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)NextTickListEntry.comparator(); -+ -+ // we do not record the interval, this class is meant to be used on a ring buffer -+ -+ // inlined enum map for TickListPriority -+ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; -+ -+ { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); -+ } -+ } -+ -+ public void addEntryLast(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); -+ } -+ -+ public void addEntryFirst(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); -+ } -+ -+ public void clear() { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i].clear(); // O(1) clear -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f341f06fc ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -@@ -0,0 +1,142 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+public final class LinkedSortedSet implements Iterable { -+ -+ public final Comparator comparator; -+ -+ protected Link head; -+ protected Link tail; -+ -+ public LinkedSortedSet() { -+ this((Comparator)Comparator.naturalOrder()); -+ } -+ -+ public LinkedSortedSet(final Comparator comparator) { -+ this.comparator = comparator; -+ } -+ -+ public void clear() { -+ this.head = this.tail = null; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Link next = LinkedSortedSet.this.head; -+ -+ @Override -+ public boolean hasNext() { -+ return this.next != null; -+ } -+ -+ @Override -+ public E next() { -+ final Link next = this.next; -+ if (next == null) { -+ throw new NoSuchElementException(); -+ } -+ this.next = next.next; -+ return next.element; -+ } -+ }; -+ } -+ -+ public boolean addLast(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.tail; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) < 0) { -+ Link prev = curr; -+ curr = curr.prev; -+ if (curr != null) { -+ continue; -+ } -+ this.head = prev.prev = new Link<>(element, null, prev); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert after curr -+ final Link next = curr.next; -+ final Link insert = new Link<>(element, curr, next); -+ curr.next = insert; -+ -+ if (next == null) { -+ this.tail = insert; -+ } else { -+ next.prev = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ public boolean addFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.head; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) > 0) { -+ Link prev = curr; -+ curr = curr.next; -+ if (curr != null) { -+ continue; -+ } -+ this.tail = prev.next = new Link<>(element, prev, null); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert before curr -+ final Link prev = curr.prev; -+ final Link insert = new Link<>(element, prev, curr); -+ curr.prev = insert; -+ -+ if (prev == null) { -+ this.head = insert; -+ } else { -+ prev.next = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ protected static final class Link { -+ public E element; -+ public Link prev; -+ public Link next; -+ -+ public Link() {} -+ -+ public Link(final E element) { -+ this.element = element; -+ } -+ -+ public Link(final E element, final Link prev, final Link next) { -+ this.element = element; -+ this.prev = prev; -+ this.next = next; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 8c0aeb51f5e230fd6109e750732eb54559bc9637..1fb931d4c0720a5e496030e25c865771aea3ec70 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -111,6 +111,7 @@ public class BlockPosition extends BaseBlockPosition { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } - -+ public final BlockPosition add(BaseBlockPosition baseblockposition) { return this.a(baseblockposition); } // Paper - OBFHELPER - public BlockPosition a(BaseBlockPosition baseblockposition) { - return this.b(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0c8864eeae6e3b449514f52d95c17f2e4a304f0e..a444f6214b90f7707be2265f4b2ab12632986c53 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -21,6 +21,7 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.MathHelper; - import net.minecraft.util.profiling.GameProfilerFiller; -@@ -217,6 +218,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ public final boolean isTickingReadyMainThread(BlockPosition pos) { -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(pos)); -+ return chunk != null && chunk.isTickingReady(); -+ } -+ // Paper end - rewrite ticklistserver -+ - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; - this.serverThreadQueue = new ChunkProviderServer.a(worldserver); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 6433463938d8bb717840c8f57fe6e7079e1030f2..445dba8ed210407664904b707c36c78a76f25510 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -496,7 +496,9 @@ public class PlayerChunk { - PlayerChunk.this.isTickingReady = true; - - -- -+ // Paper start - rewrite ticklistserver -+ PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z); -+ // Paper end - rewrite ticklistserver - - } - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index cf6e9a949a864df12ca1670dbc456494d2b5e473..5b1dfcf231e9736552b8a2ad9cd91306dd36e5d5 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -298,6 +298,15 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ void onChunkSetTicking(int chunkX, int chunkZ) { -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListBlock).onChunkSetTicking(chunkX, chunkZ); -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListFluid).onChunkSetTicking(chunkX, chunkZ); -+ } -+ } -+ // Paper end - rewrite ticklistserver -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -305,12 +314,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); - // CraftBukkit end -- this.nextTickListBlock = new TickListServer<>(this, (block) -> { -- return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -- this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } else { -+ this.nextTickListBlock = new TickListServer<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -645,7 +663,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (this.Q) { - long i = this.worldData.getTime() + 1L; - -- this.worldDataServer.setTime(i); -+ this.worldDataServer.setTime(i); // Paper - diff on change, we want the below to be ran right after this -+ this.nextTickListBlock.nextTick(); // Paper -+ this.nextTickListFluid.nextTick(); // Paper - this.worldDataServer.u().a(this.server, i); - if (this.worldData.q().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) { - this.setDayTime(this.worldData.getDayTime() + 1L); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 37b7dd82a227a88b720c13a813dd7e8caf803e03..8eb3084def3aa8776d32f8a3c942c95d24ccea3f 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPosition; - public class NextTickListEntry { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T e; -- public final BlockPosition a; -- public final long b; -- public final TickListPriority c; -- private final long f; -+ private final T e; public final T getData() { return this.e; } // Paper - OBFHELPER -+ public final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Paper - OBFHELPER -+ public final long b; public final long getTargetTick() { return this.b; } // Paper - OBFHELPER -+ public final TickListPriority c; public final TickListPriority getPriority() { return this.c; } // Paper - OBFHELPER -+ private final long f; public final long getId() { return this.f; } // Paper - OBFHELPER -+ private final int hash; // Paper -+ public int tickState; // Paper - - public NextTickListEntry(BlockPosition blockposition, T t0) { - this(blockposition, t0, 0L, TickListPriority.NORMAL); -@@ -22,6 +24,7 @@ public class NextTickListEntry { - this.e = t0; - this.b = i; - this.c = ticklistpriority; -+ this.hash = this.computeHash(); // Paper - } - - public boolean equals(Object object) { -@@ -34,19 +37,31 @@ public class NextTickListEntry { - } - } - -+ // Paper start - optimize hashcode -+ @Override - public int hashCode() { -+ return this.hash; -+ } -+ public final int computeHash() { -+ // Paper end - optimize hashcode - return this.a.hashCode(); - } - -- public static Comparator a() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix -- }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return NextTickListEntry.a(); } // Paper - OBFHELPER -+ public static Comparator a() { -+ return (Comparator)(Comparator)(NextTickListEntry nextticklistentry, NextTickListEntry nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); -+ -+ if (i != 0) { -+ return i; -+ } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); -+ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); -+ } -+ }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.e + ": " + this.a + ", " + this.b + ", " + this.c + ", " + this.f; -diff --git a/src/main/java/net/minecraft/world/level/TickListChunk.java b/src/main/java/net/minecraft/world/level/TickListChunk.java -index c3cb513d0d107ecb43e98960b25054626aa6a03f..fd293e11ec62a41a53c1e5238cb1219349d446d4 100644 ---- a/src/main/java/net/minecraft/world/level/TickListChunk.java -+++ b/src/main/java/net/minecraft/world/level/TickListChunk.java -@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; - - public class TickListChunk implements TickList { - -@@ -61,6 +62,8 @@ public class TickListChunk implements TickList { - return nbttaglist; - } - -+ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static TickListChunk a(NBTTagList nbttaglist, Function function, Function function1) { - List> list = Lists.newArrayList(); - -@@ -71,7 +74,14 @@ public class TickListChunk implements TickList { - if (t0 != null) { - BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new TickListChunk.a<>(t0, blockposition, nbttagcompound.getInt("t"), TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); -+ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); -+ continue; -+ } -+ list.add(new TickListChunk.a<>(t0, blockposition, delay, TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper end - clean up broken entries - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index c221e5caf518b8c588390e438346fa58fa8c5a38..4fd89bbe6ce578fd3a166bcfbbe41908a7bb4753 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -50,7 +50,16 @@ public class TickListServer implements TickList { - private final co.aikar.timings.Timing timingTicking; // Paper - // Paper end - -+ // Paper start -+ public void nextTick() {} -+ // Paper end -+ - public void b() { -+ // Paper start - allow overriding -+ this.tick(); -+ } -+ public void tick() { -+ // Paper end - int i = this.nextTickList.size(); - - if (false) { // CraftBukkit -@@ -118,10 +127,20 @@ public class TickListServer implements TickList { - - @Override - public boolean b(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(blockposition, t0); -+ } -+ public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.f.contains(new NextTickListEntry<>(blockposition, t0)); - } - - public List> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, flag, flag1); -+ } -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; -@@ -131,6 +150,11 @@ public class TickListServer implements TickList { - } - - public List> a(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(structureboundingbox, flag, flag1); -+ } -+ public List> getEntriesInBoundingBox(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end - List> list = this.a((List) null, this.nextTickList, structureboundingbox, flag); - - if (flag && list != null) { -@@ -170,6 +194,11 @@ public class TickListServer implements TickList { - } - - public void a(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper start - allow overriding -+ this.copy(structureboundingbox, blockposition); -+ } -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper end - List> list = this.a(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - -@@ -187,11 +216,17 @@ public class TickListServer implements TickList { - } - - public NBTTagList a(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper end - List> list = this.a(chunkcoordintpair, false, true); - - return a(this.b, list, this.e.getTime()); - } - -+ public static NBTTagList serialize(Function function, Iterable> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER - private static NBTTagList a(Function function, Iterable> iterable, long i) { - NBTTagList nbttaglist = new NBTTagList(); - Iterator iterator = iterable.iterator(); -@@ -214,11 +249,21 @@ public class TickListServer implements TickList { - - @Override - public boolean a(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isScheduledForTick(blockposition, t0); -+ } -+ public boolean isScheduledForTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.nextTickListHash.contains(new NextTickListEntry<>(blockposition, t0)); - } - - @Override - public void a(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper start - allow overriding -+ this.schedule(blockposition, t0, i, ticklistpriority); -+ } -+ public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper end - if (!this.a.test(t0)) { - this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.e.getTime(), ticklistpriority)); - } -@@ -234,6 +279,11 @@ public class TickListServer implements TickList { - } - - public int a() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.nextTickListHash.size(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -index b5d6c8163c686c31375fb645d7721af06c01df40..fb4b8d7167ad7f1d24d40bbbda5f52e278f25895 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -@@ -8,12 +8,12 @@ import net.minecraft.nbt.NBTTagIntArray; - - public class StructureBoundingBox { - -- public int a; -- public int b; -- public int c; -- public int d; -- public int e; -- public int f; -+ public int a; public final int getMinX() { return this.a; } // Paper - OBFHELPER -+ public int b; public final int getMinY() { return this.b; } // Paper - OBFHELPER -+ public int c; public final int getMinZ() { return this.c; } // Paper - OBFHELPER -+ public int d; public final int getMaxX() { return this.d; } // Paper - OBFHELPER -+ public int e; public final int getMaxY() { return this.e; } // Paper - OBFHELPER -+ public int f; public final int getMaxZ() { return this.f; } // Paper - OBFHELPER - - public StructureBoundingBox() {} - -@@ -92,6 +92,7 @@ public class StructureBoundingBox { - this.e = 512; - } - -+ public final boolean intersects(StructureBoundingBox boundingBox) { return this.b(boundingBox); } // Paper - OBFHELPER - public boolean b(StructureBoundingBox structureboundingbox) { - return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e; - } -@@ -126,6 +127,7 @@ public class StructureBoundingBox { - this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER - public boolean b(BaseBlockPosition baseblockposition) { - return baseblockposition.getX() >= this.a && baseblockposition.getX() <= this.d && baseblockposition.getZ() >= this.c && baseblockposition.getZ() <= this.f && baseblockposition.getY() >= this.b && baseblockposition.getY() <= this.e; - } diff --git a/Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch b/Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch deleted file mode 100644 index 6d6444c726bf..000000000000 --- a/Spigot-Server-Patches/0417-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 1 Feb 2020 16:50:39 +0100 -Subject: [PATCH] Pillager patrol spawn settings and per player options - -This adds config options for defining the spawn chance, spawn delay and -spawn start day as well as toggles for handling the spawn delay and -start day per player. (Based on the time played statistic) -When not per player it will use the Vanilla mechanic of one delay per -world and the world age for the start day. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -582,10 +582,21 @@ public class PaperWorldConfig { - } - - public boolean disablePillagerPatrols = false; -+ public double patrolSpawnChance = 0.2; -+ public boolean patrolPerPlayerDelay = false; -+ public int patrolDelay = 12000; -+ public boolean patrolPerPlayerStart = false; -+ public int patrolStartDay = 5; - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); -+ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); -+ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); -+ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); -+ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); - } - -+ - public boolean entitiesTargetWithFollowRange = false; - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index f5212a7ec0f2dd27fb1c06e0dfc37f2aff595fde..c0e32b13e79fa6b34ac9448d2f74339bb771274f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -216,6 +216,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean viewingCredits; - private int containerUpdateDelay; // Paper - public long loginTime; // Paper -+ public int patrolSpawnDelay; // Paper - per player patrol spawns - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatisticWrapper.java b/src/main/java/net/minecraft/stats/StatisticWrapper.java -index c1a694c4a773a41cdefca6b154711f7fc0a7fcaa..00d79ccf9c65acadc030ab1796cff4598392cb6a 100644 ---- a/src/main/java/net/minecraft/stats/StatisticWrapper.java -+++ b/src/main/java/net/minecraft/stats/StatisticWrapper.java -@@ -28,6 +28,7 @@ public class StatisticWrapper implements Iterable> { - return this.b.values().iterator(); - } - -+ public final Statistic get(T t) { return this.b(t); }; // Paper - OBFHELPER - public Statistic b(T t0) { - return this.a(t0, Counter.DEFAULT); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index cba98adb7f2711fb97c7e4120d962f46a59682e7..111c4c1fad2f1839a8c6b7c277cf801236ae1685 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -3,7 +3,9 @@ package net.minecraft.world.level.levelgen; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.stats.StatisticList; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; -@@ -20,13 +22,13 @@ import net.minecraft.world.level.block.state.IBlockData; - - public class MobSpawnerPatrol implements MobSpawner { - -- private int a; -+ private int a;private int getSpawnDelay() { return a; } private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER - - public MobSpawnerPatrol() {} - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -- if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper -+ if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { -@@ -34,23 +36,51 @@ public class MobSpawnerPatrol implements MobSpawner { - } else { - Random random = worldserver.random; - -- --this.a; -- if (this.a > 0) { -+ // Paper start - Patrol settings -+ // Random player selection moved up for per player spawning and configuration -+ int j = worldserver.getPlayers().size(); -+ if (j < 1) { - return 0; -+ } -+ -+ EntityPlayer entityhuman = worldserver.getPlayers().get(random.nextInt(j)); -+ if (entityhuman.isSpectator()) { -+ return 0; -+ } -+ -+ int patrolSpawnDelay; -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ --entityhuman.patrolSpawnDelay; -+ patrolSpawnDelay = entityhuman.patrolSpawnDelay; - } else { -- this.a += 12000 + random.nextInt(1200); -- long i = worldserver.getDayTime() / 24000L; -+ setSpawnDelay(getSpawnDelay() - 1); -+ patrolSpawnDelay = getSpawnDelay(); -+ } -+ -+ if (patrolSpawnDelay > 0) { -+ return 0; -+ } else { -+ long days; -+ if (worldserver.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang -+ } else { -+ days = worldserver.getDayTime() / 24000L; -+ } -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ entityhuman.patrolSpawnDelay += worldserver.paperConfig.patrolDelay + random.nextInt(1200); -+ } else { -+ setSpawnDelay(getSpawnDelay() + worldserver.paperConfig.patrolDelay + random.nextInt(1200)); -+ } - -- if (i >= 5L && worldserver.isDay()) { -- if (random.nextInt(5) != 0) { -+ if (days >= worldserver.paperConfig.patrolStartDay && worldserver.isDay()) { -+ if (random.nextDouble() >= worldserver.paperConfig.patrolSpawnChance) { -+ // Paper end - return 0; - } else { -- int j = worldserver.getPlayers().size(); - - if (j < 1) { - return 0; - } else { -- EntityHuman entityhuman = (EntityHuman) worldserver.getPlayers().get(random.nextInt(j)); - - if (entityhuman.isSpectator()) { - return 0; diff --git a/Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch b/Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch deleted file mode 100644 index 0eaa76de2fc5..000000000000 --- a/Spigot-Server-Patches/0418-Ensure-Entity-is-never-double-registered.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 29 Mar 2020 18:26:14 -0400 -Subject: [PATCH] Ensure Entity is never double registered - -If something calls register twice, and the world is ticking, it could be -enqueued to add twice. - -Vs behavior of non ticking of just overwriting state. - -We will now simply log a warning when this happens instead of crashing the server. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 5b1dfcf231e9736552b8a2ad9cd91306dd36e5d5..b97682e967ea1d9a9f9142dba4089a9f15302913 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -649,6 +649,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - Entity entity2; - - while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) { -+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers - this.registerEntity(entity2); - } - -@@ -1406,6 +1407,19 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - public void unregisterEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot -+ // Paper start - fix entity registration issues -+ if (entity instanceof EntityComplexPart) { -+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. -+ this.entitiesById.remove(entity.getId(), entity); -+ return; -+ } -+ if (!entity.valid) { -+ // Someone called remove before we ever got added, cancel the add. -+ entity.isQueuedForRegister = false; -+ return; -+ } -+ // Paper end - // Spigot start - if ( entity instanceof EntityHuman ) - { -@@ -1472,9 +1486,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void registerEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot -+ // Paper start - don't double enqueue entity registration -+ //noinspection ObjectEquality -+ if (this.entitiesById.get(entity.getId()) == entity) { -+ LOGGER.error(entity + " was already registered!"); -+ new Throwable().printStackTrace(); -+ return; -+ } -+ // Paper end - if (this.tickingEntities) { -- this.entitiesToAdd.add(entity); -+ if (!entity.isQueuedForRegister) { // Paper -+ this.entitiesToAdd.add(entity); -+ entity.isQueuedForRegister = true; // Paper -+ } - } else { -+ entity.isQueuedForRegister = false; // Paper - this.entitiesById.put(entity.getId(), entity); - if (entity instanceof EntityEnderDragon) { - EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ(); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 68fdb01c3f11c3b060d3d621099d67f6b29431d6..f95aa9b4cc53c1e3258b7b32249ec1c3ef4ae2f1 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -148,6 +148,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public boolean isQueuedForRegister = false; - public static Random SHARED_RANDOM = new Random() { - private boolean locked = false; - @Override diff --git a/Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch b/Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch deleted file mode 100644 index 87b2b3c46a45..000000000000 --- a/Spigot-Server-Patches/0419-Fix-unregistering-entities-from-unloading-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:01:45 -0400 -Subject: [PATCH] Fix unregistering entities from unloading chunks - -CraftBukkit caused a regression here by making unloading chunks not -have a ticket added and returning unloaded future. - -This caused entities who were killed in same tick their chunk is unloading -to not be able to be removed from the chunk. - -This then results in dead entities lingering in the Chunk. - -Combine that with a buggy detail of the previous implementation of -the Dupe UUID patch, then this was the likely source of the "Ghost entities" - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index b97682e967ea1d9a9f9142dba4089a9f15302913..a71531d6d329b11b9ad535786d26c4c2327bcbb9 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1565,9 +1565,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - private void removeEntityFromChunk(Entity entity) { -- IChunkAccess ichunkaccess = chunkProvider.getChunkUnchecked(entity.chunkX, entity.chunkZ); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). -+ Chunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways - -- if (ichunkaccess instanceof Chunk) { -+ if (ichunkaccess != null) { // Paper - ((Chunk) ichunkaccess).b(entity); - } - diff --git a/Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch deleted file mode 100644 index f765b7f7b5d7..000000000000 --- a/Spigot-Server-Patches/0420-Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:50:42 -0400 -Subject: [PATCH] Remote Connections shouldn't hold up shutdown - -Bugs in the connection logic appears to leave stale connections even, preventing shutdown - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 2d42b863b3fd83d1ee0532d1fcb63861641ec47b..557f80accfa36b495c9a8cffdab2e248c1cbb514 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -400,11 +400,11 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - } - - if (this.remoteControlListener != null) { -- this.remoteControlListener.b(); -+ //this.remoteControlListener.b(); // Paper - don't wait for remote connections - } - - if (this.remoteStatusListener != null) { -- this.remoteStatusListener.b(); -+ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections - } - - System.exit(0); // CraftBukkit diff --git a/Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch deleted file mode 100644 index 290489e39821..000000000000 --- a/Spigot-Server-Patches/0421-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 17 Mar 2020 14:18:50 -0500 -Subject: [PATCH] Do not allow bees to load chunks for beehives - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 7ce8eaeb9af3547869f467910b6a458118c63c1f..1d1f71a995a99b2101891a7a5bda7bec5d67f118 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -358,6 +358,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (this.hivePos == null) { - return false; - } else { -+ if (!this.world.isLoadedAndInBounds(hivePos)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d(); -@@ -390,6 +391,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - } - - private boolean i(BlockPosition blockposition) { -+ if (!this.world.isLoadedAndInBounds(blockposition)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(blockposition); - - return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false; -@@ -632,6 +634,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - @Override - public boolean g() { - if (EntityBee.this.hasHivePos() && EntityBee.this.fd() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { -@@ -655,6 +658,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - @Override - public void c() { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { diff --git a/Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch deleted file mode 100644 index 3a8c5c03df96..000000000000 --- a/Spigot-Server-Patches/0422-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 01:42:39 -0400 -Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server - -Suspected case would be around the technique used in .stopRiding -Stack will identify any causer of this and warn instead of crashing. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index baef98331c07b0f8c95351f39c5e471f96a59c05..c7619bba9115e8695b5aea2b4d059bea577e748e 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1503,6 +1503,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - protected void addEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot -+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server -+ if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -+ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.world.getWorld().getName() -+ + ": " + entity + (this.trackedEntities.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) -+ .printStackTrace(); -+ return; -+ } -+ // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); - int i = entitytypes.getChunkRange() * 16; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index a71531d6d329b11b9ad535786d26c4c2327bcbb9..8159baec6e862580dc340d8fd7c16013ec8f0e66 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1531,7 +1531,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.getChunkProvider().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { - this.navigators.add(((EntityDrowned) entity).navigationWater); -@@ -1542,6 +1542,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch b/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index b289eb0159b0..000000000000 --- a/Spigot-Server-Patches/0423-Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9af1d81475d2def60a682ed23e88f1afbbc4c7e6..0a99ee6221c46043ecdf9e9df7a064aa63ee6951 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -61,6 +61,7 @@ import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.sounds.SoundCategory; -@@ -74,6 +75,7 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -809,6 +811,7 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f95aa9b4cc53c1e3258b7b32249ec1c3ef4ae2f1..7bce3722fb00194f5a913c0b9866b73cfc74611d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -169,6 +169,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private CraftEntity bukkitEntity; - - PlayerChunkMap.EntityTracker tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/ICollisionAccess.java b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -index fcf6cc86e3b5d9afe3ab3b3fba2ec13846ed0b4c..fcb3e2f9dea97138e0fd4cd2eb11b54799e1d3b5 100644 ---- a/src/main/java/net/minecraft/world/level/ICollisionAccess.java -+++ b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -@@ -54,7 +54,9 @@ public interface ICollisionAccess extends IBlockAccess { - } - - default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index fa3421c9cd8531618827627e9c524a8df77c4c58..d0cc8677f2be422722160fee9b71894b5ddd3186 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -7,6 +7,9 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.CursorPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.RegionLimitedWorldAccess; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShapes; - public class VoxelShapeSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity a; -+ private final Entity a; final Entity getEntity() { return this.a; } // Paper - OBFHELPER - private final AxisAlignedBB b; - private final VoxelShapeCollision c; - private final CursorPosition d; -- private final BlockPosition.MutableBlockPosition e; -+ private final BlockPosition.MutableBlockPosition e; final BlockPosition.MutableBlockPosition getMutablePos() { return this.e; } // Paper - OBFHELPER - private final VoxelShape f; -- private final ICollisionAccess g; -+ private final ICollisionAccess g; final ICollisionAccess getCollisionAccess() { return this.g; } // Paper - OBFHELPER - private boolean h; - private final BiPredicate i; - -@@ -64,23 +67,37 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - boolean a(Consumer consumer) { - while (true) { - if (this.d.a()) { -- int i = this.d.b(); -- int j = this.d.c(); -- int k = this.d.d(); -+ int i = this.d.b(); final int x = i; -+ int j = this.d.c(); final int y = j; -+ int k = this.d.d(); final int z = k; - int l = this.d.e(); - - if (l == 3) { - continue; - } - -- IBlockAccess iblockaccess = this.a(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.locX(), y, entity.locZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof RegionLimitedWorldAccess; -+ IBlockData iblockdata = isRegionLimited ? Blocks.VOID_AIR.getBlockData() : ((!far && entity instanceof EntityPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getType(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.e.d(i, j, k); -- IBlockData iblockdata = iblockaccess.getType(this.e); -+ // Paper - moved up -+ // Paper end - - if (!this.i.test(iblockdata, this.e) || l == 1 && !iblockdata.d() || l == 2 && !iblockdata.a(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index cf32a4f63e8e59535c02a3f9c57f98833a2b0e83..24ecac40625629b0bbe460e7fc984b147ede1f1f 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -249,7 +249,8 @@ public final class VoxelShapes { - - if (k2 < 3) { - blockposition_mutableblockposition.a(enumaxiscycle1, i2, j2, l1); -- IBlockData iblockdata = iworldreader.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); diff --git a/Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch b/Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch deleted file mode 100644 index 9b85066c219d..000000000000 --- a/Spigot-Server-Patches/0424-Don-t-tick-dead-players.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 17:16:48 -0400 -Subject: [PATCH] Don't tick dead players - -Causes sync chunk loads and who knows what all else. -This is safe because Spectators are skipped in unloaded chunks too in vanilla. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index c0e32b13e79fa6b34ac9448d2f74339bb771274f..e3721287cc18c8df81d1353084364966eb3f55ab 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -609,7 +609,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public void playerTick() { - try { -- if (!this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { -+ if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } - diff --git a/Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch b/Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch deleted file mode 100644 index 04592576bcb1..000000000000 --- a/Spigot-Server-Patches/0425-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 19:31:16 -0400 -Subject: [PATCH] Dead Player's shouldn't be able to move - -This fixes a lot of game state issues where packets were delayed for processing -due to 1.15's new queue but processed while dead. - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 564dfa98c166fde509044e6e1938efb321ece53d..8981dfacd10cae9de052e1b36ce5181cd0e6752d 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1049,7 +1049,7 @@ public abstract class EntityHuman extends EntityLiving { - - @Override - protected boolean isFrozen() { -- return super.isFrozen() || this.isSleeping(); -+ return super.isFrozen() || this.isSleeping() || dead || !valid; // Paper - player's who are dead or not in a world shouldn't move... - } - - @Override diff --git a/Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch deleted file mode 100644 index a08aa23bac5a..000000000000 --- a/Spigot-Server-Patches/0426-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 03:06:30 -0400 -Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks - -No longer clones visible chunks which is causing massive memory -allocation issues, likely the source of Humongous Objects on large servers. - -Instead we just synchronize, clear and rebuild, reusing the same object buffers -as before with only 2 small objects created (FastIterator/MapEntry) - -This should result in siginificant memory use reduction and improved GC behavior. - -diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e78f0bbdb ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -@@ -0,0 +1,39 @@ -+package com.destroystokyo.paper.util.map; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+ -+public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { -+ -+ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { -+ if (key.length != map.key.length) { -+ key = null; -+ key = new long[map.key.length]; -+ } -+ if (value.length != map.value.length) { -+ value = null; -+ //noinspection unchecked -+ value = (V[]) new Object[map.value.length]; -+ } -+ if (link.length != map.link.length) { -+ link = null; -+ link = new long[map.link.length]; -+ } -+ System.arraycopy(map.key, 0, this.key, 0, map.key.length); -+ System.arraycopy(map.value, 0, this.value, 0, map.value.length); -+ System.arraycopy(map.link, 0, this.link, 0, map.link.length); -+ this.size = map.size; -+ this.mask = map.mask; -+ this.first = map.first; -+ this.last = map.last; -+ this.n = map.n; -+ this.maxFill = map.maxFill; -+ this.containsNullKey = map.containsNullKey; -+ } -+ -+ @Override -+ public Long2ObjectLinkedOpenHashMapFastCopy clone() { -+ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); -+ clone.copyFrom(this); -+ return clone; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 5a410550cfb48505c9de9979465ed1528c8fbf05..9edbde8299bcd127e1727d34ed441f638e716b2a 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -616,7 +616,7 @@ public final class MCUtil { - - WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); - PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); - ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; - List allChunks = new ArrayList<>(visibleChunks.values()); - List players = world.players; -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index a444f6214b90f7707be2265f4b2ab12632986c53..138676e5b03bc80a777a1f4c12f3f4b5316e8dea 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -780,7 +780,7 @@ public class ChunkProviderServer extends IChunkProvider { - entityPlayer.playerNaturallySpawnedEvent.callEvent(); - }; - // Paper end -- this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... -+ this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index c7619bba9115e8695b5aea2b4d059bea577e748e..5ccc70f36616e1bd8cdb8b23315f7422ec5acc61 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -106,8 +106,33 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private static final Logger LOGGER = LogManager.getLogger(); - public static final int GOLDEN_TICKET = 33 + ChunkStatus.b(); -- public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunks; -+ // Paper start - faster copying -+ public final Long2ObjectLinkedOpenHashMap updatingChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying -+ public final Long2ObjectLinkedOpenHashMap visibleChunks = new ProtectedVisibleChunksMap(); // Paper - faster copying -+ -+ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { -+ @Override -+ public PlayerChunk put(long k, PlayerChunk playerChunk) { -+ throw new UnsupportedOperationException("Updating visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk remove(long k) { -+ throw new UnsupportedOperationException("Removing visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk get(long k) { -+ return PlayerChunkMap.this.getVisibleChunk(k); -+ } -+ -+ public PlayerChunk safeGet(long k) { -+ return super.get(k); -+ } -+ } -+ // Paper end -+ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only -+ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed - private final Long2ObjectLinkedOpenHashMap pendingUnload; - public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; -@@ -180,7 +205,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); -- this.visibleChunks = this.updatingChunks.clone(); -+ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning - this.pendingUnload = new Long2ObjectLinkedOpenHashMap(); - this.loadedChunks = new LongOpenHashSet(); - this.unloadQueue = new LongOpenHashSet(); -@@ -272,9 +297,52 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return (PlayerChunk) this.updatingChunks.get(i); - } - -+ // Paper start - remove cloning of visible chunks unless accessed as a collection async -+ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); -+ private boolean isIterating = false; -+ private boolean hasPendingVisibleUpdate = false; -+ public void forEachVisibleChunk(java.util.function.Consumer consumer) { -+ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); -+ boolean prev = isIterating; -+ isIterating = true; -+ try { -+ for (PlayerChunk value : this.visibleChunks.values()) { -+ consumer.accept(value); -+ } -+ } finally { -+ this.isIterating = prev; -+ if (!this.isIterating && this.hasPendingVisibleUpdate) { -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom(this.pendingVisibleChunks); -+ this.pendingVisibleChunks.clear(); -+ this.hasPendingVisibleUpdate = false; -+ } -+ } -+ } -+ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { -+ if (Thread.currentThread() == this.world.serverThread) { -+ return this.visibleChunks; -+ } else { -+ synchronized (this.visibleChunks) { -+ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); -+ if (this.visibleChunksClone == null) { -+ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunks).clone(); -+ } -+ return this.visibleChunksClone; -+ } -+ } -+ } -+ // Paper end -+ - @Nullable - public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public -- return (PlayerChunk) this.visibleChunks.get(i); -+ // Paper start - mt safe get -+ if (Thread.currentThread() != this.world.serverThread) { -+ synchronized (this.visibleChunks) { -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ } -+ } -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ // Paper end - } - - protected IntSupplier c(long i) { -@@ -462,8 +530,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - - protected void save(boolean flag) { -+ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) - if (flag) { -- List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -+ List list = (List) visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); // Paper - remove cloning of visible chunks - MutableBoolean mutableboolean = new MutableBoolean(); - - do { -@@ -491,7 +560,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { -- this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -+ visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { - IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error - - if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { -@@ -662,7 +731,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!this.updatingChunksModified) { - return false; - } else { -- this.visibleChunks = this.updatingChunks.clone(); -+ // Paper start - stop cloning visibleChunks -+ synchronized (this.visibleChunks) { -+ if (isIterating) { -+ hasPendingVisibleUpdate = true; -+ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ } else { -+ hasPendingVisibleUpdate = false; -+ this.pendingVisibleChunks.clear(); -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ this.visibleChunksClone = null; -+ } -+ } -+ // Paper end -+ - this.updatingChunksModified = false; - return true; - } -@@ -1141,12 +1223,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - protected Iterable f() { -- return Iterables.unmodifiableIterable(this.visibleChunks.values()); -+ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper - } - - void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("z").a("level").a("in_memory").a("status").a("full_status").a("accessible_ready").a("ticking_ready").a("entity_ticking_ready").a("ticket").a("spawning").a("entity_count").a("block_entity_count").a(writer); -- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunks.long2ObjectEntrySet().iterator(); -+ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper - - while (objectbidirectionaliterator.hasNext()) { - Entry entry = (Entry) objectbidirectionaliterator.next(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fcad64fcfc22af227be19741b634b773aca7a98d..c5a4c8c4c9d90a8a081a593488f86ab487adaecb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -294,6 +294,7 @@ public class CraftWorld implements World { - return ret; - } - public int getTileEntityCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - // We don't use the full world tile entity list, so we must iterate chunks - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - int size = 0; -@@ -305,11 +306,13 @@ public class CraftWorld implements World { - size += chunk.tileEntities.size(); - } - return size; -+ }); - } - public int getTickableTileEntityCount() { - return world.tileEntityListTick.size(); - } - public int getChunkCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - int ret = 0; - - for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -@@ -318,7 +321,7 @@ public class CraftWorld implements World { - } - } - -- return ret; -+ return ret; }); - } - public int getPlayerCount() { - return world.players.size(); -@@ -443,6 +446,14 @@ public class CraftWorld implements World { - - @Override - public Chunk[] getLoadedChunks() { -+ // Paper start -+ if (Thread.currentThread() != world.getMinecraftWorld().serverThread) { -+ synchronized (world.getChunkProvider().playerChunkMap.visibleChunks) { -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); -+ } -+ } -+ // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); - } diff --git a/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch b/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch deleted file mode 100644 index 4590de93173f..000000000000 --- a/Spigot-Server-Patches/0427-Increase-Light-Queue-Size.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 21:24:05 -0400 -Subject: [PATCH] Increase Light Queue Size - -Wiz mentioned that large WorldEdit operations cause light to run on -main thread. The queue was small, set to 5.. this bumps it to 20 -but makes it configurable per-world. - -The main risk of increasing this higher is during shutdown, some -queued light updates may be lost because mojang did not flush the -light engine on shutdown... - -The queue size only puts a cap on max loss, doesn't solve that problem. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1..cd248eb6be663e8be33f2c3c6b06b77b6d5753a4 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -620,4 +620,9 @@ public class PaperWorldConfig { - private void zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } -+ -+ public int lightQueueSize = 20; -+ private void lightQueueSize() { -+ lightQueueSize = getInt("light-queue-size", lightQueueSize); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c86c3cdea77369e3297548c8d5f10674c1100f76..54738ef346b1fe4c45ea95db2f236d10f8525a20 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -777,7 +777,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Thu, 9 Apr 2020 00:09:26 -0400 -Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and - generation - -Credit to Spotted for the idea - -A lot of the new chunk system requires constant back and forth the main thread -to handle priority scheduling and ensuring conflicting tasks do not run at the -same time. - -The issue is, these queues are only checked at either: - -A) Sync Chunk Loads -B) End of Tick while sleeping - -This results in generating chunks sitting waiting for a full tick to -complete before it will even start the next unit of work to do. - -Additionally, this also delays loading of chunks until this same timing. - -We will now periodically poll the chunk task queues throughout the tick, -looking for work to do. -We do this in a fair method that considers all worlds, not just the one being -ticked, so that each world can get 1 task procesed each before the next pass. - -In a view distance of 15, chunk loading performance was visually faster on the client. - -Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index fed920e5ec65409377f181d74dcf9274d45aadc1..b4d43ceed368552e703886213327a0c0bb5ccb92 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -16,6 +16,7 @@ import java.util.Map; - public final class MinecraftTimings { - - public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); - public static final Timing playerListTimer = Timings.ofSafe("Player List"); - public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); - public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85fe851078 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -410,4 +410,9 @@ public class PaperConfig { - log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); - } - } -+ -+ public static int midTickChunkTasks = 1000; -+ private static void midTickChunkTasks() { -+ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 54738ef346b1fe4c45ea95db2f236d10f8525a20..5ea593ccfedf55140a723f6dc29bebe282e77ab3 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1057,6 +1057,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1320,13 +1339,16 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - safe iterator incase chunk loads, also no wrapping -+ final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -@@ -804,6 +807,7 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); - this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper -+ if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper - } - } - } -@@ -960,6 +964,41 @@ public class ChunkProviderServer extends IChunkProvider { - super.executeTask(runnable); - } - -+ // Paper start -+ private long lastMidTickChunkTask = 0; -+ public boolean pollChunkLoadTasks() { -+ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { -+ try { -+ ChunkProviderServer.this.tickDistanceManager(); -+ } finally { -+ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task -+ playerChunkMap.callbackExecutor.run(); -+ } -+ return true; -+ } -+ return false; -+ } -+ public void midTickLoadChunks() { -+ MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); -+ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count -+ //noinspection StatementWithEmptyBody -+ while (pollChunkLoadTasks()) {} -+ -+ if (System.nanoTime() - lastMidTickChunkTask < 200000) { -+ return; -+ } -+ -+ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { -+ if (this.executeNext()) { -+ server.midTickChunksTasksRan++; -+ lastMidTickChunkTask = System.nanoTime(); -+ } else { -+ break; -+ } -+ } -+ } -+ // Paper end -+ - @Override - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 8159baec6e862580dc340d8fd7c16013ec8f0e66..6f15e2d0302108d64b14b3449e81f18f985db7ae 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -571,6 +571,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - timings.scheduledBlocks.stopTiming(); // Paper - -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - gameprofilerfiller.exitEnter("raid"); - this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -@@ -579,6 +580,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.doSounds.startTiming(); // Spigot - this.ak(); - timings.doSounds.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.ticking = false; - gameprofilerfiller.exitEnter("entities"); - boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -645,6 +647,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -654,6 +657,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - timings.tickEntities.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.tickBlockEntities(); - } - diff --git a/Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch b/Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch deleted file mode 100644 index 17f522dfd366..000000000000 --- a/Spigot-Server-Patches/0429-Don-t-move-existing-players-to-world-spawn.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 9 Apr 2020 21:20:33 -0400 -Subject: [PATCH] Don't move existing players to world spawn - -This can cause a nasty server lag the spawn chunks are not kept loaded -or they aren't finished loading yet, or if the world spawn radius is -larger than the keep loaded range. - -By skipping this, we avoid potential for a large spike on server start. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index e3721287cc18c8df81d1353084364966eb3f55ab..79003f43c4f15a7e5dd51587bc8c2f477bedb1b2 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -254,7 +254,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.serverStatisticManager = minecraftserver.getPlayerList().getStatisticManager(this); - this.advancementDataPlayer = minecraftserver.getPlayerList().f(this); - this.G = 1.0F; -- this.c(worldserver); -+ //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.co = minecraftserver.a(this); - - this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -306,6 +306,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - -+ public final void moveToSpawn(WorldServer worldserver) { c(worldserver); } // Paper - OBFHELPER - private void c(WorldServer worldserver) { - BlockPosition blockposition = worldserver.getSpawn(); - -@@ -483,7 +484,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - position = Vec3D.a(((WorldServer) world).getSpawn()); - } - this.world = world; -- this.setPosition(position.getX(), position.getY(), position.getZ()); -+ this.setPositionRaw(position.getX(), position.getY(), position.getZ()); // Paper - don't register to chunks yet - } - this.playerInteractManager.a((WorldServer) world); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0a99ee6221c46043ecdf9e9df7a064aa63ee6951..bd272d6fe86c30c3f22418802f98609410f947f8 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -208,6 +208,8 @@ public abstract class PlayerList { - worldserver1 = worldserver; - } - -+ if (nbttagcompound == null) entityplayer.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... -+ - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); - String s1 = "local"; diff --git a/Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch b/Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch deleted file mode 100644 index 9054be2b7b59..000000000000 --- a/Spigot-Server-Patches/0430-Add-tick-times-API-and-mspt-command.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:23:14 -0500 -Subject: [PATCH] Add tick times API and /mspt command - - -diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42cc6d7ba6d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -@@ -0,0 +1,64 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import java.text.DecimalFormat; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.List; -+ -+public class MSPTCommand extends Command { -+ private static final DecimalFormat DF = new DecimalFormat("########0.0"); -+ -+ public MSPTCommand(String name) { -+ super(name); -+ this.description = "View server tick times"; -+ this.usageMessage = "/mspt"; -+ this.setPermission("bukkit.command.mspt"); -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ return Collections.emptyList(); -+ } -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ List times = new ArrayList<>(); -+ times.addAll(eval(server.tickTimes5s.getTimes())); -+ times.addAll(eval(server.tickTimes10s.getTimes())); -+ times.addAll(eval(server.tickTimes60s.getTimes())); -+ -+ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); -+ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); -+ return true; -+ } -+ -+ private static List eval(long[] times) { -+ long min = Integer.MAX_VALUE; -+ long max = 0L; -+ long total = 0L; -+ for (long value : times) { -+ if (value > 0L && value < min) min = value; -+ if (value > max) max = value; -+ total += value; -+ } -+ double avgD = ((double) total / (double) times.length) * 1.0E-6D; -+ double minD = ((double) min) * 1.0E-6D; -+ double maxD = ((double) max) * 1.0E-6D; -+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); -+ } -+ -+ private static String getColor(double avg) { -+ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index ddbc8cb712c50038922eded75dd6ca85fe851078..78271b400c79578d043b20a5389a37b1bef9a70d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -69,6 +69,7 @@ public class PaperConfig { - - commands = new HashMap(); - commands.put("paper", new PaperCommand("paper")); -+ commands.put("mspt", new MSPTCommand("mspt")); - - version = getInt("config-version", 20); - set("config-version", 20); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5ea593ccfedf55140a723f6dc29bebe282e77ab3..795cf9635ab6ac7f001476354813cac9d7e025eb 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -219,6 +219,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 10 Apr 2020 21:24:12 -0400 -Subject: [PATCH] Expose MinecraftServer#isRunning - -This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 35e1739c4c90f4f27ed2b729a2ec2522b3aa0c06..fbc5d62d1ac2affc5240b114ee88375ff0199ef4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2380,5 +2380,10 @@ public final class CraftServer implements Server { - public int getCurrentTick() { - return net.minecraft.server.MinecraftServer.currentTick; - } -+ -+ @Override -+ public boolean isStopping() { -+ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch b/Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index 292ccedef133..000000000000 --- a/Spigot-Server-Patches/0432-Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:54 +0200 -Subject: [PATCH] Add Raw Byte ItemStack Serialization - -Serializes using NBT which is safer for server data migrations than bukkits format. - -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 20410a5853e34c90c872f5e9592d50c4727e914d..860f084de38dc3f8723d881ff78fb1873f2b602a 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -51,6 +51,7 @@ public class NBTCompressedStreamTools { - return nbttagcompound; - } - -+ public static NBTTagCompound readNBT(InputStream inputstream) throws IOException { return a(inputstream); } // Paper - OBFHELPER - public static NBTTagCompound a(InputStream inputstream) throws IOException { - DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(inputstream))); - Throwable throwable = null; -@@ -106,6 +107,7 @@ public class NBTCompressedStreamTools { - - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { a(nbttagcompound, outputstream); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { - DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); - Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -index 6527509e6aed7187667c681af682e9a02937a224..28e36ee76da533f8aa0a09cfc4f1fc0f744af715 100644 ---- a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -+++ b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -@@ -208,6 +208,7 @@ public class DataConverterRegistry { - return datafixerbuilder.build(SystemUtils.e()); - } - -+ public static DataFixer getDataFixer() { return a(); } // Paper - OBFHELPER - public static DataFixer a() { - return DataConverterRegistry.c; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 7b1df591007b9c50bcaf4bcd30562396a9549193..b88aec3b97d43018cf2733bad069a90338aa98cb 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -198,6 +198,7 @@ public final class ItemStack { - this.checkEmpty(); - } - -+ public static ItemStack fromCompound(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER - public static ItemStack a(NBTTagCompound nbttagcompound) { - try { - return new ItemStack(nbttagcompound); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 7e4cceff7ce9ffaff00caf21088fd7bc59e66933..2519dbce9717ff647d50c31aed6aca68b9f4e3af 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -380,6 +380,46 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); - } -+ -+ @Override -+ public byte[] serializeItem(ItemStack item) { -+ Preconditions.checkNotNull(item, "null cannot be serialized"); -+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); -+ -+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound()); -+ compound.setInt("DataVersion", getDataVersion()); -+ try { -+ net.minecraft.nbt.NBTCompressedStreamTools.writeNBT( -+ compound, -+ outputStream -+ ); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return outputStream.toByteArray(); -+ } -+ -+ @Override -+ public ItemStack deserializeItem(byte[] data) { -+ Preconditions.checkNotNull(data, "null cannot be deserialized"); -+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); -+ -+ try { -+ NBTTagCompound compound = net.minecraft.nbt.NBTCompressedStreamTools.readNBT( -+ new java.io.ByteArrayInputStream(data) -+ ); -+ int dataVersion = compound.getInt("DataVersion"); -+ -+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); -+ } catch (IOException ex) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); -+ throw new RuntimeException(); -+ } -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch b/Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch deleted file mode 100644 index 493779862032..000000000000 --- a/Spigot-Server-Patches/0433-Remove-streams-from-Mob-AI-System.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:53:29 -0700 -Subject: [PATCH] Remove streams from Mob AI System - -The streams hurt performance and allocate tons of garbage, so -replace them with the standard iterator. - -Also optimise the stream.anyMatch statement to move to a bitset -where we can replace the call with a single bitwise operation. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index b505c23c57a4b84faf5906c6295455b4720c4426..5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -1,10 +1,12 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import java.util.EnumSet; - - public abstract class PathfinderGoal { - -- private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - - public PathfinderGoal() {} - -@@ -28,16 +30,20 @@ public abstract class PathfinderGoal { - public void e() {} - - public void a(EnumSet enumset) { -- this.a.clear(); -- this.a.addAll(enumset); -+ // Paper start - remove streams from pathfindergoalselector -+ this.goalTypes.clear(); -+ this.goalTypes.addAllUnchecked(enumset); -+ // Paper end - remove streams from pathfindergoalselector - } - - public String toString() { - return this.getClass().getSimpleName(); - } - -- public EnumSet i() { -- return this.a; -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.goalTypes; -+ // Paper end - remove streams from pathfindergoalselector - } - - public static enum Type { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28..385cd079e264a7e66e91ab3b70b90afb59688dcd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -1,8 +1,10 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import com.google.common.collect.Sets; - import java.util.EnumMap; - import java.util.EnumSet; -+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector - import java.util.Map; - import java.util.Set; - import java.util.function.Supplier; -@@ -28,7 +30,8 @@ public class PathfinderGoalSelector { - private final Map c = new EnumMap(PathfinderGoal.Type.class); - private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; -- private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER - private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - -@@ -56,35 +59,38 @@ public class PathfinderGoalSelector { - // Paper end - - public void a(PathfinderGoal pathfindergoal) { -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d); -- this.d.removeIf((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped goalWrapped = iterator.next(); -+ if (goalWrapped.j() != pathfindergoal) { -+ continue; -+ } -+ if (goalWrapped.g()) { -+ goalWrapped.d(); -+ } -+ iterator.remove(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - } - -+ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector -+ - public void doTick() { - GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get(); - - gameprofilerfiller.enter("goalCleanup"); -- this.d().filter((pathfindergoalwrapped) -> { -- boolean flag; -- -- if (pathfindergoalwrapped.g()) { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) { -- flag = false; -- return flag; -- } -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (!wrappedGoal.g()) { -+ continue; - } -- -- flag = true; -- return flag; -- }).forEach(PathfinderGoal::d); -+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) { -+ continue; -+ } -+ wrappedGoal.d(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { - if (!pathfindergoalwrapped.g()) { - this.c.remove(pathfindergoal_type); -@@ -93,30 +99,58 @@ public class PathfinderGoalSelector { - }); - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalUpdate"); -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return !pathfindergoalwrapped.g(); -- }).filter((pathfindergoalwrapped) -> { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- return stream.noneMatch(enumset::contains); -- }).filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> { -- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped); -- }); -- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> { -- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> { -- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b); -- -- pathfindergoalwrapped1.d(); -- this.c.put(pathfindergoal_type, pathfindergoalwrapped); -- }); -- pathfindergoalwrapped.c(); -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ goal_update_loop: for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ continue; -+ } -+ -+ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); -+ -+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { -+ continue; -+ } -+ -+ long iterator1 = wrappedGoalSet.getBackingSet(); -+ int wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ if (!wrapped.a(wrappedGoal)) { -+ continue goal_update_loop; -+ } -+ } -+ -+ if (!wrappedGoal.a()) { -+ continue; -+ } -+ -+ iterator1 = wrappedGoalSet.getBackingSet(); -+ wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ -+ wrapped.d(); -+ this.c.put(type, wrappedGoal); -+ } -+ -+ wrappedGoal.c(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalTick"); -- this.d().forEach(PathfinderGoalWrapped::e); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ wrappedGoal.e(); -+ } -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - } - -@@ -125,11 +159,11 @@ public class PathfinderGoalSelector { - } - - public void a(PathfinderGoal.Type pathfindergoal_type) { -- this.f.add(pathfindergoal_type); -+ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void b(PathfinderGoal.Type pathfindergoal_type) { -- this.f.remove(pathfindergoal_type); -+ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 7bb531e47668cf445083c4dedb03ccafe6a9c96b..8c8e39d35fb56aa6cf7d456adab01dff5d13a60d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -59,9 +59,10 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - this.a.a(enumset); - } - -- @Override -- public EnumSet i() { -- return this.a.i(); -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.a.getGoalTypes(); -+ // Paper end - remove streams from pathfindergoalselector - } - - public boolean isRunning() { return this.g(); } // Paper - OBFHELPER diff --git a/Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch deleted file mode 100644 index ed808f345d93..000000000000 --- a/Spigot-Server-Patches/0434-Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:23:42 -0400 -Subject: [PATCH] Delay unsafe actions until after entity ticking is done - -This will help prevent many cases of unregistering entities during entity ticking - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 6f15e2d0302108d64b14b3449e81f18f985db7ae..cfe784560ea4c368d6e3a0797d09c0a717eb146e 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -178,6 +178,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; -+ // Paper start -+ List afterEntityTickingTasks = Lists.newArrayList(); -+ public void doIfNotEntityTicking(java.lang.Runnable run) { -+ if (tickingEntities) { -+ afterEntityTickingTasks.add(run); -+ } else { -+ run.run(); -+ } -+ } -+ // Paper end - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type - public boolean savingDisabled; -@@ -647,6 +657,16 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ // Paper start -+ for (java.lang.Runnable run : this.afterEntityTickingTasks) { -+ try { -+ run.run(); -+ } catch (Exception e) { -+ LOGGER.error("Error in After Entity Ticking Task", e); -+ } -+ } -+ this.afterEntityTickingTasks.clear(); -+ // Paper end - this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; diff --git a/Spigot-Server-Patches/0435-Async-command-map-building.patch b/Spigot-Server-Patches/0435-Async-command-map-building.patch deleted file mode 100644 index 463fac0fc78d..000000000000 --- a/Spigot-Server-Patches/0435-Async-command-map-building.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Wed, 8 Apr 2020 02:42:14 -0500 -Subject: [PATCH] Async command map building - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index ddbd4c43bbe6d6a5b90f4958c4be80520a40beab..c97424b401147be53ffa7e2a2a3271d696752efe 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -29,6 +29,7 @@ import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutCommands; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.commands.CommandAdvancement; - import net.minecraft.server.commands.CommandAttribute; - import net.minecraft.server.commands.CommandBan; -@@ -327,6 +328,14 @@ public class CommandDispatcher { - if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot - // CraftBukkit start - // Register Vanilla commands into builtRoot as before -+ // Paper start - Async command map building -+ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { -+ sendAsync(entityplayer); -+ }); -+ } -+ -+ private void sendAsync(EntityPlayer entityplayer) { -+ // Paper end - Async command map building - Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues - RootCommandNode vanillaRoot = new RootCommandNode(); - -@@ -344,7 +353,14 @@ public class CommandDispatcher { - for (CommandNode node : rootcommandnode.getChildren()) { - bukkit.add(node.getName()); - } -+ // Paper start - Async command map building -+ MinecraftServer.getServer().execute(() -> { -+ runSync(entityplayer, bukkit, rootcommandnode); -+ }); -+ } - -+ private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { -+ // Paper end - Async command map building - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - diff --git a/Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch b/Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch deleted file mode 100644 index 93119e26e226..000000000000 --- a/Spigot-Server-Patches/0436-Improved-Watchdog-Support.patch +++ /dev/null @@ -1,604 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Apr 2020 15:50:48 -0400 -Subject: [PATCH] Improved Watchdog Support - -Forced Watchdog Crash support and Improve Async Shutdown - -If the request to shut down the server is received while we are in -a watchdog hang, immediately treat it as a crash and begin the shutdown -process. Shutdown process is now improved to also shutdown cleanly when -not using restart scripts either. - -If a server is deadlocked, a server owner can send SIGUP (or any other signal -the JVM understands to shut down as it currently does) and the watchdog -will no longer need to wait until the full timeout, allowing you to trigger -a close process and try to shut the server down gracefully, saving player and -world data. - -Previously there was no way to trigger this outside of waiting for a full watchdog -timeout, which may be set to a really long time... - -Additionally, fix everything to do with shutting the server down asynchronously. - -Previously, nearly everything about the process was fragile and unsafe. Main might -not have actually been frozen, and might still be manipulating state. - -Or, some reuest might ask main to do something in the shutdown but main is dead. - -Or worse, other things might start closing down items such as the Console or Thread Pool -before we are fully shutdown. - -This change tries to resolve all of these issues by moving everything into the stop -method and guaranteeing only one thread is stopping the server. - -We then issue Thread Death to the main thread of another thread initiates the stop process. -We have to ensure Thread Death propagates correctly though to stop main completely. - -This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. - -This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they -are properly accounted for and wont trip watchdog on init. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 0b9e689d57705965721b5c55bc45d36657f360e4..dee00aac05f1acf050f05d4db557a08dd0f301c8 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -92,7 +92,12 @@ public class Metrics { - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { -- final Runnable submitTask = this::submitData; -+ final Runnable submitTask = () -> { -+ if (MinecraftServer.getServer().hasStopped()) { -+ return; -+ } -+ submitData(); -+ }; - - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index d0fdb9ce57b22a1f582cddec9afcc35b75d58cc6..9b7a51890c667601b195ff15b2bf0d6c76c7f19f 100644 ---- a/src/main/java/net/minecraft/CrashReport.java -+++ b/src/main/java/net/minecraft/CrashReport.java -@@ -257,6 +257,7 @@ public class CrashReport { - } - - public static CrashReport a(Throwable throwable, String s) { -+ if (throwable instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(throwable); // Paper - while (throwable instanceof CompletionException && throwable.getCause() != null) { - throwable = throwable.getCause(); - } -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 397194b3e90c9df39cfae17b401c7ac891b0dbb7..61b4c42e95994343772a91640b243b8e8224e09b 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -130,6 +130,7 @@ public class SystemUtils { - return SystemUtils.f; - } - -+ public static void shutdownServerThreadPool() { h(); } // Paper - OBFHELPER - public static void h() { - a(SystemUtils.e); - a(SystemUtils.f); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 795cf9635ab6ac7f001476354813cac9d7e025eb..6f51409bac9c2907a5be02e4c15319fcc520609f 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -271,7 +271,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant S a(Function function) { - AtomicReference atomicreference = new AtomicReference(); - Thread thread = new Thread(() -> { -@@ -853,6 +855,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ world.tickingEntities = false; -+ }); -+ } -+ // Paper end - // CraftBukkit end - MinecraftServer.LOGGER.info("Stopping server"); - MinecraftTimings.stopServer(); // Paper -@@ -932,7 +952,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant {}; -+ } -+ // Paper end - return new TickTask(this.ticks, runnable); - } - -@@ -1423,6 +1479,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - CompletableFuture completablefuture; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index cfe784560ea4c368d6e3a0797d09c0a717eb146e..795c4a9e3e33660af888ff80204bfd47a3b327fd 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -177,7 +177,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Queue entitiesToAdd = Queues.newArrayDeque(); - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public -- boolean tickingEntities; -+ public boolean tickingEntities; // Paper - expose for watchdog - // Paper start - List afterEntityTickingTasks = Lists.newArrayList(); - public void doIfNotEntityTicking(java.lang.Runnable run) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index bd272d6fe86c30c3f22418802f98609410f947f8..9eec320ca5a63a313138dc84367e93038b457c0d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -507,7 +507,7 @@ public abstract class PlayerList { - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -- entityplayer.playerTick(); // SPIGOT-924 -+ if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) - // CraftBukkit end - - // Paper start - Remove from collideRule team if needed -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index ca23ca14d8011fc8daa7e20f2eaa550a8ff92c53..158ea6d77698d62ba795aff6c061a80652e42e03 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -135,6 +135,7 @@ public abstract class IAsyncTaskHandler implements Mailbox asList(String... params) { - return Arrays.asList(params); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 449e99d1b673870ed6892f6ab2c715a2db35c35d..c7ed6e0f8a989cec97700df2b15198c9c481c549 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -12,12 +12,27 @@ public class ServerShutdownThread extends Thread { - @Override - public void run() { - try { -+ // Paper start - try to shutdown on main -+ server.safeShutdown(false, false); -+ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { -+ Thread.sleep(100); -+ } -+ if (server.hasStopped()) { -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ return; -+ } -+ // Looks stalled, close async - org.spigotmc.AsyncCatcher.enabled = false; // Spigot - org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper -+ server.forceTicks = true; - server.close(); -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ // Paper end - } finally { - try { -- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender -+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index b45d7e5c108c7a8541fcbc9ad92d1a79a94746a1..6a408dc9286a60c3ca7830f88171919fb0fe6363 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -139,7 +139,7 @@ public class RestartCommand extends Command - // Paper end - - // Paper start - copied from above and modified to return if the hook registered -- private static boolean addShutdownHook(String restartScript) -+ public static boolean addShutdownHook(String restartScript) - { - String[] split = restartScript.split( " " ); - if ( split.length > 0 && new File( split[0] ).isFile() ) -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 58e50bf0fb0f309227e1f4c1f6bb11c01d8e08d3..30a665c090f419985e1d0f49df9e8d110c83943a 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -13,6 +13,7 @@ import org.bukkit.Bukkit; - public class WatchdogThread extends Thread - { - -+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - private static WatchdogThread instance; - private long timeoutTime; - private boolean restart; -@@ -41,6 +42,7 @@ public class WatchdogThread extends Thread - { - if ( instance == null ) - { -+ if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); - } else -@@ -71,12 +73,13 @@ public class WatchdogThread extends Thread - // Paper start - Logger log = Bukkit.getServer().getLogger(); - long currentTime = monotonicMillis(); -- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) -+ MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) - { -- boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); - // Don't spam early warning dumps - if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... - lastEarlyWarning = currentTime; - if (isLongTimeout) { - // Paper end -@@ -118,7 +121,7 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper -- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); -+ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // - // Paper start - Only print full dump on long timeouts -@@ -139,9 +142,24 @@ public class WatchdogThread extends Thread - - if ( isLongTimeout ) - { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) -+ if ( !server.hasStopped() ) - { -- RestartCommand.restart(); -+ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ AsyncCatcher.shuttingDown = true; -+ server.forceTicks = true; -+ if (restart) { -+ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); -+ } -+ // try one last chance to safe shutdown on main incase it 'comes back' -+ server.safeShutdown(false, restart); -+ try { -+ Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ } -+ if (!server.hasStopped()) { -+ server.close(); -+ } - } - break; - } // Paper end -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 476f4a5cbe664ddd05474cb88553018bd334a5b8..8af159abd3d0cc94cf155fec5b384c42f69551bf 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -1,5 +1,5 @@ - -- -+ - - - diff --git a/Spigot-Server-Patches/0437-Optimize-Pathfinding.patch b/Spigot-Server-Patches/0437-Optimize-Pathfinding.patch deleted file mode 100644 index 812fed5f729e..000000000000 --- a/Spigot-Server-Patches/0437-Optimize-Pathfinding.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:02:07 -0600 -Subject: [PATCH] Optimize Pathfinding - -Prevents pathfinding from spamming failures for things such as -arrow attacks. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 06d05b511d623d0247d44989bee85b383a8fb52f..e6ba9b7fbf08ae0dd083a1ebee8eb7ed8a937751 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -11,6 +11,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -32,7 +33,7 @@ public abstract class NavigationAbstract { - protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable -- protected PathEntity c; -+ protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER - protected double d; - protected int e; - protected int f; -@@ -184,10 +185,30 @@ public abstract class NavigationAbstract { - return this.a(this.a(d0, d1, d2, 1), d3); - } - -+ // Paper start - optimise pathfinding -+ private int lastFailure = 0; -+ private int pathfindFailures = 0; -+ // Paper end -+ - public boolean a(Entity entity, double d0) { -+ // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { -+ return false; -+ } -+ // Paper end - PathEntity pathentity = this.a(entity, 1); - -- return pathentity != null && this.a(pathentity, d0); -+ // Paper start - Pathfinding optimizations -+ if (pathentity != null && this.a(pathentity, d0)) { -+ this.lastFailure = 0; -+ this.pathfindFailures = 0; -+ return true; -+ } else { -+ this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; -+ return false; -+ } -+ // Paper end - } - - public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER diff --git a/Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch b/Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch deleted file mode 100644 index 0f4641263b09..000000000000 --- a/Spigot-Server-Patches/0438-Reduce-Either-Optional-allocation.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:35:09 -0700 -Subject: [PATCH] Reduce Either Optional allocation - -In order to get chunk values, we shouldn't need to create -an optional each time. - -diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java -index a90adac7bd7ebd423f480e9ae0f44cb9d521fa4f..3f65fe71024928e35111fc6719a290aab9a6859e 100644 ---- a/src/main/java/com/mojang/datafixers/util/Either.java -+++ b/src/main/java/com/mojang/datafixers/util/Either.java -@@ -22,7 +22,7 @@ public abstract class Either implements App, L> { - } - - private static final class Left extends Either { -- private final L value; -+ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Left(final L value) { - this.value = value; -@@ -51,7 +51,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional left() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override -@@ -83,7 +83,7 @@ public abstract class Either implements App, L> { - } - - private static final class Right extends Either { -- private final R value; -+ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Right(final R value) { - this.value = value; -@@ -117,7 +117,7 @@ public abstract class Either implements App, L> { - - @Override - public Optional right() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override diff --git a/Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch b/Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch deleted file mode 100644 index f1a9a0128ae7..000000000000 --- a/Spigot-Server-Patches/0439-Remove-streams-from-PairedQueue.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:10:43 -0700 -Subject: [PATCH] Remove streams from PairedQueue - -We shouldn't be doing stream calls just to see if the queue is -empty. This creates loads of garbage thanks to how often it's called. - -diff --git a/src/main/java/net/minecraft/util/thread/PairedQueue.java b/src/main/java/net/minecraft/util/thread/PairedQueue.java -index 024b414aae32c8ad32bdf031361257fc74b80eb3..56c9efa78ceeac499182eb401e605a60dad12182 100644 ---- a/src/main/java/net/minecraft/util/thread/PairedQueue.java -+++ b/src/main/java/net/minecraft/util/thread/PairedQueue.java -@@ -20,32 +20,30 @@ public interface PairedQueue { - - public static final class a implements PairedQueue { - -- private final List> a; -+ private final List> a; private final List> getQueues() { return this.a; } // Paper - OBFHELPER - - public a(int i) { -- this.a = (List) IntStream.range(0, i).mapToObj((j) -> { -- return Queues.newConcurrentLinkedQueue(); -- }).collect(Collectors.toList()); -+ // Paper start - remove streams -+ this.a = new java.util.ArrayList<>(i); // queues -+ for (int j = 0; j < i; ++j) { -+ this.getQueues().add(Queues.newConcurrentLinkedQueue()); -+ } -+ // Paper end - remove streams - } - - @Nullable - @Override - public Runnable a() { -- Iterator iterator = this.a.iterator(); -- -- Runnable runnable; -- -- do { -- if (!iterator.hasNext()) { -- return null; -+ // Paper start - remove iterator creation -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ Runnable ret = queue.poll(); -+ if (ret != null) { -+ return ret; - } -- -- Queue queue = (Queue) iterator.next(); -- -- runnable = (Runnable) queue.poll(); -- } while (runnable == null); -- -- return runnable; -+ } -+ return null; -+ // Paper end - remove iterator creation - } - - public boolean a(PairedQueue.b pairedqueue_b) { -@@ -57,7 +55,16 @@ public interface PairedQueue { - - @Override - public boolean b() { -- return this.a.stream().allMatch(Collection::isEmpty); -+ // Paper start - remove streams -+ // why are we doing streams every time we might want to execute a task? -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ if (!queue.isEmpty()) { -+ return false; -+ } -+ } -+ return true; -+ // Paper end - remove streams - } - } - diff --git a/Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch b/Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch deleted file mode 100644 index a8f074ccde1c..000000000000 --- a/Spigot-Server-Patches/0440-Reduce-memory-footprint-of-NBTTagCompound.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:39:25 -0700 -Subject: [PATCH] Reduce memory footprint of NBTTagCompound - -Fastutil maps are going to have a lower memory footprint - which -is important because we clone chunk data after reading it for safety. -So, reduce the impact of the clone on GC. - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index d5508deff819309034554abc7b36aac40fa33503..77afbaad5b2cb8d912f5404fcbd3a0970490f4f3 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -26,6 +26,7 @@ import net.minecraft.ReportedException; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -47,7 +48,7 @@ public class NBTTagCompound implements NBTBase { - if (i > 512) { - throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); - } else { -- HashMap hashmap = Maps.newHashMap(); -+ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound - - byte b0; - -@@ -83,7 +84,7 @@ public class NBTTagCompound implements NBTBase { - } - - public NBTTagCompound() { -- this(Maps.newHashMap()); -+ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound - } - - @Override -@@ -417,9 +418,17 @@ public class NBTTagCompound implements NBTBase { - - @Override - public NBTTagCompound clone() { -- Map map = Maps.newHashMap(Maps.transformValues(this.map, NBTBase::clone)); -+ // Paper start - reduce memory footprint of NBTTagCompound -+ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.map.size(), 0.8f); - -- return new NBTTagCompound(map); -+ Iterator> iterator = (this.map instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.map).object2ObjectEntrySet().fastIterator() : this.map.entrySet().iterator(); -+ while (iterator.hasNext()) { -+ Map.Entry entry = iterator.next(); -+ ret.put(entry.getKey(), entry.getValue().clone()); -+ } -+ -+ return new NBTTagCompound(ret); -+ // Paper end - reduce memory footprint of NBTTagCompound - } - - public boolean equals(Object object) { diff --git a/Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch b/Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch deleted file mode 100644 index beb4de65b110..000000000000 --- a/Spigot-Server-Patches/0441-Prevent-opening-inventories-when-frozen.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 13 Apr 2020 07:31:44 +0100 -Subject: [PATCH] Prevent opening inventories when frozen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 79003f43c4f15a7e5dd51587bc8c2f477bedb1b2..5382dfbad7a33670268d5d713cf3bdd425bbe885 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -560,7 +560,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - containerUpdateDelay = world.paperConfig.containerUpdateTickRate; - } - // Paper end -- if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -+ if (!this.world.isClientSide && this.activeContainer != this.defaultContainer && (isFrozen() || !this.activeContainer.canUse(this))) { // Paper - auto close while frozen - this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } -@@ -1407,7 +1407,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } else { - // CraftBukkit start - this.activeContainer = container; -- this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); -+ if (!isFrozen()) this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); // Paper - // CraftBukkit end - container.addSlotListener(this); - return OptionalInt.of(this.containerCounter); -@@ -2209,7 +2209,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- protected boolean isFrozen() { -+ public boolean isFrozen() { // Paper - protected > public - return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index e8f8a07f256e01c5792199bf47f3cc1f0f3d1610..5b142e96248278c6bb6068879bb5ad1578b0f79f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -322,7 +322,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -396,7 +396,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } diff --git a/Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch b/Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch deleted file mode 100644 index 1ff7b9b2f9ea..000000000000 --- a/Spigot-Server-Patches/0442-Optimise-ArraySetSorted-removeIf.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 18:23:28 -0700 -Subject: [PATCH] Optimise ArraySetSorted#removeIf - -Remove iterator allocation and ensure the call is always O(n) - -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index 427daa94322f47b4eaf881d85a01fed239db549a..936a90272579f78832eff93f2a81d673feb669c1 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -10,8 +10,8 @@ import java.util.NoSuchElementException; - public class ArraySetSorted extends AbstractSet { - - private final Comparator a; -- private T[] b; -- private int c; -+ private T[] b; private final T[] getBackingArray() { return this.b; } // Paper - OBFHELPER -+ private int c; private final int getSize() { return this.c; } private final void setSize(int value) { this.c = value; } // Paper - OBFHELPER - - private ArraySetSorted(int i, Comparator comparator) { - this.a = comparator; -@@ -22,6 +22,42 @@ public class ArraySetSorted extends AbstractSet { - } - } - -+ // Paper start - optimise removeIf -+ @Override -+ public boolean removeIf(java.util.function.Predicate filter) { -+ // prev. impl used an iterator, which could be n^2 and creates garbage -+ int i = 0, len = this.getSize(); -+ T[] backingArray = this.getBackingArray(); -+ -+ for (;;) { -+ if (i >= len) { -+ return false; -+ } -+ if (!filter.test(backingArray[i])) { -+ ++i; -+ continue; -+ } -+ break; -+ } -+ -+ // we only want to write back to backingArray if we really need to -+ -+ int lastIndex = i; // this is where new elements are shifted to -+ -+ for (; i < len; ++i) { -+ T curr = backingArray[i]; -+ if (!filter.test(curr)) { // if test throws we're screwed -+ backingArray[lastIndex++] = curr; -+ } -+ } -+ -+ // cleanup end -+ Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); -+ return true; -+ } -+ // Paper end - optimise removeIf -+ - public static > ArraySetSorted a(int i) { - return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } diff --git a/Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch b/Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch deleted file mode 100644 index da7931a459a6..000000000000 --- a/Spigot-Server-Patches/0443-Don-t-run-entity-collision-code-if-not-needed.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 17:56:07 -0700 -Subject: [PATCH] Don't run entity collision code if not needed - -Will not run if max entity craming is disabled and -the max collisions per entity is less than or equal to 0 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 86c6a8fd4511dfe426cc1651d289f38b467d3029..dc9e12c38d1682f6c4558ca07b781de2226c0621 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -2944,10 +2944,16 @@ public abstract class EntityLiving extends Entity { - protected void doTick() {} - - protected void collideNearby() { -+ // Paper - start don't run getEntities if we're not going to use its result -+ int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ if (i <= 0 && world.paperConfig.maxCollisionsPerEntity <= 0) { -+ return; -+ } -+ // Paper - end don't run getEntities if we're not going to use its result - List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); - - if (!list.isEmpty()) { -- int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ // Paper - move up - int j; - - if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch deleted file mode 100644 index 615f5f78eee2..000000000000 --- a/Spigot-Server-Patches/0444-Optimize-ChunkProviderServer-s-chunk-level-checking-.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 16 Apr 2020 16:13:59 -0700 -Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper - methods - -These can be hot functions (i.e entity ticking and block ticking), -so inline where possible, and avoid the abstraction of the -Either class. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 99108d2c8145c16943fb29872c55d8e74f75eb77..2d7d2e712a7117e6985e3104097a31a5577c1b82 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -643,21 +643,29 @@ public class ChunkProviderServer extends IChunkProvider { - - public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER - @Override public boolean a(Entity entity) { -- long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // entity ticking -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER - @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { -- return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is entity ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(chunkcoordintpair)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - @Override - public boolean a(BlockPosition blockposition) { -- long i = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::a); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(blockposition)); -+ return playerChunk != null && playerChunk.isTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - private boolean a(long i, Function>> function) { diff --git a/Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch b/Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch deleted file mode 100644 index ed7ce57a1432..000000000000 --- a/Spigot-Server-Patches/0445-Restrict-vanilla-teleport-command-to-valid-locations.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Thu, 16 Apr 2020 20:07:29 -0500 -Subject: [PATCH] Restrict vanilla teleport command to valid locations - -Fixes GH-3165, GH-3575 - -diff --git a/src/main/java/net/minecraft/server/commands/CommandTeleport.java b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -index b59763643def065cd998fa3005523c37973613fd..dcc92b0c9a7a0214a3e803d714c5e7078c17a039 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandTeleport.java -+++ b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -@@ -142,6 +142,12 @@ public class CommandTeleport { - - private static void a(CommandListenerWrapper commandlistenerwrapper, Entity entity, WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, @Nullable CommandTeleport.a commandteleport_a) throws CommandSyntaxException { - BlockPosition blockposition = new BlockPosition(d0, d1, d2); -+ // Paper start - Don't allow teleport command to invalid locations -+ if (d0 <= -30000000 || d2 <= -30000000 || d0 > 30000000 || d2 > 30000000 || d1 > 30000000 || d1 <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation -+ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + entity.getName() + " to " + d0 + ", " + d1 + ", " + d2); -+ return; -+ } -+ // Paper end - - if (!World.l(blockposition)) { - throw CommandTeleport.a.create(); diff --git a/Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch b/Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch deleted file mode 100644 index 92a17b9c3a7c..000000000000 --- a/Spigot-Server-Patches/0446-Implement-Player-Client-Options-API.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Mon, 20 Jan 2020 21:38:15 +0100 -Subject: [PATCH] Implement Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -@@ -0,0 +1,74 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Objects; -+ -+import java.util.StringJoiner; -+ -+public class PaperSkinParts implements SkinParts { -+ -+ private final int raw; -+ -+ public PaperSkinParts(int raw) { -+ this.raw = raw; -+ } -+ -+ public boolean hasCapeEnabled() { -+ return (raw & 1) == 1; -+ } -+ -+ public boolean hasJacketEnabled() { -+ return (raw >> 1 & 1) == 1; -+ } -+ -+ public boolean hasLeftSleeveEnabled() { -+ return (raw >> 2 & 1) == 1; -+ } -+ -+ public boolean hasRightSleeveEnabled() { -+ return (raw >> 3 & 1) == 1; -+ } -+ -+ public boolean hasLeftPantsEnabled() { -+ return (raw >> 4 & 1) == 1; -+ } -+ -+ public boolean hasRightPantsEnabled() { -+ return (raw >> 5 & 1) == 1; -+ } -+ -+ public boolean hasHatsEnabled() { -+ return (raw >> 6 & 1) == 1; -+ } -+ -+ @Override -+ public int getRaw() { -+ return raw; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ PaperSkinParts that = (PaperSkinParts) o; -+ return raw == that.raw; -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(raw); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") -+ .add("raw=" + raw) -+ .add("cape=" + hasCapeEnabled()) -+ .add("jacket=" + hasJacketEnabled()) -+ .add("leftSleeve=" + hasLeftSleeveEnabled()) -+ .add("rightSleeve=" + hasRightSleeveEnabled()) -+ .add("leftPants=" + hasLeftPantsEnabled()) -+ .add("rightPants=" + hasRightPantsEnabled()) -+ .add("hats=" + hasHatsEnabled()) -+ .toString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -index 90842b27f64afcdd8eb7d0e52df8cfcb418b5b5a..f47cd43f96f61475bd1d5da11bdbc7c5e5f7e1bc 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -@@ -41,14 +41,17 @@ public class PacketPlayInSettings implements Packet { - packetlistenerplayin.a(this); - } - -+ public EnumChatVisibility getChatVisibility() { return d(); } // Paper - OBFHELPER - public EnumChatVisibility d() { - return this.c; - } - -+ public boolean hasChatColorsEnabled() { return e(); } // Paper - OBFHELPER - public boolean e() { - return this.d; - } - -+ public int getSkinParts() { return f(); } // Paper - OBFHELPER - public int f() { - return this.e; - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 5382dfbad7a33670268d5d713cf3bdd425bbe885..ff0913941a888ab529d7a4dd1b160fe9659b25cb 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -2,6 +2,7 @@ package net.minecraft.server.level; - - import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; -+import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; // Paper - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -@@ -191,7 +192,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int lastSentExp = -99999999; - public int invulnerableTicks = 60; - private EnumChatVisibility bY; -- private boolean bZ = true; -+ private boolean bZ = true; public boolean hasChatColorsEnabled() { return this.bZ; } // Paper - OBFHELPER - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -@@ -1810,6 +1811,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { -+ new PlayerClientOptionsChangeEvent(getBukkitEntity(), packetplayinsettings.locale, packetplayinsettings.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packetplayinsettings.getChatVisibility().name()), packetplayinsettings.hasChatColorsEnabled(), new com.destroystokyo.paper.PaperSkinParts(packetplayinsettings.getSkinParts()), packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 8981dfacd10cae9de052e1b36ce5181cd0e6752d..202fa94d5dc55b549475ae0309bbcfca8f1b2c96 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -133,7 +133,7 @@ public abstract class EntityHuman extends EntityLiving { - private static final Map b = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.bh).put(EntityPose.SLEEPING, EntityHuman.ah).put(EntityPose.FALL_FLYING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.b(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.b(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.c(0.2F, 0.2F)).build(); - private static final DataWatcherObject c = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.c); - private static final DataWatcherObject d = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.b); -- protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); -+ protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); public static DataWatcherObject getSkinPartsWatcher() { return bi; } // Paper - OBFHELPER - protected static final DataWatcherObject bj = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); - protected static final DataWatcherObject bk = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); - protected static final DataWatcherObject bl = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index dc8545241ed62f6b654b2559e025c3b34c00575f..935b5668a81db4d19a08b09c61519114532a23d9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1,5 +1,8 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.PaperSkinParts; -+import com.destroystokyo.paper.ClientOption; - import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; -@@ -2253,6 +2256,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void setViewDistance(int viewDistance) { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO - } -+ -+ @Override -+ public T getClientOption(ClientOption type) { -+ if(ClientOption.SKIN_PARTS.equals(type)) { -+ return type.getType().cast(new PaperSkinParts(getHandle().getDataWatcher().get(EntityHuman.getSkinPartsWatcher()))); -+ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { -+ return type.getType().cast(getHandle().hasChatColorsEnabled()); -+ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { -+ return type.getType().cast(getHandle().getChatFlags() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatFlags().name())); -+ } else if(ClientOption.LOCALE.equals(type)) { -+ return type.getType().cast(getLocale()); -+ } else if(ClientOption.MAIN_HAND.equals(type)) { -+ return type.getType().cast(getMainHand()); -+ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { -+ return type.getType().cast(getClientViewDistance()); -+ } -+ throw new RuntimeException("Unknown settings type"); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch b/Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch deleted file mode 100644 index 3f1b970f5362..000000000000 --- a/Spigot-Server-Patches/0447-Fix-Chunk-Post-Processing-deadlock-risk.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 04:36:11 -0400 -Subject: [PATCH] Fix Chunk Post Processing deadlock risk - -See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 - -as part of post processing a chunk, we can call ChunkConverter. - -ChunkConverter then kicks off major physics updates, and when blocks -that have connections across chunk boundries occur, a recursive risk -can occur where A updates a block that triggers a physics request. - -That physics request may trigger a chunk request, that then enqueues -a task into the Mailbox ChunkTaskQueueSorter. - -If anything requests that same chunk that is in the middle of conversion, -it's mailbox queue is going to be held up, so the subsequent chunk request -will be unable to proceed. - -We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into -the executor so that the mailbox ChunkQueue is now considered empty. - -This successfully fixed a reoccurring and highly reproduceable crash -for heightmaps. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 2d7d2e712a7117e6985e3104097a31a5577c1b82..6e5d21af43261dc2f12ceec7b7e3269be635cf7a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -1019,6 +1019,7 @@ public class ChunkProviderServer extends IChunkProvider { - return super.executeNext() || execChunkTask; // Paper - } - } finally { -+ playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter - playerChunkMap.callbackExecutor.run(); - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index b00c5a7eaf456e6d6ce250ee790ce33dfa9bb496..6279846a92489b5dade21ad55a1bec1157073e27 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -183,6 +183,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper -+ - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -@@ -1056,7 +1058,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. - }); - - completablefuture1.thenAcceptAsync((either) -> { diff --git a/Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch deleted file mode 100644 index 83e1af8a9c01..000000000000 --- a/Spigot-Server-Patches/0448-Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 15:59:41 -0400 -Subject: [PATCH] Don't crash if player is attempted to be removed from - untracked chunk. - -I suspect it deals with teleporting as it uses players current x/y/z - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 961257ebc28a8b4753faf3c2d5b6abaea4ffc0dd..60fcea78bf617559114b1ca1c0bf2d4cd9075a8c 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -245,8 +245,8 @@ public abstract class ChunkMapDistance { - ObjectSet objectset = (ObjectSet) this.c.get(i); - if (objectset == null) return; // CraftBukkit - SPIGOT-6208 - -- objectset.remove(entityplayer); -- if (objectset.isEmpty()) { -+ if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. -+ if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); - this.f.update(i, Integer.MAX_VALUE, false); - this.g.update(i, Integer.MAX_VALUE, false); diff --git a/Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch b/Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch deleted file mode 100644 index 6ffc69370610..000000000000 --- a/Spigot-Server-Patches/0449-Broadcast-join-message-to-console.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AvrooVulcan -Date: Fri, 17 Apr 2020 00:15:23 +0100 -Subject: [PATCH] Broadcast join message to console - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 9eec320ca5a63a313138dc84367e93038b457c0d..7d336c23a57c06c3744ae5b187960da798dd07c8 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -288,7 +288,9 @@ public abstract class PlayerList { - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure - joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -- server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure -+ // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure -+ // Paper end - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch deleted file mode 100644 index d064811c32d4..000000000000 --- a/Spigot-Server-Patches/0450-Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 00:05:46 -0400 -Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent - -For years, plugin developers have had to delay many things they do -inside of the PlayerJoinEvent by 1 tick to make it actually work. - -This all boiled down to 1 reason why: The event fired before the -player was fully ready and joined to the world! - -Additionally, if that player logged out on a vehicle, the event -fired before the vehicle was even loaded, so that plugins had no -access to the vehicle during this event either. - -This change finally fixes this issue, fully preparing the player -into the world as a fully ready entity, vehicle included. - -There should be no plugins that break because of this change, but might -improve consistency with other plugins instead. - -For example, if 2 plugins listens to this event, and the first one -teleported the player in the event, then the 2nd plugin actually -would be getting a valid player! - -This was very non deterministic. This change will ensure every plugin -receives a deterministic result, and should no longer require 1 tick -delays anymore. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index ff0913941a888ab529d7a4dd1b160fe9659b25cb..505cb0eb74d45906132e78c5cf8741dc5fd4eaf0 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -240,6 +240,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public double maxHealthCache; - public boolean joining = true; - public boolean sentListPacket = false; -+ public boolean supressTrackerForLogin = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6279846a92489b5dade21ad55a1bec1157073e27..86cb1f33cd5269ff271129ceedd3a3a8532fa6eb 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -1586,7 +1586,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -- protected void addEntity(Entity entity) { -+ public void addEntity(Entity entity) { // Paper - protected -> public - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot - // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -@@ -1595,6 +1595,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - .printStackTrace(); - return; - } -+ if (entity instanceof EntityPlayer && ((EntityPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets - // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7d336c23a57c06c3744ae5b187960da798dd07c8..66c1a9ca392b29fe2191577d32c70b214fa7293d 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -276,6 +276,12 @@ public abstract class PlayerList { - this.j.put(entityplayer.getUniqueID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - -+ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -+ entityplayer.supressTrackerForLogin = true; -+ worldserver1.addPlayerJoin(entityplayer); -+ this.server.getBossBattleCustomData().a(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); -+ // Paper end - // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); -@@ -311,6 +317,8 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); - } - entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now - // CraftBukkit end - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.getDataWatcher(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -@@ -336,6 +344,11 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); - } - -+ // Paper start - move vehicle into method so it can be called above - short circuit around that code -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); -+ } -+ private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver1, NBTTagCompound nbttagcompound) { -+ // Paper end - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - // CraftBukkit start -@@ -384,6 +397,10 @@ public abstract class PlayerList { - } - } - -+ // Paper start -+ } -+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) { -+ // Paper end - entityplayer.syncInventory(); - // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); diff --git a/Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch b/Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch deleted file mode 100644 index 89af9ea1da26..000000000000 --- a/Spigot-Server-Patches/0451-Load-Chunks-for-Login-Asynchronously.patch +++ /dev/null @@ -1,306 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 04:28:29 -0400 -Subject: [PATCH] Load Chunks for Login Asynchronously - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 6e5d21af43261dc2f12ceec7b7e3269be635cf7a..ecf4cd6dfea777ab9daea0b40724d247df7ddb53 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -629,7 +629,7 @@ public class ChunkProviderServer extends IChunkProvider { - return this.serverThreadQueue.executeNext(); - } - -- private boolean tickDistanceManager() { -+ public boolean tickDistanceManager() { // Paper - private -> public - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 505cb0eb74d45906132e78c5cf8741dc5fd4eaf0..39fb3a1445338c3ac1642b8e518eb8d1031f9a5c 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -31,6 +31,7 @@ import net.minecraft.core.NonNullList; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; -@@ -175,6 +176,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); - public PlayerConnection playerConnection; -+ public NetworkManager networkManager; // Paper - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; - public final Deque removeQueue = new ArrayDeque<>(); // Paper -@@ -241,6 +243,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean joining = true; - public boolean sentListPacket = false; - public boolean supressTrackerForLogin = false; // Paper -+ public boolean didPlayerJoinEvent = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 86cb1f33cd5269ff271129ceedd3a3a8532fa6eb..6e4a47581843be42b77034fec16b1d531a5b5759 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -147,7 +147,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Mailbox> mailboxWorldGen; - private final Mailbox> mailboxMain; - public final WorldLoadListener worldLoadListener; -- public final PlayerChunkMap.a chunkDistanceManager; -+ public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; - public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 218dc900e125a11548485887b1918742072c7a77..2c932d36f982e7f8713aabff9a6c631055810366 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -21,6 +21,7 @@ public class TicketType { - public static final TicketType FORCED = a("forced", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType LIGHT = a("light", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType PORTAL = a("portal", BaseBlockPosition::compareTo, 300); -+ public static final TicketType LOGIN = a("login", Long::compareTo, 100); // Paper - public static final TicketType POST_TELEPORT = a("post_teleport", Integer::compareTo, 5); - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 09ceac61f873ee0cb689c66a403c42677961011d..06e2b48ed6d6d52d0eb17301254ed07fb69cb8af 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -88,7 +88,7 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer == null) { - this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; -@@ -188,7 +188,7 @@ public class LoginListener implements PacketLoginInListener { - } - - this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i)); -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer != null) { - this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index f02ddd53df4674a2b5e0bb142db756d1f153d69b..443247b03b8352c4dd453270dccdbd7eb5f0944b 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -222,6 +222,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final Logger LOGGER = LogManager.getLogger(); - public final NetworkManager networkManager; - private final MinecraftServer minecraftServer; -+ public Runnable playerJoinReady; // Paper - public EntityPlayer player; - private int e; - private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -@@ -300,6 +301,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -+ // Paper start - login async -+ Runnable playerJoinReady = this.playerJoinReady; -+ if (playerJoinReady != null) { -+ this.playerJoinReady = null; -+ playerJoinReady.run(); -+ } -+ // Don't tick if not valid (dead), otherwise we load chunks below -+ if (this.player.valid) { -+ // Paper end - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -341,7 +351,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.r = null; - this.D = false; - this.E = 0; -- } -+ }} // Paper - end if (valid) - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66c1a9ca392b29fe2191577d32c70b214fa7293d..c7e78d0626fa0dd18021c1a0827a10c08ab10b4a 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -41,6 +41,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutEntityStatus; - import net.minecraft.network.protocol.game.PacketPlayOutExperience; - import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; - import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.network.protocol.game.PacketPlayOutLogin; - import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; -@@ -60,6 +61,8 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.PlayerInteractManager; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -128,11 +131,12 @@ public abstract class PlayerList { - private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map j = Maps.newHashMap(); -+ private final Map j = Maps.newHashMap();Map getUUIDMap() { return j; } // Paper - OBFHELPER - private final GameProfileBanList k; - private final IpBanList l; - private final OpList operators; - private final WhiteList whitelist; -+ private final Map pendingPlayers = Maps.newHashMap(); // Paper - // CraftBukkit start - // private final Map o; - // private final Map p; -@@ -171,6 +175,11 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -+ if (prev != null) { -+ disconnectPendingPlayer(prev); -+ } -+ entityplayer.networkManager = networkmanager; // Paper - entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); -@@ -184,7 +193,7 @@ public abstract class PlayerList { - if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { - NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; -- } -+ }String lastKnownName = s; // Paper - // CraftBukkit end - - if (nbttagcompound != null) { -@@ -259,6 +268,51 @@ public abstract class PlayerList { - entityplayer.getRecipeBook().a(entityplayer); - this.sendScoreboard(worldserver1.getScoreboard(), entityplayer); - this.server.invalidatePingSample(); -+ // Paper start - async load spawn in chunk -+ WorldServer finalWorldserver = worldserver1; -+ int chunkX = loc.getBlockX() >> 4; -+ int chunkZ = loc.getBlockZ() >> 4; -+ final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); -+ PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; -+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -+ worldserver1.getChunkProvider().tickDistanceManager(); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(chunk); -+ } -+ }).thenAccept(chunk -> { -+ playerconnection.playerJoinReady = () -> { -+ postChunkLoadJoin( -+ entityplayer, finalWorldserver, networkmanager, playerconnection, -+ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName -+ ); -+ }; -+ }); -+ } -+ -+ public EntityPlayer getActivePlayer(UUID uuid) { -+ EntityPlayer player = this.getUUIDMap().get(uuid); -+ return player != null ? player : pendingPlayers.get(uuid); -+ } -+ -+ void disconnectPendingPlayer(EntityPlayer entityplayer) { -+ ChatMessage msg = new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]); -+ entityplayer.networkManager.sendPacket(new PacketPlayOutKickDisconnect(msg), (future) -> { -+ entityplayer.networkManager.close(msg); -+ entityplayer.networkManager = null; -+ }); -+ } -+ -+ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver1, NetworkManager networkmanager, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String s) { -+ pendingPlayers.remove(entityplayer.getUniqueID(), entityplayer); -+ if (!networkmanager.isConnected()) { -+ return; -+ } -+ entityplayer.didPlayerJoinEvent = true; -+ // Paper end - ChatMessage chatmessage; - - if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) { -@@ -496,6 +550,7 @@ public abstract class PlayerList { - - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit -+ if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -523,7 +578,7 @@ public abstract class PlayerList { - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -- cserver.getPluginManager().callEvent(playerQuitEvent); -+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) -@@ -576,6 +631,13 @@ public abstract class PlayerList { - // this.p.remove(uuid); - // CraftBukkit end - } -+ // Paper start -+ entityplayer1 = pendingPlayers.get(uuid); -+ if (entityplayer1 == entityplayer) { -+ pendingPlayers.remove(uuid); -+ } -+ entityplayer.networkManager = null; -+ // Paper end - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); -@@ -593,7 +655,7 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.quitMessage(); // Paper - Adventure -+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -612,6 +674,13 @@ public abstract class PlayerList { - list.add(entityplayer); - } - } -+ // Paper start - check pending players too -+ entityplayer = pendingPlayers.get(uuid); -+ if (entityplayer != null) { -+ this.pendingPlayers.remove(uuid); -+ disconnectPendingPlayer(entityplayer); -+ } -+ // Paper end - - Iterator iterator = list.iterator(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7bce3722fb00194f5a913c0b9866b73cfc74611d..8ca7012264528f17ac2e4f15ced96c774fa566d7 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1372,7 +1372,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.lastY = d1; - this.lastZ = d4; - this.setPosition(d3, d1, d4); -- world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit -+ if (valid) world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit // Paper - } - - public void d(Vec3D vec3d) { diff --git a/Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch deleted file mode 100644 index 49c31930c672..000000000000 --- a/Spigot-Server-Patches/0452-Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 2277 <38501234+2277@users.noreply.github.com> -Date: Tue, 31 Mar 2020 10:33:55 +0100 -Subject: [PATCH] Move player to spawn point if spawn in unloaded world - -The code following this has better support for null worlds to move -them back to the world spawn. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 8ca7012264528f17ac2e4f15ced96c774fa566d7..675d0cb32efc99f66c4d2b000bf49cf1c065a5e2 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1808,9 +1808,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - bworld = server.getWorld(worldName); - } - -- if (bworld == null) { -- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -- } -+ // Paper start - Move player to spawn point if spawn in unloaded world -+// if (bworld == null) { -+// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -+// } -+ // Paper end - Move player to spawn point if spawn in unloaded world - - spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle()); - } diff --git a/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch b/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index 325aa1c5a1bd..000000000000 --- a/Spigot-Server-Patches/0453-Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:44:50 -0700 -Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index dc9e12c38d1682f6c4558ca07b781de2226c0621..850225509a5398ddcc9335bf88e99bde662bfc91 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -1931,7 +1931,16 @@ public abstract class EntityLiving extends Entity { - - EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); - if (damagesource.getEntity() instanceof EntityHuman) { -- ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired -+ // Paper start - PlayerAttackEntityCooldownResetEvent -+ if (damagesource.getEntity() instanceof EntityPlayer) { -+ EntityPlayer player = (EntityPlayer) damagesource.getEntity(); -+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackCooldown(0F)).callEvent()) { -+ player.resetAttackCooldown(); -+ } -+ } else { -+ ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); -+ } -+ // Paper end - } - if (event.isCancelled()) { - return false; diff --git a/Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch deleted file mode 100644 index df3e2c58ef41..000000000000 --- a/Spigot-Server-Patches/0454-Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Apr 2020 03:51:53 -0400 -Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor - -ChunkMapDistance polls multiple entries for pendingChunkUpdates - -Each of these have the potential to move a chunk in and out of -"Loaded" state, which will result in multiple callbacks being -needed within a single tick of ChunkMapDistance - -Use an ArrayDeque to store this Queue - -We make sure to also implement a pattern that is recursion safe too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6e4a47581843be42b77034fec16b1d531a5b5759..d509cfd2da99233e5142abd176cc50ccea7c32b6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -162,24 +162,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); - public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { - -- private Runnable queued; -+ // Paper start - replace impl with recursive safe multi entry queue -+ // it's possible to schedule multiple tasks currently, so it's vital we change this impl -+ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency -+ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); - - @Override - public void execute(Runnable runnable) { -- if (queued != null) { -- throw new IllegalStateException("Already queued"); -+ if (queued == null) { -+ queued = new java.util.ArrayDeque<>(); - } -- queued = runnable; -+ queued.add(runnable); - } - - @Override - public void run() { -- Runnable task = queued; -+ if (queued == null) { -+ return; -+ } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { - task.run(); - } - } -+ // Paper end - }; - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch b/Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch deleted file mode 100644 index 895675ad8005..000000000000 --- a/Spigot-Server-Patches/0455-Don-t-fire-BlockFade-on-worldgen-threads.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 23 Apr 2020 01:36:39 -0400 -Subject: [PATCH] Don't fire BlockFade on worldgen threads - -Caused a deadlock - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 5ef38414d87fbce453e3ab11579c89a8ff089ae0..e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -94,6 +94,7 @@ public class BlockFire extends BlockFireAbstract { - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start -+ if (!(generatoraccess instanceof WorldServer)) return this.canPlace(iblockdata, generatoraccess, blockposition) ? (IBlockData) this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)) : Blocks.AIR.getBlockData(); // Paper - don't fire events in world generation - if (!this.canPlace(iblockdata, generatoraccess, blockposition)) { - // Suppress during worldgen - if (!(generatoraccess instanceof World)) { -@@ -109,7 +110,7 @@ public class BlockFire extends BlockFireAbstract { - return blockState.getHandle(); - } - } -- return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); -+ return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); // Paper - diff on change, see "don't fire events in world generation" - // CraftBukkit end - } - diff --git a/Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch b/Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch deleted file mode 100644 index 68c8e2168d5a..000000000000 --- a/Spigot-Server-Patches/0456-Add-phantom-creative-and-insomniac-controls.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 25 Apr 2020 15:13:41 -0500 -Subject: [PATCH] Add phantom creative and insomniac controls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index cd248eb6be663e8be33f2c3c6b06b77b6d5753a4..46ac6d91422423f1e03b86d3efa3241f2599000d 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -625,4 +625,11 @@ public class PaperWorldConfig { - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); - } -+ -+ public boolean phantomIgnoreCreative = true; -+ public boolean phantomOnlyAttackInsomniacs = true; -+ private void phantomSettings() { -+ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); -+ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 1a6f8aec32af85717f5d56e0b00a02cda88ce028..c8d7ea8cfa4945af4a6675172b931a4cc3ca2801 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -3,6 +3,9 @@ package net.minecraft.world.entity; - import com.google.common.base.Predicates; - import java.util.function.Predicate; - import javax.annotation.Nullable; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.stats.StatisticList; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.EnumDifficulty; - import net.minecraft.world.IInventory; - import net.minecraft.world.entity.player.EntityHuman; -@@ -31,6 +34,7 @@ public final class IEntitySelector { - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -+ public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - - // Paper start - public static final Predicate affectsSpawning = (entity) -> { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 6c498d4345df35a411d155799ac56e47c9c48114..42cf3fa42b73739182d26fbb524ee5b304c799b2 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -262,6 +262,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - - if (EntityPhantom.this.a((EntityLiving) entityhuman, PathfinderTargetCondition.a)) { -+ if (!world.paperConfig.phantomOnlyAttackInsomniacs || IEntitySelector.isInsomniac.test(entityhuman)) // Paper - EntityPhantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason - return true; - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index 96a5a6569387a25b15a06aaab3bd9d033547e875..e4f5e570636862481aac92ec9b74d6cf5723eb6e 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -53,7 +53,7 @@ public class MobSpawnerPhantom implements MobSpawner { - while (iterator.hasNext()) { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - -- if (!entityhuman.isSpectator()) { -+ if (!entityhuman.isSpectator() && (!worldserver.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper - BlockPosition blockposition = entityhuman.getChunkCoordinates(); - - if (!worldserver.getDimensionManager().hasSkyLight() || blockposition.getY() >= worldserver.getSeaLevel() && worldserver.e(blockposition)) { diff --git a/Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch deleted file mode 100644 index 92b2bb339116..000000000000 --- a/Spigot-Server-Patches/0457-Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 25 Apr 2020 06:46:35 -0400 -Subject: [PATCH] Fix numerous item duplication issues and teleport issues - -This notably fixes the newest "Donkey Dupe", but also fixes a lot -of dupe bugs in general around nether portals and entity world transfer - -We also fix item duplication generically by anytime we clone an item -to drop it on the ground, destroy the source item. - -This avoid an itemstack ever existing twice in the world state pre -clean up stage. - -So even if something NEW comes up, it would be impossible to drop the -same item twice because the source was destroyed. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 675d0cb32efc99f66c4d2b000bf49cf1c065a5e2..cb5c93dca3b947462b89f79c60c7562085684b87 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1969,11 +1969,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } else { - // CraftBukkit start - Capture drops for death event - if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) { -- ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); -+ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // Paper - mirror so we can destroy it later - return null; - } - // CraftBukkit end -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack); -+ EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack.cloneItemStack()); // Paper - clone so we can destroy original -+ itemstack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - - entityitem.defaultPickupDelay(); - // CraftBukkit start -@@ -2621,6 +2622,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - @Nullable - public Entity teleportTo(WorldServer worldserver, BlockPosition location) { - // CraftBukkit end -+ // Paper start - fix bad state entities causing dupes -+ if (!isAlive() || !valid) { -+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); -+ return null; -+ } -+ // Paper end - if (this.world instanceof WorldServer && !this.dead) { - this.world.getMethodProfiler().enter("changeDimension"); - // CraftBukkit start -@@ -2641,6 +2648,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit end - - this.world.getMethodProfiler().exitEnter("reloading"); -+ // Paper start - Change lead drop timing to prevent dupe -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).unleash(true, true); // Paper drop lead -+ } -+ // Paper end - Entity entity = this.getEntityType().a((World) worldserver); - - if (entity != null) { -@@ -2654,10 +2666,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit start - Forward the CraftEntity to the new entity - this.getBukkitEntity().setHandle(entity); - entity.bukkitEntity = this.getBukkitEntity(); -- -- if (this instanceof EntityInsentient) { -- ((EntityInsentient) this).unleash(true, false); // Unleash to prevent duping of leads. -- } - // CraftBukkit end - } - -@@ -2782,7 +2790,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean canPortal() { -- return true; -+ return isAlive() && valid; // Paper - } - - public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 69361caebf0d3caa5195b519a16691705ac5e16a..5eb900619951083b9a777b1645cb5495b99968ec 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -602,7 +602,7 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.handItems.size(); ++i) { - itemstack = (ItemStack) this.handItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.handItems.set(i, ItemStack.b); - } - } -@@ -610,7 +610,7 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.armorItems.size(); ++i) { - itemstack = (ItemStack) this.armorItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.armorItems.set(i, ItemStack.b); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index dbfd500ad18262e4c1af40308229802fa0cb2e5d..ce02da607d07d22cb0b71e032efa0a8f45148d0c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -824,7 +824,8 @@ public class CraftEventFactory { - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { - if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; - -- world.dropItem(entity.getLocation(), stack); -+ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS -+ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items - } - - return event; diff --git a/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch b/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch deleted file mode 100644 index 09d52a49dcfc..000000000000 --- a/Spigot-Server-Patches/0458-Implement-Brigadier-Mojang-API.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 18:15:29 -0400 -Subject: [PATCH] Implement Brigadier Mojang API - -Adds AsyncPlayerSendCommandsEvent - - Allows modifying on a per command basis what command data they see. - -Adds CommandRegisteredEvent - - Allows manipulating the CommandNode to add more children/metadata for the client - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index c97424b401147be53ffa7e2a2a3271d696752efe..07d3dec9f613013aac72f3f5db17089ebe5ee770 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -354,6 +354,7 @@ public class CommandDispatcher { - bukkit.add(node.getName()); - } - // Paper start - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - MinecraftServer.getServer().execute(() -> { - runSync(entityplayer, bukkit, rootcommandnode); - }); -@@ -361,6 +362,7 @@ public class CommandDispatcher { - - private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { - // Paper end - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index eb2c9d2248a8647beee9960c5016a83f35aa1247..b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -38,7 +38,7 @@ import net.minecraft.world.phys.Vec3D; - - import com.mojang.brigadier.tree.CommandNode; // CraftBukkit - --public class CommandListenerWrapper implements ICompletionProvider { -+public class CommandListenerWrapper implements ICompletionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper - - public static final SimpleCommandExceptionType a = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.player")); - public static final SimpleCommandExceptionType b = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.entity")); -@@ -150,6 +150,25 @@ public class CommandListenerWrapper implements ICompletionProvider { - return this.g; - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity getBukkitEntity() { -+ return getEntity() != null ? getEntity().getBukkitEntity() : null; -+ } -+ -+ @Override -+ public org.bukkit.World getBukkitWorld() { -+ return getWorld() != null ? getWorld().getWorld() : null; -+ } -+ -+ @Override -+ public org.bukkit.Location getBukkitLocation() { -+ Vec3D pos = getPosition(); -+ org.bukkit.World world = getBukkitWorld(); -+ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 443247b03b8352c4dd453270dccdbd7eb5f0944b..b6d326ea30a806240e4a87c277b3cd73a04c805c 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -770,8 +770,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); - - this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ // Paper start -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper -+ // Paper end - }); - }); - } -@@ -780,7 +784,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); - completions.forEach(builder::suggest); -- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestEvent.getSuggestions())); - } - // Paper end - async tab completion - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -index 23d922a8baac01144602fd7813e9e76abc5335a3..8ddd246ad69a2e53749d38c369af701c161de54e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -@@ -17,7 +17,7 @@ import net.minecraft.commands.CommandListenerWrapper; - import org.bukkit.command.Command; - import org.bukkit.craftbukkit.CraftServer; - --public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { -+public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper - - private final CraftServer server; - private final Command command; -@@ -28,10 +28,19 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { -- return dispatcher.register( -- LiteralArgumentBuilder.literal(label).requires(this).executes(this) -- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) -- ); -+ // Paper start - Expose Brigadier to Paper-MojangAPI -+ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); -+ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); -+ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); -+ literal.addChild(defaultArgs); -+ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); -+ if (!event.callEvent()) { -+ return null; -+ } -+ literal = event.getLiteral(); -+ root.addChild(literal); -+ return literal; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0459-Villager-Restocks-API.patch b/Spigot-Server-Patches/0459-Villager-Restocks-API.patch deleted file mode 100644 index d136893c4578..000000000000 --- a/Spigot-Server-Patches/0459-Villager-Restocks-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:01 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index d7e152f7147bb599ce21dc605ebbd76e82eced26..d2850b003f8672122e70da0d52da1de59b2b01dd 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -113,7 +113,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - private long bA; - private int bB; - private long bC; -- private int bD; -+ private int bD; public int getRestocksToday(){ return this.bD; } public void setRestocksToday(int restocksToday){ this.bD = restocksToday; } // Paper OBFHELPER - private long bE; - private boolean bF; - private static final ImmutableList> bG = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index b020bc9e78a524b4745844ceb99249949c5ab6a4..4b2451179cdda918808ea7001f5033c7e5a8b9ac 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -84,6 +84,18 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - getHandle().setExperience(experience); - } - -+ // Paper start -+ @Override -+ public int getRestocksToday() { -+ return getHandle().getRestocksToday(); -+ } -+ -+ @Override -+ public void setRestocksToday(int restocksToday) { -+ getHandle().setRestocksToday(restocksToday); -+ } -+ // Paper end -+ - @Override - public boolean sleep(Location location) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch b/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch deleted file mode 100644 index 37c6dde53bce..000000000000 --- a/Spigot-Server-Patches/0460-Validate-PickItem-Packet-and-kick-for-invalid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 May 2020 03:09:46 -0400 -Subject: [PATCH] Validate PickItem Packet and kick for invalid - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index b6d326ea30a806240e4a87c277b3cd73a04c805c..6db70005ebc99b19185b8efca550a0783ea05cad 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -883,7 +883,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - @Override - public void a(PacketPlayInPickItem packetplayinpickitem) { - PlayerConnectionUtils.ensureMainThread(packetplayinpickitem, this, this.player.getWorldServer()); -- this.player.inventory.c(packetplayinpickitem.b()); -+ // Paper start - validate pick item position -+ if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { -+ PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -+ this.disconnect("Invalid hotbar selection (Hacking?)"); -+ return; -+ } -+ this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, packetplayinpickitem.b(), this.player.inventory.getItem(packetplayinpickitem.b()))); - this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); diff --git a/Spigot-Server-Patches/0461-Expose-game-version.patch b/Spigot-Server-Patches/0461-Expose-game-version.patch deleted file mode 100644 index adc8f3c549c7..000000000000 --- a/Spigot-Server-Patches/0461-Expose-game-version.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Fri, 1 May 2020 17:39:26 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b55b2a27adba357faee0f260c8d7cc247d8d8238..688bf56b331cc4b6b9664365f97a98720ec522a9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -518,6 +518,13 @@ public final class CraftServer implements Server { - return bukkitVersion; - } - -+ // Paper start - expose game version -+ @Override -+ public String getMinecraftVersion() { -+ return console.getVersion(); -+ } -+ // Paper end -+ - @Override - public List getOnlinePlayers() { - return this.playerView; diff --git a/Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch b/Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch deleted file mode 100644 index e817b3873784..000000000000 --- a/Spigot-Server-Patches/0462-Optimize-Voxel-Shape-Merging.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 May 2020 22:35:09 -0400 -Subject: [PATCH] Optimize Voxel Shape Merging - -This method shows up as super hot in profiler, and also a high "self" time. - -Upon analyzing, it appears most usages of this method fall down to the final -else statement of the nasty ternary. - -Upon even further analyzation, it appears then the majority of those have a -consistent list 1.... One with Infinity head and Tails. - -First optimization is to detect these infinite states and immediately return that -VoxelShapeMergerList so we can avoid testing the rest for most cases. - -Break the method into 2 to help the JVM promote inlining of this fast path. - -Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot -with a high self time... - -Well, knowing that in most cases our list 1 is actualy the same value, it allows -us to know that with an infinite list1, the result on the merger is essentially -list2 as the final values. - -This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) -and compute a deterministic result for the MergerList values. - -Additionally, this lets us avoid even allocating new objects for this too, further -reducing memory usage. - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index c58d380b96e81d65d7c254a9e53017e5157769b0..57a4b4fcb6f89aacadcca49b25153157c8d06cc3 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; - - public final class VoxelShapeMergerList implements VoxelShapeMerger { - -- private final DoubleArrayList a; -+ private final DoubleList a; // Paper - private final IntArrayList b; - private final IntArrayList c; - -+ // Paper start -+ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); -+ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); -+ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); -+ // Paper end -+ - protected VoxelShapeMergerList(DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int i = 0; - int j = 0; -@@ -18,6 +24,22 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - int l = doublelist1.size(); - int i1 = k + l; - -+ // Paper start - optimize common path of infinity doublelist -+ int size = doublelist.size(); -+ double tail = doublelist.getDouble(size - 1); -+ double head = doublelist.getDouble(0); -+ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !flag && !flag1 && (size == 2 || size == 4)) { -+ this.a = doublelist1; -+ if (size == 2) { -+ this.b = INFINITE_B_0; -+ } else { -+ this.b = INFINITE_B_1; -+ } -+ this.c = INFINITE_C; -+ return; -+ } -+ // Paper end -+ - this.a = new DoubleArrayList(i1); - this.b = new IntArrayList(i1); - this.c = new IntArrayList(i1); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 24ecac40625629b0bbe460e7fc984b147ede1f1f..2d7405d1fa7c8f378bebe86f5d0de57a129ed92d 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -329,9 +329,21 @@ public final class VoxelShapes { - } - - @VisibleForTesting -- protected static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { -+ private static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { // Paper - private -+ // Paper start - fast track the most common scenario -+ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause -+ // This is actually the most common path, so jump to it straight away -+ if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Split out rest to hopefully inline the above -+ return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); -+ } -+ -+ private static VoxelShapeMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int j = doublelist.size() - 1; - int k = doublelist1.size() - 1; -+ // Paper note - Rewrite below as optimized order if instead of nasty ternary - - if (doublelist instanceof VoxelShapeCubePoint && doublelist1 instanceof VoxelShapeCubePoint) { - long l = a(j, k); -@@ -341,7 +353,22 @@ public final class VoxelShapes { - } - } - -- return (VoxelShapeMerger) (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist, doublelist1, false) : (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist1, doublelist, true) : (j == k && Objects.equals(doublelist, doublelist1) ? (doublelist instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist : (doublelist1 instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist1 : new VoxelShapeMergerIdentical(doublelist))) : new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1)))); -+ // Identical happens more often than Disjoint -+ if (j == k && Objects.equals(doublelist, doublelist1)) { -+ if (doublelist instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist; -+ } else if (doublelist1 instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist1; -+ } -+ return new VoxelShapeMergerIdentical(doublelist); -+ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist, doublelist1, false); -+ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist1, doublelist, true); -+ } else { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Paper end - } - - public interface a { diff --git a/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch deleted file mode 100644 index 8676a856f79d..000000000000 --- a/Spigot-Server-Patches/0463-Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 May 2020 01:08:56 -0400 -Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache - -See: https://www.evanjones.ca/java-bytebuffer-leak.html - -This is potentially a source of lots of native memory usage. - -We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. - -Region File usage fixed in previous patch should of tecnically only been somewhat -temporary until GC finally gets it some time later, but between all the various -plugins doing IO on various threads, this hidden detail of the JDK could be -keeping long lived large direct buffers in cache. - -Set system properly at server startup if not set already to help protect from this. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 777116a0a0be6a5a00b1443204d6c53803af8051..6cae7454f3cf5b246300bac489b38ea65e2185c9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -28,6 +28,7 @@ public class Main { - } - // Paper end - // Todo: Installation script -+ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size - OptionParser parser = new OptionParser() { - { - acceptsAll(asList("?", "help"), "Show the help"); diff --git a/Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch b/Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch deleted file mode 100644 index a31429141629..000000000000 --- a/Spigot-Server-Patches/0464-Implement-Mob-Goal-API.patch +++ /dev/null @@ -1,1170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Fri, 3 Jan 2020 16:26:19 +0100 -Subject: [PATCH] Implement Mob Goal API - - -diff --git a/pom.xml b/pom.xml -index dd5f7dba3610b63aa16088a94bf3b459d496cb3c..1869a7fdb8e48dc94cd9c22c7d85298a06729b5b 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -176,6 +176,13 @@ - 1.3 - test - -+ -+ -+ io.github.classgraph -+ classgraph -+ 4.8.47 -+ test -+ - - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f62d0ee49ebda2b0c7a136562b24ee038502d048 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +1,530 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.destroystokyo.paper.entity.RangedEntity; -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; -+import com.google.common.collect.BiMap; -+import com.google.common.collect.HashBiMap; -+import java.lang.reflect.Constructor; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.EntityAgeable; -+import net.minecraft.world.entity.EntityCreature; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.EntityTameableAnimal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ambient.EntityAmbient; -+import net.minecraft.world.entity.ambient.EntityBat; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityCat; -+import net.minecraft.world.entity.animal.EntityChicken; -+import net.minecraft.world.entity.animal.EntityCod; -+import net.minecraft.world.entity.animal.EntityCow; -+import net.minecraft.world.entity.animal.EntityDolphin; -+import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.animal.EntityFishSchool; -+import net.minecraft.world.entity.animal.EntityFox; -+import net.minecraft.world.entity.animal.EntityGolem; -+import net.minecraft.world.entity.animal.EntityIronGolem; -+import net.minecraft.world.entity.animal.EntityMushroomCow; -+import net.minecraft.world.entity.animal.EntityOcelot; -+import net.minecraft.world.entity.animal.EntityPanda; -+import net.minecraft.world.entity.animal.EntityParrot; -+import net.minecraft.world.entity.animal.EntityPerchable; -+import net.minecraft.world.entity.animal.EntityPig; -+import net.minecraft.world.entity.animal.EntityPolarBear; -+import net.minecraft.world.entity.animal.EntityPufferFish; -+import net.minecraft.world.entity.animal.EntityRabbit; -+import net.minecraft.world.entity.animal.EntitySalmon; -+import net.minecraft.world.entity.animal.EntitySheep; -+import net.minecraft.world.entity.animal.EntitySnowman; -+import net.minecraft.world.entity.animal.EntitySquid; -+import net.minecraft.world.entity.animal.EntityTropicalFish; -+import net.minecraft.world.entity.animal.EntityTurtle; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.EntityWolf; -+import net.minecraft.world.entity.animal.horse.EntityHorse; -+import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseChestedAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseDonkey; -+import net.minecraft.world.entity.animal.horse.EntityHorseMule; -+import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; -+import net.minecraft.world.entity.animal.horse.EntityHorseZombie; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.animal.horse.EntityLlamaTrader; -+import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.boss.wither.EntityWither; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityCaveSpider; -+import net.minecraft.world.entity.monster.EntityCreeper; -+import net.minecraft.world.entity.monster.EntityDrowned; -+import net.minecraft.world.entity.monster.EntityEnderman; -+import net.minecraft.world.entity.monster.EntityEndermite; -+import net.minecraft.world.entity.monster.EntityEvoker; -+import net.minecraft.world.entity.monster.EntityGhast; -+import net.minecraft.world.entity.monster.EntityGiantZombie; -+import net.minecraft.world.entity.monster.EntityGuardian; -+import net.minecraft.world.entity.monster.EntityGuardianElder; -+import net.minecraft.world.entity.monster.EntityIllagerAbstract; -+import net.minecraft.world.entity.monster.EntityIllagerIllusioner; -+import net.minecraft.world.entity.monster.EntityIllagerWizard; -+import net.minecraft.world.entity.monster.EntityMagmaCube; -+import net.minecraft.world.entity.monster.EntityMonster; -+import net.minecraft.world.entity.monster.EntityMonsterPatrolling; -+import net.minecraft.world.entity.monster.EntityPhantom; -+import net.minecraft.world.entity.monster.EntityPigZombie; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.EntityRavager; -+import net.minecraft.world.entity.monster.EntityShulker; -+import net.minecraft.world.entity.monster.EntitySilverfish; -+import net.minecraft.world.entity.monster.EntitySkeleton; -+import net.minecraft.world.entity.monster.EntitySkeletonAbstract; -+import net.minecraft.world.entity.monster.EntitySkeletonStray; -+import net.minecraft.world.entity.monster.EntitySkeletonWither; -+import net.minecraft.world.entity.monster.EntitySlime; -+import net.minecraft.world.entity.monster.EntitySpider; -+import net.minecraft.world.entity.monster.EntityStrider; -+import net.minecraft.world.entity.monster.EntityVex; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityWitch; -+import net.minecraft.world.entity.monster.EntityZoglin; -+import net.minecraft.world.entity.monster.EntityZombie; -+import net.minecraft.world.entity.monster.EntityZombieHusk; -+import net.minecraft.world.entity.monster.EntityZombieVillager; -+import net.minecraft.world.entity.monster.IRangedEntity; -+import net.minecraft.world.entity.monster.hoglin.EntityHoglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinAbstract; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinBrute; -+import net.minecraft.world.entity.npc.EntityVillager; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; -+import net.minecraft.world.entity.npc.EntityVillagerTrader; -+import net.minecraft.world.entity.raid.EntityRaider; -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.AbstractHorse; -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Ageable; -+import org.bukkit.entity.Ambient; -+import org.bukkit.entity.Animals; -+import org.bukkit.entity.Bat; -+import org.bukkit.entity.Bee; -+import org.bukkit.entity.Blaze; -+import org.bukkit.entity.Cat; -+import org.bukkit.entity.CaveSpider; -+import org.bukkit.entity.ChestedHorse; -+import org.bukkit.entity.Chicken; -+import org.bukkit.entity.Cod; -+import org.bukkit.entity.Cow; -+import org.bukkit.entity.Creature; -+import org.bukkit.entity.Creeper; -+import org.bukkit.entity.Dolphin; -+import org.bukkit.entity.Donkey; -+import org.bukkit.entity.Drowned; -+import org.bukkit.entity.ElderGuardian; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Endermite; -+import org.bukkit.entity.Evoker; -+import org.bukkit.entity.Fish; -+import org.bukkit.entity.Flying; -+import org.bukkit.entity.Fox; -+import org.bukkit.entity.Ghast; -+import org.bukkit.entity.Giant; -+import org.bukkit.entity.Golem; -+import org.bukkit.entity.Guardian; -+import org.bukkit.entity.Hoglin; -+import org.bukkit.entity.Horse; -+import org.bukkit.entity.Husk; -+import org.bukkit.entity.Illager; -+import org.bukkit.entity.Illusioner; -+import org.bukkit.entity.IronGolem; -+import org.bukkit.entity.Llama; -+import org.bukkit.entity.MagmaCube; -+import org.bukkit.entity.Mob; -+import org.bukkit.entity.Monster; -+import org.bukkit.entity.Mule; -+import org.bukkit.entity.MushroomCow; -+import org.bukkit.entity.Ocelot; -+import org.bukkit.entity.Panda; -+import org.bukkit.entity.Parrot; -+import org.bukkit.entity.Phantom; -+import org.bukkit.entity.Pig; -+import org.bukkit.entity.PigZombie; -+import org.bukkit.entity.Piglin; -+import org.bukkit.entity.PiglinAbstract; -+import org.bukkit.entity.PiglinBrute; -+import org.bukkit.entity.Pillager; -+import org.bukkit.entity.PolarBear; -+import org.bukkit.entity.PufferFish; -+import org.bukkit.entity.Rabbit; -+import org.bukkit.entity.Raider; -+import org.bukkit.entity.Ravager; -+import org.bukkit.entity.Salmon; -+import org.bukkit.entity.Sheep; -+import org.bukkit.entity.Shulker; -+import org.bukkit.entity.Silverfish; -+import org.bukkit.entity.Skeleton; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.entity.Slime; -+import org.bukkit.entity.Snowman; -+import org.bukkit.entity.Spellcaster; -+import org.bukkit.entity.Spider; -+import org.bukkit.entity.Squid; -+import org.bukkit.entity.Stray; -+import org.bukkit.entity.Strider; -+import org.bukkit.entity.Tameable; -+import org.bukkit.entity.TraderLlama; -+import org.bukkit.entity.TropicalFish; -+import org.bukkit.entity.Turtle; -+import org.bukkit.entity.Vex; -+import org.bukkit.entity.Villager; -+import org.bukkit.entity.Vindicator; -+import org.bukkit.entity.WanderingTrader; -+import org.bukkit.entity.WaterMob; -+import org.bukkit.entity.Witch; -+import org.bukkit.entity.Wither; -+import org.bukkit.entity.WitherSkeleton; -+import org.bukkit.entity.Wolf; -+import org.bukkit.entity.Zoglin; -+import org.bukkit.entity.Zombie; -+import org.bukkit.entity.ZombieHorse; -+import org.bukkit.entity.ZombieVillager; -+ -+public class MobGoalHelper { -+ -+ private static final BiMap deobfuscationMap = HashBiMap.create(); -+ private static final Map, Class> entityClassCache = new HashMap<>(); -+ private static final Map, Class> bukkitMap = new HashMap<>(); -+ -+ static final Set ignored = new HashSet<>(); -+ -+ static { -+ // TODO these kinda should be checked on each release, in case obfuscation changes -+ deobfuscationMap.put("bee_b", "bee_attack"); -+ deobfuscationMap.put("bee_c", "bee_become_angry"); -+ deobfuscationMap.put("bee_d", "bee_enter_hive"); -+ deobfuscationMap.put("bee_e", "bee_go_to_hive"); -+ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); -+ deobfuscationMap.put("bee_g", "bee_grow_crop"); -+ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); -+ deobfuscationMap.put("bee_i", "bee_locate_hive"); -+ deobfuscationMap.put("bee_k", "bee_pollinate"); -+ deobfuscationMap.put("bee_l", "bee_wander"); -+ deobfuscationMap.put("cat_a", "cat_avoid_entity"); -+ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); -+ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); -+ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); -+ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); -+ deobfuscationMap.put("drowned_a", "drowned_attack"); -+ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); -+ deobfuscationMap.put("drowned_c", "drowned_goto_water"); -+ deobfuscationMap.put("drowned_e", "drowned_swim_up"); -+ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); -+ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); -+ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); -+ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); -+ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); -+ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); -+ deobfuscationMap.put("fish_b", "fish_swim"); -+ deobfuscationMap.put("fox_a", "fox_defend_trusted"); -+ deobfuscationMap.put("fox_b", "fox_faceplant"); -+ deobfuscationMap.put("fox_e", "fox_breed"); -+ deobfuscationMap.put("fox_f", "fox_eat_berries"); -+ deobfuscationMap.put("fox_g", "fox_float"); -+ deobfuscationMap.put("fox_h", "fox_follow_parent"); -+ deobfuscationMap.put("fox_j", "fox_look_at_player"); -+ deobfuscationMap.put("fox_l", "fox_melee_attack"); -+ deobfuscationMap.put("fox_n", "fox_panic"); -+ deobfuscationMap.put("fox_o", "fox_pounce"); -+ deobfuscationMap.put("fox_p", "fox_search_for_items"); -+ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); -+ deobfuscationMap.put("fox_r", "fox_perch_and_search"); -+ deobfuscationMap.put("fox_s", "fox_seek_shelter"); -+ deobfuscationMap.put("fox_t", "fox_sleep"); -+ deobfuscationMap.put("fox_u", "fox_stalk_prey"); -+ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); -+ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); -+ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); -+ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); -+ deobfuscationMap.put("llama_a", "llama_attack_wolf"); -+ deobfuscationMap.put("llama_c", "llama_hurt_by"); -+ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); -+ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); -+ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); -+ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); -+ deobfuscationMap.put("panda_b", "panda_attack"); -+ deobfuscationMap.put("panda_c", "panda_avoid"); -+ deobfuscationMap.put("panda_d", "panda_breed"); -+ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); -+ deobfuscationMap.put("panda_f", "panda_lie_on_back"); -+ deobfuscationMap.put("panda_g", "panda_look_at_player"); -+ deobfuscationMap.put("panda_i", "panda_panic"); -+ deobfuscationMap.put("panda_j", "panda_roll"); -+ deobfuscationMap.put("panda_k", "panda_sit"); -+ deobfuscationMap.put("panda_l", "panda_sneeze"); -+ deobfuscationMap.put("phantom_b", "phantom_attack_player"); -+ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); -+ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); -+ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); -+ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); -+ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); -+ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); -+ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); -+ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); -+ deobfuscationMap.put("raider_a", "raider_hold_ground"); -+ deobfuscationMap.put("raider_b", "raider_obtain_banner"); -+ deobfuscationMap.put("raider_c", "raider_celebration"); -+ deobfuscationMap.put("raider_d", "raider_move_through_village"); -+ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); -+ deobfuscationMap.put("shulker_a", "shulker_attack"); -+ deobfuscationMap.put("shulker_c", "shulker_defense"); -+ deobfuscationMap.put("shulker_d", "shulker_nearest"); -+ deobfuscationMap.put("shulker_e", "shulker_peek"); -+ deobfuscationMap.put("squid_a", "squid_flee"); -+ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); -+ deobfuscationMap.put("strider_a", "strider_go_to_lava"); -+ deobfuscationMap.put("turtle_a", "turtle_breed"); -+ deobfuscationMap.put("turtle_b", "turtle_go_home"); -+ deobfuscationMap.put("turtle_c", "turtle_goto_water"); -+ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); -+ deobfuscationMap.put("turtle_f", "turtle_panic"); -+ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); -+ deobfuscationMap.put("turtle_i", "turtle_tempt"); -+ deobfuscationMap.put("turtle_j", "turtle_travel"); -+ deobfuscationMap.put("vex_a", "vex_charge_attack"); -+ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); -+ deobfuscationMap.put("vex_d", "vex_random_move"); -+ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); -+ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); -+ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); -+ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); -+ deobfuscationMap.put("wither_a", "wither_do_nothing"); -+ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); -+ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); -+ -+ ignored.add("selector_1"); -+ ignored.add("selector_2"); -+ ignored.add("wrapped"); -+ -+ bukkitMap.put(EntityInsentient.class, Mob.class); -+ bukkitMap.put(EntityAgeable.class, Ageable.class); -+ bukkitMap.put(EntityAmbient.class, Ambient.class); -+ bukkitMap.put(EntityAnimal.class, Animals.class); -+ bukkitMap.put(EntityBat.class, Bat.class); -+ bukkitMap.put(EntityBee.class, Bee.class); -+ bukkitMap.put(EntityBlaze.class, Blaze.class); -+ bukkitMap.put(EntityCat.class, Cat.class); -+ bukkitMap.put(EntityCaveSpider.class, CaveSpider.class); -+ bukkitMap.put(EntityChicken.class, Chicken.class); -+ bukkitMap.put(EntityCod.class, Cod.class); -+ bukkitMap.put(EntityCow.class, Cow.class); -+ bukkitMap.put(EntityCreature.class, Creature.class); -+ bukkitMap.put(EntityCreeper.class, Creeper.class); -+ bukkitMap.put(EntityDolphin.class, Dolphin.class); -+ bukkitMap.put(EntityDrowned.class, Drowned.class); -+ bukkitMap.put(EntityEnderDragon.class, EnderDragon.class); -+ bukkitMap.put(EntityEnderman.class, Enderman.class); -+ bukkitMap.put(EntityEndermite.class, Endermite.class); -+ bukkitMap.put(EntityEvoker.class, Evoker.class); -+ bukkitMap.put(EntityFish.class, Fish.class); -+ bukkitMap.put(EntityFishSchool.class, Fish.class); // close enough -+ bukkitMap.put(EntityFlying.class, Flying.class); -+ bukkitMap.put(EntityFox.class, Fox.class); -+ bukkitMap.put(EntityGhast.class, Ghast.class); -+ bukkitMap.put(EntityGiantZombie.class, Giant.class); -+ bukkitMap.put(EntityGolem.class, Golem.class); -+ bukkitMap.put(EntityGuardian.class, Guardian.class); -+ bukkitMap.put(EntityGuardianElder.class, ElderGuardian.class); -+ bukkitMap.put(EntityHorse.class, Horse.class); -+ bukkitMap.put(EntityHorseAbstract.class, AbstractHorse.class); -+ bukkitMap.put(EntityHorseChestedAbstract.class, ChestedHorse.class); -+ bukkitMap.put(EntityHorseDonkey.class, Donkey.class); -+ bukkitMap.put(EntityHorseMule.class, Mule.class); -+ bukkitMap.put(EntityHorseSkeleton.class, SkeletonHorse.class); -+ bukkitMap.put(EntityHorseZombie.class, ZombieHorse.class); -+ bukkitMap.put(EntityIllagerAbstract.class, Illager.class); -+ bukkitMap.put(EntityIllagerIllusioner.class, Illusioner.class); -+ bukkitMap.put(EntityIllagerWizard.class, Spellcaster.class); -+ bukkitMap.put(EntityIronGolem.class, IronGolem.class); -+ bukkitMap.put(EntityLlama.class, Llama.class); -+ bukkitMap.put(EntityLlamaTrader.class, TraderLlama.class); -+ bukkitMap.put(EntityMagmaCube.class, MagmaCube.class); -+ bukkitMap.put(EntityMonster.class, Monster.class); -+ bukkitMap.put(EntityMonsterPatrolling.class, Monster.class); // close enough -+ bukkitMap.put(EntityMushroomCow.class, MushroomCow.class); -+ bukkitMap.put(EntityOcelot.class, Ocelot.class); -+ bukkitMap.put(EntityPanda.class, Panda.class); -+ bukkitMap.put(EntityParrot.class, Parrot.class); -+ bukkitMap.put(EntityPerchable.class, Parrot.class); // close enough -+ bukkitMap.put(EntityPhantom.class, Phantom.class); -+ bukkitMap.put(EntityPig.class, Pig.class); -+ bukkitMap.put(EntityPigZombie.class, PigZombie.class); -+ bukkitMap.put(EntityPillager.class, Pillager.class); -+ bukkitMap.put(EntityPolarBear.class, PolarBear.class); -+ bukkitMap.put(EntityPufferFish.class, PufferFish.class); -+ bukkitMap.put(EntityRabbit.class, Rabbit.class); -+ bukkitMap.put(EntityRaider.class, Raider.class); -+ bukkitMap.put(EntityRavager.class, Ravager.class); -+ bukkitMap.put(EntitySalmon.class, Salmon.class); -+ bukkitMap.put(EntitySheep.class, Sheep.class); -+ bukkitMap.put(EntityShulker.class, Shulker.class); -+ bukkitMap.put(EntitySilverfish.class, Silverfish.class); -+ bukkitMap.put(EntitySkeleton.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonAbstract.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonStray.class, Stray.class); -+ bukkitMap.put(EntitySkeletonWither.class, WitherSkeleton.class); -+ bukkitMap.put(EntitySlime.class, Slime.class); -+ bukkitMap.put(EntitySnowman.class, Snowman.class); -+ bukkitMap.put(EntitySpider.class, Spider.class); -+ bukkitMap.put(EntitySquid.class, Squid.class); -+ bukkitMap.put(EntityTameableAnimal.class, Tameable.class); -+ bukkitMap.put(EntityTropicalFish.class, TropicalFish.class); -+ bukkitMap.put(EntityTurtle.class, Turtle.class); -+ bukkitMap.put(EntityVex.class, Vex.class); -+ bukkitMap.put(EntityVillager.class, Villager.class); -+ bukkitMap.put(EntityVillagerAbstract.class, AbstractVillager.class); -+ bukkitMap.put(EntityVillagerTrader.class, WanderingTrader.class); -+ bukkitMap.put(EntityVindicator.class, Vindicator.class); -+ bukkitMap.put(EntityWaterAnimal.class, WaterMob.class); -+ bukkitMap.put(EntityWitch.class, Witch.class); -+ bukkitMap.put(EntityWither.class, Wither.class); -+ bukkitMap.put(EntityWolf.class, Wolf.class); -+ bukkitMap.put(EntityZombie.class, Zombie.class); -+ bukkitMap.put(EntityZombieHusk.class, Husk.class); -+ bukkitMap.put(EntityZombieVillager.class, ZombieVillager.class); -+ bukkitMap.put(EntityHoglin.class, Hoglin.class); -+ bukkitMap.put(EntityPiglin.class, Piglin.class); -+ bukkitMap.put(EntityPiglinAbstract.class, PiglinAbstract.class); -+ bukkitMap.put(EntityPiglinBrute.class, PiglinBrute.class); -+ bukkitMap.put(EntityStrider.class, Strider.class); -+ bukkitMap.put(EntityZoglin.class, Zoglin.class); -+ } -+ -+ public static String getUsableName(Class clazz) { -+ String name = clazz.getName(); -+ name = name.substring(name.lastIndexOf(".") + 1); -+ boolean flag = false; -+ // inner classes -+ if (name.contains("$")) { -+ String cut = name.substring(name.indexOf("$") + 1); -+ if (cut.length() <= 2) { -+ name = name.replace("Entity", ""); -+ name = name.replace("$", "_"); -+ flag = true; -+ } else { -+ // mapped, wooo -+ name = cut; -+ } -+ } -+ name = name.replace("PathfinderGoal", ""); -+ StringBuilder sb = new StringBuilder(); -+ for (char c : name.toCharArray()) { -+ if (c >= 'A' && c <= 'Z') { -+ sb.append("_"); -+ sb.append(Character.toLowerCase(c)); -+ } else { -+ sb.append(c); -+ } -+ } -+ name = sb.toString(); -+ name = name.replaceFirst("_", ""); -+ -+ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { -+ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); -+ } -+ -+ // did we rename this key? -+ return deobfuscationMap.getOrDefault(name, name); -+ } -+ -+ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { -+ EnumSet goals = EnumSet.noneOf(GoalType.class); -+ for (GoalType type : GoalType.values()) { -+ if (types.hasElement(paperToVanilla(type))) { -+ goals.add(type); -+ } -+ } -+ return goals; -+ } -+ -+ public static GoalType vanillaToPaper(PathfinderGoal.Type type) { -+ switch (type) { -+ case MOVE: -+ return GoalType.MOVE; -+ case LOOK: -+ return GoalType.LOOK; -+ case JUMP: -+ return GoalType.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return GoalType.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return GoalType.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); -+ } -+ } -+ -+ public static EnumSet paperToVanilla(EnumSet types) { -+ EnumSet goals = EnumSet.noneOf(PathfinderGoal.Type.class); -+ for (GoalType type : types) { -+ goals.add(paperToVanilla(type)); -+ } -+ return goals; -+ } -+ -+ public static PathfinderGoal.Type paperToVanilla(GoalType type) { -+ switch (type) { -+ case MOVE: -+ return PathfinderGoal.Type.MOVE; -+ case LOOK: -+ return PathfinderGoal.Type.LOOK; -+ case JUMP: -+ return PathfinderGoal.Type.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return PathfinderGoal.Type.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return PathfinderGoal.Type.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); -+ } -+ } -+ -+ public static GoalKey getKey(Class goalClass) { -+ String name = getUsableName(goalClass); -+ if (ignored.contains(name)) { -+ //noinspection unchecked -+ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); -+ } -+ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); -+ } -+ -+ public static Class getEntity(Class goalClass) { -+ //noinspection unchecked -+ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { -+ for (Constructor ctor : key.getDeclaredConstructors()) { -+ for (int i = 0; i < ctor.getParameterCount(); i++) { -+ Class param = ctor.getParameterTypes()[i]; -+ if (EntityInsentient.class.isAssignableFrom(param)) { -+ //noinspection unchecked -+ return toBukkitClass((Class) param); -+ } else if (IRangedEntity.class.isAssignableFrom(param)) { -+ return RangedEntity.class; -+ } -+ } -+ } -+ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? -+ }); -+ } -+ -+ public static Class toBukkitClass(Class nmsClass) { -+ Class bukkitClass = bukkitMap.get(nmsClass); -+ if (bukkitClass == null) { -+ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? -+ } -+ return bukkitClass; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0b963f80857209bc73ece917203447d8839860b6 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -@@ -0,0 +1,54 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps api in vanilla -+ */ -+public class PaperCustomGoal extends PathfinderGoal { -+ -+ private final Goal handle; -+ -+ public PaperCustomGoal(Goal handle) { -+ this.handle = handle; -+ -+ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); -+ if (this.getGoalTypes().size() == 0) { -+ this.getGoalTypes().addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void onTaskReset() { -+ handle.stop(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ public Goal getHandle() { -+ return handle; -+ } -+ -+ public GoalKey getKey() { -+ return handle.getKey(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..bf792c013fe3b9a0b5800a35308b9aaa36e5350d ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -@@ -0,0 +1,222 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalWrapped; -+import org.bukkit.craftbukkit.entity.CraftMob; -+import org.bukkit.entity.Mob; -+ -+public class PaperMobGoals implements MobGoals { -+ -+ private final Map> instanceCache = new HashMap<>(); -+ -+ @Override -+ public void addGoal(T mob, int priority, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); -+ } -+ -+ @Override -+ public void removeGoal(T mob, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((PathfinderGoal) goal); -+ } else if (goal instanceof PaperVanillaGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); -+ } else { -+ List toRemove = new LinkedList<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, goal.getTypes()).getTasks()) { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { -+ toRemove.add(item.getGoal()); -+ } -+ } -+ } -+ -+ for (PathfinderGoal g : toRemove) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(g); -+ } -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob) { -+ for (GoalType type : GoalType.values()) { -+ removeAllGoals(mob, type); -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob, GoalType type) { -+ for (Goal goal : getAllGoals(mob, type)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public void removeGoal(T mob, GoalKey key) { -+ for (Goal goal : getGoals(mob, key)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public boolean hasGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ @Override -+ public Goal getGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return g; -+ } -+ } -+ return null; -+ } -+ -+ @Override -+ public Collection> getGoals(T mob, GoalKey key) { -+ Set> goals = new HashSet<>(); -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ goals.add(g); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getAllGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, type).getTasks()) { -+ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ for (PathfinderGoalWrapped item : getHandle(craftMob, internalType).getTasks()) { -+ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getRunningGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() -+ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ getHandle(craftMob, internalType).getExecutingGoals() -+ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ } -+ return goals; -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, EnumSet types) { -+ if (types.contains(GoalType.TARGET)) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, GoalType type) { -+ if (type == GoalType.TARGET) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1ed6e7273bc84a406ca843bc47bb69314bb2dd74 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -@@ -0,0 +1,62 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.EnumSet; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps vanilla in api -+ */ -+public class PaperVanillaGoal implements VanillaGoal { -+ -+ private final PathfinderGoal handle; -+ private final GoalKey key; -+ -+ private final EnumSet types; -+ -+ public PaperVanillaGoal(PathfinderGoal handle) { -+ this.handle = handle; -+ this.key = MobGoalHelper.getKey(handle.getClass()); -+ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); -+ } -+ -+ public PathfinderGoal getHandle() { -+ return handle; -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate2(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive2(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void stop() { -+ handle.onTaskReset(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ @Override -+ public GoalKey getKey() { -+ return key; -+ } -+ -+ @Override -+ public EnumSet getTypes() { -+ return types; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -index 9df0006c1a283f77c4d01d9fce9062fc1c9bbb1f..b3329c6fcd6758a781a51f5ba8f5052ac1c77b49 100644 ---- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -64,4 +64,8 @@ public final class OptimizedSmallEnumSet> { - public boolean hasCommonElements(final OptimizedSmallEnumSet other) { - return (other.backingSet & this.backingSet) != 0; - } -+ -+ public boolean hasElement(final E element) { -+ return (this.backingSet & (1L << element.ordinal())) != 0; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf..59ea1432152051ce8a60c0a526db787593f0e744 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -8,11 +8,17 @@ public abstract class PathfinderGoal { - private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - -- public PathfinderGoal() {} -+ // Paper start make sure goaltypes is never empty -+ public PathfinderGoal() { -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ // paper end - -- public abstract boolean a(); -+ public boolean a() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return a(); } // Paper - OBFHELPER, for both directions... - -- public boolean b() { -+ public boolean b() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return b(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... - return this.a(); - } - -@@ -20,19 +26,23 @@ public abstract class PathfinderGoal { - return true; - } - -- public void c() {} -+ public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - - public void d() { - onTaskReset(); // Paper - } - public void onTaskReset() {} // Paper - -- public void e() {} -+ public void e() { this.tick(); } public void tick() {} // Paper OBFHELPER - -- public void a(EnumSet enumset) { -+ public void a(EnumSet enumset) { this.setTypes(enumset); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - this.goalTypes.clear(); - this.goalTypes.addAllUnchecked(enumset); -+ // make sure its never empty -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } - // Paper end - remove streams from pathfindergoalselector - } - -@@ -48,7 +58,7 @@ public abstract class PathfinderGoal { - - public static enum Type { - -- MOVE, LOOK, JUMP, TARGET; -+ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown - - private Type() {} - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 385cd079e264a7e66e91ab3b70b90afb59688dcd..637928664f8c7b1c694a234e507c20724294e450 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -28,7 +28,7 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER -+ private final Set d = Sets.newLinkedHashSet(); public final Set getTasks() { return d; }// Paper - OBFHELPER // Paper - private -> public - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector -@@ -39,7 +39,7 @@ public class PathfinderGoalSelector { - this.e = supplier; - } - -- public void a(int i, PathfinderGoal pathfindergoal) { -+ public void addGoal(int priority, PathfinderGoal goal) {a(priority, goal);} public void a(int i, PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -@@ -58,7 +58,7 @@ public class PathfinderGoalSelector { - } - // Paper end - -- public void a(PathfinderGoal pathfindergoal) { -+ public void removeGoal(PathfinderGoal goal) {a(goal);} public void a(PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped goalWrapped = iterator.next(); -@@ -154,6 +154,7 @@ public class PathfinderGoalSelector { - gameprofilerfiller.exit(); - } - -+ public final Stream getExecutingGoals() { return d(); } // Paper - OBFHELPER - public Stream d() { - return this.d.stream().filter(PathfinderGoalWrapped::g); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 8c8e39d35fb56aa6cf7d456adab01dff5d13a60d..bcf6c924894f49f1c602b83b501f904e553235fd 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -5,8 +5,8 @@ import javax.annotation.Nullable; - - public class PathfinderGoalWrapped extends PathfinderGoal { - -- private final PathfinderGoal a; -- private final int b; -+ private final PathfinderGoal a; public PathfinderGoal getGoal() {return a;} // Paper - OBFHELPER -+ private final int b; public int getPriority() {return b;} // Paper - OBFHELPER - private boolean c; - - public PathfinderGoalWrapped(int i, PathfinderGoal pathfindergoal) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 688bf56b331cc4b6b9664365f97a98720ec522a9..3b7a7791a221aaf39b4b6974b2f37efd403e4b25 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2392,5 +2392,11 @@ public final class CraftServer implements Server { - public boolean isStopping() { - return net.minecraft.server.MinecraftServer.getServer().hasStopped(); - } -+ -+ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); -+ @Override -+ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return mobGoals; -+ } - // Paper end - } -diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c0525216a8469613c3e0d4b5774a82f69e70fb16 ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +1,104 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.junit.Assert; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.lang.reflect.Modifier; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+import org.bukkit.entity.Mob; -+ -+import io.github.classgraph.ClassGraph; -+import io.github.classgraph.ScanResult; -+ -+public class VanillaMobGoalTest { -+ -+ @Test -+ public void testKeys() { -+ List> deprecated = new ArrayList<>(); -+ List> keys = new ArrayList<>(); -+ for (Field field : VanillaGoal.class.getFields()) { -+ if (field.getType().equals(GoalKey.class)) { -+ try { -+ GoalKey goalKey = (GoalKey) field.get(null); -+ if (field.getAnnotation(Deprecated.class) != null) { -+ deprecated.add(goalKey); -+ } else { -+ keys.add(goalKey); -+ } -+ } catch (IllegalAccessException e) { -+ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); -+ } -+ } -+ } -+ -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); -+ } -+ -+ List> vanillaNames = classes.stream() -+ .filter(VanillaMobGoalTest::hasNoEnclosingClass) -+ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) -+ .collect(Collectors.toList()); -+ -+ List> missingFromAPI = new ArrayList<>(vanillaNames); -+ missingFromAPI.removeAll(keys); -+ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); -+ List> missingFromVanilla = new ArrayList<>(keys); -+ missingFromVanilla.removeAll(vanillaNames); -+ -+ boolean shouldFail = false; -+ if (missingFromAPI.size() != 0) { -+ System.out.println("Missing from API: "); -+ for (GoalKey key : missingFromAPI) { -+ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + -+ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); -+ } -+ shouldFail = true; -+ } -+ if (missingFromVanilla.size() != 0) { -+ System.out.println("Missing from vanilla: "); -+ missingFromVanilla.forEach(System.out::println); -+ shouldFail = true; -+ } -+ -+ if (deprecated.size() != 0) { -+ System.out.println("Deprecated (might want to remove them at some point): "); -+ deprecated.forEach(System.out::println); -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+ -+ private static boolean hasNoEnclosingClass(Class clazz) { -+ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); -+ } -+ -+ @Test -+ public void testBukkitMap() { -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { -+ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); -+ } -+ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); -+ -+ boolean shouldFail = false; -+ for (Class nmsClass : classes) { -+ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); -+ if (bukkitClass == null) { -+ shouldFail = true; -+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); -+ } -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+} diff --git a/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch b/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch deleted file mode 100644 index 2866b183113e..000000000000 --- a/Spigot-Server-Patches/0465-Use-distance-map-to-optimise-entity-tracker.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:18:05 -0700 -Subject: [PATCH] Use distance map to optimise entity tracker - -Use the distance map to find candidate players for tracking. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6f51409bac9c2907a5be02e4c15319fcc520609f..e25539dd54956225e8b14d3b8c636130267f226d 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1653,6 +1653,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = this.tracker.getPassengers(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index d509cfd2da99233e5142abd176cc50ccea7c32b6..9fc74f08b912ff885c9478167c7ef173c32f1654 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -195,21 +196,55 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ // Paper start - use distance map to optimise tracker -+ public static boolean isLegacyTrackingEntity(Entity entity) { -+ return entity.isLegacyTrackingEntity; -+ } -+ -+ // inlined EnumMap, TrackingRange.TrackingRangeType -+ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; -+ final int[] entityTrackerTrackRanges; -+ -+ private int convertSpigotRangeToVanilla(final int vanilla) { -+ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); -+ } -+ // Paper end - use distance map to optimise tracker - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -- -+ // Paper start - use distance map to optimise tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ this.playerEntityTrackerTrackMaps[i].remove(player); -+ } -+ // Paper end - use distance map to optimise tracker - } - - void updateMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - // Paper end - -@@ -246,6 +281,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ // Paper start - use distance map to optimise entity tracker -+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; -+ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; -+ -+ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.world.spigotConfig; -+ -+ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { -+ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; -+ int configuredSpigotValue; -+ switch (trackingRangeType) { -+ case PLAYER: -+ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; -+ break; -+ case ANIMAL: -+ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; -+ break; -+ case MONSTER: -+ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; -+ break; -+ case MISC: -+ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; -+ break; -+ case OTHER: -+ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; -+ break; -+ case ENDERDRAGON: -+ configuredSpigotValue = EntityTypes.ENDER_DRAGON.getChunkRange() * 16; -+ break; -+ default: -+ throw new IllegalStateException("Missing case for enum " + trackingRangeType); -+ } -+ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); -+ -+ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); -+ this.entityTrackerTrackRanges[ordinal] = trackRange; -+ -+ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1492,17 +1566,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public void movePlayer(EntityPlayer entityplayer) { -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -- -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- -- if (playerchunkmap_entitytracker.tracker == entityplayer) { -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -- } else { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- } -- } -+ // Paper - delay this logic for the entity tracker tick, no need to duplicate it - - int i = MathHelper.floor(entityplayer.locX()) >> 4; - int j = MathHelper.floor(entityplayer.locZ()) >> 4; -@@ -1618,7 +1682,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -+ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players - if (entity instanceof EntityPlayer) { - EntityPlayer entityplayer = (EntityPlayer) entity; - -@@ -1661,7 +1725,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entity.tracker = null; // Paper - We're no longer tracked - } - -+ // Paper start - optimised tracker -+ private final void processTrackQueue() { -+ this.world.timings.tracker1.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ // update tracker entry -+ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); -+ } -+ } finally { -+ this.world.timings.tracker1.stopTiming(); -+ } -+ -+ -+ this.world.timings.tracker2.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ tracker.trackerEntry.tick(); -+ } -+ } finally { -+ this.world.timings.tracker2.stopTiming(); -+ } -+ } -+ // Paper end - optimised tracker -+ - protected void g() { -+ // Paper start - optimized tracker -+ if (true) { -+ this.processTrackQueue(); -+ return; -+ } -+ // Paper end - optimized tracker - List list = Lists.newArrayList(); - List list1 = this.world.getPlayers(); - -@@ -1730,23 +1824,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PacketDebug.a(this.world, chunk.getPos()); - List list = Lists.newArrayList(); - List list1 = Lists.newArrayList(); -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -+ // Paper start - optimise entity tracker -+ // use the chunk entity list, not the whole trackedEntities map... -+ Entity[] entities = chunk.entities.getRawData(); -+ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { -+ Entity entity = entities[i]; -+ if (entity == entityplayer) { -+ continue; -+ } -+ PlayerChunkMap.EntityTracker tracker = this.trackedEntities.get(entity.getId()); -+ if (tracker != null) { // dumb plugins... move on... -+ tracker.updatePlayer(entityplayer); -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- Entity entity = playerchunkmap_entitytracker.tracker; -+ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! -+ // (and god knows what the leash thing is) - -- if (entity != entityplayer && entity.chunkX == chunk.getPos().x && entity.chunkZ == chunk.getPos().z) { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) { -- list.add(entity); -- } -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).getLeashHolder() != null) { -+ list.add(entity); -+ } - -- if (!entity.getPassengers().isEmpty()) { -- list1.add(entity); -- } -+ if (!entity.getPassengers().isEmpty()) { -+ list1.add(entity); - } - } -+ // Paper end - optimise entity tracker - - Iterator iterator; - Entity entity1; -@@ -1784,7 +1886,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public class EntityTracker { - -- private final EntityTrackerEntry trackerEntry; -+ final EntityTrackerEntry trackerEntry; // Paper - private -> package private - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -@@ -1801,6 +1903,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.e = SectionPosition.a(entity); - } - -+ // Paper start - use distance map to optimise tracker -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; -+ -+ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; -+ this.lastTrackerCandidates = newTrackerCandidates; -+ -+ if (newTrackerCandidates != null) { -+ Object[] rawData = newTrackerCandidates.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ Object raw = rawData[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)raw; -+ this.updatePlayer(player); -+ } -+ } -+ -+ if (oldTrackerCandidates == newTrackerCandidates) { -+ // this is likely the case. -+ // means there has been no range changes, so we can just use the above for tracking. -+ return; -+ } -+ -+ // stuff could have been removed, so we need to check the trackedPlayers set -+ // for players that were removed -+ -+ for (EntityPlayer player : this.trackedPlayers.toArray(new EntityPlayer[0])) { // avoid CME -+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { -+ this.updatePlayer(player); -+ } -+ } -+ } -+ // Paper end - use distance map to optimise tracker -+ - public boolean equals(Object object) { - return object instanceof PlayerChunkMap.EntityTracker ? ((PlayerChunkMap.EntityTracker) object).tracker.getId() == this.tracker.getId() : false; - } -@@ -1901,7 +2039,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int j = entity.getEntityType().getChunkRange() * 16; - j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - -- if (j > i) { -+ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic - i = j; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index cb5c93dca3b947462b89f79c60c7562085684b87..da2b5bfd3966ded2d5dde0d65646583576a088c5 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; -@@ -295,6 +296,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - optimise entity tracking -+ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); -+ -+ public boolean isLegacyTrackingEntity = false; -+ -+ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { -+ this.isLegacyTrackingEntity = isLegacyTrackingEntity; -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -+ return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -+ .getObjectsInRange(MCUtil.getCoordinateKey(this)); -+ } -+ // Paper end - optimise entity tracking -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 3277a8aaffb6a25624967aa0c62f61309a517739..cd569ad95176fdd0537459b40dfba5c5127a62df 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -21,6 +21,7 @@ public class TrackingRange - */ - public static int getEntityTrackingRange(Entity entity, int defaultRange) - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return defaultRange; // Paper - enderdragon is exempt - SpigotWorldConfig config = entity.world.spigotConfig; - if ( entity instanceof EntityPlayer ) - { -@@ -44,8 +45,48 @@ public class TrackingRange - return config.miscTrackingRange; - } else - { -- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } -+ -+ // Paper start - optimise entity tracking -+ // copied from above, TODO check on update -+ public static TrackingRangeType getTrackingRangeType(Entity entity) -+ { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt -+ if ( entity instanceof EntityPlayer ) -+ { -+ return TrackingRangeType.PLAYER; -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: -+ return TrackingRangeType.MONSTER; -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return TrackingRangeType.ANIMAL; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end -+ { -+ return TrackingRangeType.MISC; -+ } else -+ { -+ return TrackingRangeType.OTHER; -+ } -+ } -+ -+ public static enum TrackingRangeType { -+ PLAYER, -+ ANIMAL, -+ MONSTER, -+ MISC, -+ OTHER, -+ ENDERDRAGON; -+ } -+ // Paper end - optimise entity tracking - } diff --git a/Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch b/Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch deleted file mode 100644 index f3f287703653..000000000000 --- a/Spigot-Server-Patches/0466-Optimize-isOutsideRange-to-use-distance-maps.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:40:53 -0700 -Subject: [PATCH] Optimize isOutsideRange to use distance maps - -Use a distance map to find the players in range quickly - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 60fcea78bf617559114b1ca1c0bf2d4cd9075a8c..335666db1854e8aa4b2ba71d5bdc2658305cb70a 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -37,7 +37,7 @@ public abstract class ChunkMapDistance { - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); - public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); -- private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); -+ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); - // Paper start use a queue, but still keep unique requirement - public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -@@ -56,6 +56,8 @@ public abstract class ChunkMapDistance { - private final Executor m; - private long currentTick; - -+ PlayerChunkMap chunkMap; // Paper -+ - protected ChunkMapDistance(Executor executor, Executor executor1) { - executor1.getClass(); - Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); -@@ -100,7 +102,7 @@ public abstract class ChunkMapDistance { - protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); - - public boolean a(PlayerChunkMap playerchunkmap) { -- this.f.a(); -+ //this.f.a(); // Paper - no longer used - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -236,7 +238,7 @@ public abstract class ChunkMapDistance { - ((ObjectSet) this.c.computeIfAbsent(i, (j) -> { - return new ObjectOpenHashSet(); - })).add(entityplayer); -- this.f.update(i, 0, true); -+ //this.f.update(i, 0, true); // Paper - no longer used - this.g.update(i, 0, true); - } - -@@ -248,7 +250,7 @@ public abstract class ChunkMapDistance { - if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. - if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); -- this.f.update(i, Integer.MAX_VALUE, false); -+ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used - this.g.update(i, Integer.MAX_VALUE, false); - } - -@@ -272,13 +274,17 @@ public abstract class ChunkMapDistance { - } - - public int b() { -- this.f.a(); -- return this.f.a.size(); -+ // Paper start - use distance map to implement -+ // note: this is the spawn chunk count -+ return this.chunkMap.playerChunkTickRangeMap.size(); -+ // Paper end - use distance map to implement - } - - public boolean d(long i) { -- this.f.a(); -- return this.f.a.containsKey(i); -+ // Paper start - use distance map to implement -+ // note: this is the is spawn chunk method -+ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; -+ // Paper end - use distance map to implement - } - - public String c() { -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index ecf4cd6dfea777ab9daea0b40724d247df7ddb53..42bb00364375e5cf324b43557385345868b37ffe 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -753,6 +753,37 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit - - if (!flag) { -+ // Paper start - optimize isOutisdeRange -+ PlayerChunkMap playerChunkMap = this.playerChunkMap; -+ for (EntityPlayer player : this.world.players) { -+ if (!player.affectsSpawning || player.isSpectator()) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int viewDistance = this.playerChunkMap.getEffectiveViewDistance(); -+ -+ // copied and modified from isOutisdeRange -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; -+ chunkRange = (chunkRange > ChunkMapDistance.MOB_SPAWN_RANGE) ? ChunkMapDistance.MOB_SPAWN_RANGE : chunkRange; -+ -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); -+ event.callEvent(); -+ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); -+ -+ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); -+ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange -+ player.playerNaturallySpawnedEvent = event; -+ } -+ // Paper end - optimize isOutisdeRange - this.world.getMethodProfiler().enter("pollingChunks"); - int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit -@@ -782,15 +813,7 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -- //Paper start - call player naturally spawn event -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = Math.min(chunkRange, 8); -- for (EntityPlayer entityPlayer : this.world.getPlayers()) { -- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -- entityPlayer.playerNaturallySpawnedEvent.callEvent(); -- }; -- // Paper end -+ // Paper - moved up - final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - -@@ -806,9 +829,9 @@ public class ChunkProviderServer extends IChunkProvider { - Chunk chunk = (Chunk) optional1.get(); - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - -- if (!this.playerChunkMap.isOutsideOfRange(chunkcoordintpair)) { -+ if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange - chunk.setInhabitedTime(chunk.getInhabitedTime() + j); -- if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot -+ if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 39fb3a1445338c3ac1642b8e518eb8d1031f9a5c..62ed75ae7ec492d8502776fdf3cf3ee461a38a53 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -250,6 +250,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 445dba8ed210407664904b707c36c78a76f25510..25484cac9c62e49de39fbbf506fcb3edc4ba6e65 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -70,6 +70,18 @@ public class PlayerChunk { - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave - -+ // Paper start - optimise isOutsideOfRange -+ // cached here to avoid a map lookup -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; -+ -+ void updateRanges() { -+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location); -+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); -+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); -+ } -+ // Paper end - optimise isOutsideOfRange -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -86,6 +98,7 @@ public class PlayerChunk { - this.n = this.oldTicketLevel; - this.a(i); - this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ this.updateRanges(); // Paper - optimise isOutsideOfRange - } - - // Paper start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 9fc74f08b912ff885c9478167c7ef173c32f1654..a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -210,6 +210,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ // A note about the naming used here: -+ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and -+ // mob spawn range. However, spigot makes the spawn range configurable by -+ // checking if the chunk is in the tick range (8) and the spawn range -+ // obviously this means a spawn range > 8 cannot be implemented -+ -+ // these maps are named after spigot's uses -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -223,6 +234,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -231,6 +245,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[i].remove(player); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerMobSpawnMap.remove(player); -+ this.playerChunkTickRangeMap.remove(player); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void updateMaps(EntityPlayer player) { -@@ -245,6 +263,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - // Paper end - -@@ -276,7 +297,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); -- this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); -+ this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -@@ -320,6 +341,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }); -+ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -339,6 +392,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - -+ private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { - double d0 = (double) (chunkcoordintpair.x * 16 + 8); - double d1 = (double) (chunkcoordintpair.z * 16 + 8); -@@ -517,6 +571,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - if (playerchunk != null) { - playerchunk.a(j); -+ playerchunk.updateRanges(); // Paper - optimise isOutsideOfRange - } - - if (playerchunk != null) { -@@ -1495,30 +1550,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return isOutsideOfRange(chunkcoordintpair, false); - } - -- boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = (chunkRange > 8) ? 8 : chunkRange; -+ // Paper start - optimise isOutsideOfRange -+ final boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ return this.isOutsideOfRange(this.getUpdatingChunk(chunkcoordintpair.pair()), chunkcoordintpair, reducedRange); -+ } - -- final int finalChunkRange = chunkRange; // Paper for lambda below -- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event -- // Spigot end -- long i = chunkcoordintpair.pair(); -+ final boolean isOutsideOfRange(PlayerChunk playerchunk, ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance -+ // tested and confirmed via System.nanoTime() -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; - -- return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- // Paper start - -- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -- double blockRange = 16384.0D; -- if (reducedRange) { -- event = entityplayer.playerNaturallySpawnedEvent; -- if (event == null || event.isCancelled()) return false; -- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -- } -+ if (playersInRange == null) { -+ return true; -+ } - -- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -- // Paper end -- }); -+ Object[] backingSet = playersInRange.getBackingSet(); -+ -+ if (reducedRange) { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } else { -+ final double range = (ChunkMapDistance.MOB_SPAWN_RANGE * 16) * (ChunkMapDistance.MOB_SPAWN_RANGE * 16); -+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } -+ // no players in range -+ return true; - } -+ // Paper end - optimise isOutsideOfRange - - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); diff --git a/Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch b/Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch deleted file mode 100644 index ef0648a1f586..000000000000 --- a/Spigot-Server-Patches/0467-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 04:05:38 -0700 -Subject: [PATCH] Stop copy-on-write operations for updating light data - -Causes huge memory allocations + gc issues - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 5f3d2c090d098834e38e447d93f1ea8184c8fb3e..5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -26,8 +26,8 @@ public abstract class LightEngineStorage> e - protected final LongSet b = new LongOpenHashSet(); - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); -- protected volatile M e; -- protected final M f; -+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M f; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); - protected final LongSet h = new LongOpenHashSet(); - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -41,8 +41,8 @@ public abstract class LightEngineStorage> e - this.l = enumskyblock; - this.m = ilightaccess; - this.f = m0; -- this.e = m0.b(); -- this.e.d(); -+ this.e_visible = m0.b(); // Paper - avoid copying light data -+ this.e_visible.d(); // Paper - avoid copying light data - } - - protected boolean g(long i) { -@@ -51,7 +51,15 @@ public abstract class LightEngineStorage> e - - @Nullable - protected NibbleArray a(long i, boolean flag) { -- return this.a(flag ? this.f : this.e, i); -+ // Paper start - avoid copying light data -+ if (flag) { -+ return this.a(this.f, i); -+ } else { -+ synchronized (this.visibleUpdateLock) { -+ return this.a(this.e_visible, i); -+ } -+ } -+ // Paper end - avoid copying light data - } - - @Nullable -@@ -364,10 +372,12 @@ public abstract class LightEngineStorage> e - - protected void e() { - if (!this.g.isEmpty()) { -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.f.b(); - - m0.d(); -- this.e = m0; -+ this.e_visible = m0; // Paper - avoid copying light data -+ } // Paper - avoid copying light data - this.g.clear(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index 242a2c5dea1241b515b9eee7c334ab3c31ad9d12..ed7864c552054fc47c6010a094230ce4aebf1c54 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -9,10 +9,23 @@ public abstract class LightEngineStorageArray a; -- -- protected LightEngineStorageArray(Long2ObjectOpenHashMap long2objectopenhashmap) { -- this.a = long2objectopenhashmap; -+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data -+ protected final boolean isVisible; // Paper - avoid copying light data -+ java.util.function.Function lookup; // Paper - faster branchless lookup -+ -+ // Paper start - avoid copying light data -+ protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { -+ if (isVisible) { -+ data.performUpdatesLockMap(); -+ } -+ this.data = data; -+ this.isVisible = isVisible; -+ if (isVisible) { -+ lookup = data::getVisibleAsync; -+ } else { -+ lookup = data::getUpdating; -+ } -+ // Paper end - avoid copying light data - this.c(); - this.d = true; - } -@@ -20,16 +33,17 @@ public abstract class LightEngineStorageArray { - - protected LightEngineStorageBlock(ILightAccess ilightaccess) { -- super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap())); -+ super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data - } - - @Override -@@ -23,13 +23,13 @@ public class LightEngineStorageBlock extends LightEngineStorage { - -- public a(Long2ObjectOpenHashMap long2objectopenhashmap) { -- super(long2objectopenhashmap); -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data -+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data - } - - @Override - public LightEngineStorageBlock.a b() { -- return new LightEngineStorageBlock.a(this.a.clone()); -+ return new a(this.data, true); // Paper - avoid copying light data - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index befc8f846c772d58ee687ad427bb71206b4dc43e..64d37f4c6a8167f47c80953a388ea6635490563a 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -23,15 +23,16 @@ public class LightEngineStorageSky extends LightEngineStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data - } - - @Override - protected int d(long i) { - long j = SectionPosition.e(i); - int k = SectionPosition.c(j); -- LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e; -- int l = lightenginestoragesky_a.c.get(SectionPosition.f(j)); -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data -+ LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -+ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data - - if (l != lightenginestoragesky_a.b && k < l) { - NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix -@@ -52,6 +53,7 @@ public class LightEngineStorageSky extends LightEngineStorage j) { - ((LightEngineStorageSky.a) this.f).b = j; -- ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b); -+ ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data - } - - long k = SectionPosition.f(i); -- int l = ((LightEngineStorageSky.a) this.f).c.get(k); -+ int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((LightEngineStorageSky.a) this.f).c.put(k, j + 1); -+ ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.o.contains(k)) { - this.q(i); - if (l > ((LightEngineStorageSky.a) this.f).b) { -@@ -107,7 +109,7 @@ public class LightEngineStorageSky extends LightEngineStorage= k; - } -@@ -327,18 +329,21 @@ public class LightEngineStorageSky extends LightEngineStorage { - - private int b; -- private final Long2IntOpenHashMap c; -- -- public a(Long2ObjectOpenHashMap long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) { -- super(long2objectopenhashmap); -- this.c = long2intopenhashmap; -- long2intopenhashmap.defaultReturnValue(i); -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ -+ // Paper start - avoid copying light data -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data - this.b = i; - } - - @Override - public LightEngineStorageSky.a b() { -- return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b); -+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data -+ return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data - } - } - } diff --git a/Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch b/Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch deleted file mode 100644 index 1e68582fcf90..000000000000 --- a/Spigot-Server-Patches/0468-No-Tick-view-distance-implementation.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:23:34 -0700 -Subject: [PATCH] No-Tick view distance implementation - -Implements world view distance getters/setters - -Per-Player is absent due to difficulty of maintaining -the diff required to make it happen. - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index c9164dfdb27ddf3709129c8aec54903a1df121ff..e33e889c291d37a821a4fbd40d9aac7bb079de0d 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -153,7 +153,8 @@ public class TimingsExport extends Thread { - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) - )); - })); - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 46ac6d91422423f1e03b86d3efa3241f2599000d..6463d3e4837d032a35654a035f42b8a805e0e286 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -632,4 +632,9 @@ public class PaperWorldConfig { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); - } -+ -+ public int noTickViewDistance; -+ private void viewDistance() { -+ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 9edbde8299bcd127e1727d34ed441f638e716b2a..17de074111a174f3a39a4477afc3ad62e04a73b5 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -638,7 +638,8 @@ public final class MCUtil { - }); - - worldData.addProperty("name", world.getWorld().getName()); -- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); -+ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); - worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); - worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); - worldData.addProperty("visible-chunk-count", visibleChunks.size()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 335666db1854e8aa4b2ba71d5bdc2658305cb70a..2bbdcedf4856080ea9232effdf3bdae9c26c425b 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -269,7 +269,7 @@ public abstract class ChunkMapDistance { - return s; - } - -- protected void a(int i) { -+ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change - this.g.a(i); - } - -@@ -388,7 +388,7 @@ public abstract class ChunkMapDistance { - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, ChunkMapDistance.b, new ChunkCoordIntPair(i)); -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance - - if (flag1) { - ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 62ed75ae7ec492d8502776fdf3cf3ee461a38a53..89a66078b722f265abd73579545a1f24df9442aa 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -252,6 +252,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - -+ boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 25484cac9c62e49de39fbbf506fcb3edc4ba6e65..1f6333c2c26ad04e23d2881235ed1dcf707be038 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -82,6 +82,18 @@ public class PlayerChunk { - } - // Paper end - optimise isOutsideOfRange - -+ // Paper start - no-tick view distance -+ public final Chunk getSendingChunk() { -+ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used -+ // in Chunk's neighbour callback -+ Chunk ret = this.chunkMap.world.getChunkProvider().getChunkAtIfLoadedImmediately(this.location.x, this.location.z); -+ if (ret != null && ret.areNeighboursLoaded(1)) { -+ return ret; -+ } -+ return null; -+ } -+ // Paper end - no-tick view distance -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -241,7 +253,7 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - byte b0 = (byte) SectionPosition.a(blockposition.getY()); -@@ -257,7 +269,7 @@ public class PlayerChunk { - } - - public void a(EnumSkyBlock enumskyblock, int i) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - chunk.setNeedsSaving(true); -@@ -339,9 +351,48 @@ public class PlayerChunk { - } - - private void a(Packet packet, boolean flag) { -- this.players.a(this.location, flag).forEach((entityplayer) -> { -- entityplayer.playerConnection.sendPacket(packet); -- }); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); -+ if (players == null) { -+ return; -+ } -+ -+ if (flag) { // flag -> border only -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ -+ int viewDistance = viewDistanceMap.getLastViewDistance(player); -+ long lastPosition = viewDistanceMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.location.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.location.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ } else { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ -+ return; -+ // Paper end - per player view distance - } - - public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index a6bb8e3b9e73f81bfa92ac13df27e9c44dd9e311..e4b5649fbc8cb9662e818581fe2891641de419b6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -60,9 +60,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; -+import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -146,7 +148,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private boolean updatingChunksModified; - private final ChunkTaskQueueSorter p; - private final Mailbox> mailboxWorldGen; -- private final Mailbox> mailboxMain; -+ public final Mailbox> mailboxMain; // Paper - private -> public -+ // Paper start -+ final Mailbox> mailboxLight; -+ public void addLightTask(PlayerChunk playerchunk, Runnable run) { -+ this.mailboxLight.a(ChunkTaskQueueSorter.a(playerchunk, run)); -+ } -+ // Paper end - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; -@@ -221,6 +229,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int noTickViewDistance; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; -+ } -+ public final int getLoadViewDistance() { -+ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; -+ // Paper end - no-tick view distance - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -237,6 +261,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -249,6 +286,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.playerViewDistanceBroadcastMap.remove(player); -+ this.playerViewDistanceTickMap.remove(player); -+ this.playerViewDistanceNoTickMap.remove(player); -+ // Paper end - no-tick view distance - } - - void updateMaps(EntityPlayer player) { -@@ -266,6 +308,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - // Paper end - -@@ -373,6 +428,45 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.setNoTickViewDistance(this.world.paperConfig.noTickViewDistance); -+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState.size() != 1) { -+ return; -+ } -+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); -+ if (chunk == null || !chunk.areNeighboursLoaded(2)) { -+ return; -+ } -+ -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState != null) { -+ return; -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }); -+ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (player.needsChunkCenterUpdate) { -+ player.needsChunkCenterUpdate = false; -+ player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ)); -+ } -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded -+ }); -+ // Paper end - no-tick view distance - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1201,15 +1295,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { - this.u.getAndIncrement(); -- Packet[] apacket = new Packet[2]; -- -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- this.a(entityplayer, apacket, chunk); -- }); -+ // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) - }); - return completablefuture1; - } -@@ -1304,32 +1394,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -- protected void setViewDistance(int i) { -- int j = MathHelper.clamp(i + 1, 3, 33); -+ public void setViewDistance(int i) { // Paper - public -+ int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 - - if (j != this.viewDistance) { - int k = this.viewDistance; - - this.viewDistance = j; -- this.chunkDistanceManager.a(this.viewDistance); -- ObjectIterator objectiterator = this.updatingChunks.values().iterator(); -+ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunk playerchunk = (PlayerChunk) objectiterator.next(); -- ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); -- Packet[] apacket = new Packet[2]; -+ } - -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = b(chunkcoordintpair, entityplayer, true); -- boolean flag = l <= k; -- boolean flag1 = l <= this.viewDistance; -+ // Paper start - no-tick view distance -+ public final void setNoTickViewDistance(int viewDistance) { -+ viewDistance = viewDistance == -1 ? -1 : MathHelper.clamp(viewDistance, 2, 32); - -- this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1); -- }); -+ this.noTickViewDistance = viewDistance; -+ int loadViewDistance = this.getLoadViewDistance(); -+ this.chunkDistanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 -+ -+ if (this.world != null && this.world.players != null) { // this can be called from constructor, where these aren't set -+ for (EntityPlayer player : this.world.players) { -+ PlayerConnection connection = player.playerConnection; -+ if (connection != null) { -+ // moved in from PlayerList -+ connection.sendPacket(new PacketPlayOutViewDistance(loadViewDistance)); -+ } -+ this.updateMaps(player); - } - } -- - } -+ // Paper end - no-tick view distance - - protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet[] apacket, boolean flag, boolean flag1) { - if (entityplayer.world == this.world) { -@@ -1337,7 +1433,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); - - if (playerchunk != null) { -- Chunk chunk = playerchunk.getChunk(); -+ Chunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - this.a(entityplayer, apacket, chunk); -@@ -1598,6 +1694,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(EntityPlayer entityplayer) { return this.b(entityplayer); } // Paper - OBFHELPER - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); - } -@@ -1625,13 +1722,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - -- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k, l); -- -- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], !flag, flag); -- } -- } -+ // Paper - broadcast view distance map handles this (see remove/add calls above) - - } - -@@ -1639,7 +1730,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer); - - entityplayer.a(sectionposition); -- entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); -+ // Paper - distance map handles this now - return sectionposition; - } - -@@ -1684,6 +1775,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int k1; - int l1; - -+ /* // Paper start - replaced by distance map - if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { - k1 = Math.min(i, i1) - this.viewDistance; - l1 = Math.min(j, j1) - this.viewDistance; -@@ -1721,7 +1813,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map - - this.updateMaps(entityplayer); // Paper - distance maps - -@@ -1729,11 +1821,46 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { -- return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkcoordintpair); - -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; -- }); -+ if (inRange == null) { -+ return Stream.empty(); -+ } -+ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it -+ List players = new java.util.ArrayList<>(); -+ Object[] backingSet = inRange.getBackingSet(); -+ -+ if (flag) { // flag -> border only -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); -+ if (Math.max(distX, distZ) == viewDistance) { -+ players.add(player); -+ } -+ } -+ } else { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ players.add(player); -+ } -+ } -+ return players.stream(); -+ // Paper end - per player view distance - } - - public void addEntity(Entity entity) { // Paper - protected -> public -@@ -1891,7 +2018,48 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER -+ // Paper start -+ private static int getLightMask(final Chunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); -+ int mask = 0; -+ -+ for (int i = 0; i < chunkSections.length; ++i) { -+ /* -+ -+ -+Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. -+Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. -+ -+ */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ } -+ -+ return mask; -+ } -+ -+ private static int getCeilingLightMask(final Chunk chunk) { -+ int mask = getLightMask(chunk); -+ -+ /* -+ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. -+ We then invert this, so we'd have 110000 and compare that to the "main" chunk. -+ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. -+ -+ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. -+ @TODO: Implement Leafs suggestion -+ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then -+ */ -+ mask |= mask >> 1; -+ mask |= mask >> 2; -+ mask |= mask >> 4; -+ mask |= mask >> 8; -+ mask |= mask >> 16; -+ -+ return mask; -+ } -+ // Paper end -+ -+ public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -2077,7 +2245,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); - PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); - -- if (playerchunk != null && playerchunk.getChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; - } - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c7e78d0626fa0dd18021c1a0827a10c08ab10b4a..66fcd68f0a0a21b113e8741cc42c841f49009118 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -254,7 +254,7 @@ public abstract class PlayerList { - boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); - - // Spigot - view distance -- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); -+ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -908,7 +908,7 @@ public abstract class PlayerList { - // CraftBukkit start - WorldData worlddata = worldserver1.getWorldData(); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.spigotConfig.viewDistance)); // Spigot -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance - entityplayer1.spawnIn(worldserver1); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); -@@ -1376,7 +1376,7 @@ public abstract class PlayerList { - - public void a(int i) { - this.viewDistance = i; -- this.sendAll(new PacketPlayOutViewDistance(i)); -+ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance - Iterator iterator = this.server.getWorlds().iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index efcfc8f0f45901d14ac8fdf8ed7b0bd67f8f94da..7ead848342bfbb5b20e95d716805f4b4fd36eb63 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -525,8 +525,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.b(blockposition, iblockdata1, iblockdata2); - } - -- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement -+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below - this.notify(blockposition, iblockdata1, iblockdata, i); -+ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance -+ // if copied from above -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { -+ ((WorldServer)this).getChunkProvider().flagDirty(blockposition); -+ // Paper end - per player view distance - } - - if ((i & 1) != 0) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index bb2ff043f0d159fa18769c31b08683ee12037c58..90e895e9eac6158a28de4a30589bf7538e5ec9cc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -28,7 +28,12 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.level.ChunkTaskQueueSorter; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -243,7 +248,51 @@ public class Chunk implements IChunkAccess { - } - - protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ // Paper start - no-tick view distance -+ ChunkProviderServer chunkProviderServer = ((WorldServer)this.world).getChunkProvider(); -+ PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; -+ // this code handles the addition of ticking tickets - the distance map handles the removal -+ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { -+ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready for entity ticking -+ chunkProviderServer.serverThreadQueue.execute(() -> { -+ // double check that this condition still holds. -+ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update -+ } -+ }); -+ } -+ } - -+ // this code handles the chunk sending -+ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { -+ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready to send -+ chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap -+ // double check that this condition still holds. -+ if (!Chunk.this.areNeighboursLoaded(1)) { -+ return; -+ } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); -+ if (inRange == null) { -+ return; -+ } -+ -+ // broadcast -+ Object[] backingSet = inRange.getBackingSet(); -+ Packet[] chunkPackets = new Packet[2]; -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ Object temp = backingSet[index]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, Chunk.this); -+ } -+ }))); -+ } -+ } -+ // Paper end - no-tick view distance - } - - public final boolean isAnyNeighborsLoaded() { -@@ -1132,7 +1181,7 @@ public class Chunk implements IChunkAccess { - IBlockData iblockdata = this.getType(blockposition); - IBlockData iblockdata1 = Block.b(iblockdata, (GeneratorAccess) this.world, blockposition); - -- this.world.setTypeAndData(blockposition, iblockdata1, 20); -+ this.world.setTypeAndData(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here - } - - this.n[i].clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index c5a4c8c4c9d90a8a081a593488f86ab487adaecb..2d90ecf04f522a4e16f44c905450a61becaa1ed2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -2550,10 +2551,39 @@ public class CraftWorld implements World { - // Spigot start - @Override - public int getViewDistance() { -- return world.spigotConfig.viewDistance; -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance - } - // Spigot end - -+ // Paper start - per player view distance -+ @Override -+ public void setViewDistance(int viewDistance) { -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getEffectiveViewDistance()) { -+ chunkMap.setViewDistance(viewDistance); -+ } -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { -+ chunkMap.setNoTickViewDistance(viewDistance); -+ } -+ } -+ // Paper end - per player view distance -+ - // Spigot start - private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() - { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 663127e6e6ec507959142b18a11a5a4790d4b98b..5c2eaca0bc63c7880ee928aba6a24761737aa649 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -2,6 +2,7 @@ package org.spigotmc; - - import java.util.Collection; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityCreature; -@@ -197,7 +198,7 @@ public class ActivationRange - maxRange = Math.max( maxRange, waterActivationRange ); - maxRange = Math.max( maxRange, villagerActivationRange ); - // Paper end -- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((WorldServer)world).getChunkProvider().playerChunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance - - for ( EntityHuman player : world.getPlayers() ) - { diff --git a/Spigot-Server-Patches/0469-Add-villager-reputation-API.patch b/Spigot-Server-Patches/0469-Add-villager-reputation-API.patch deleted file mode 100644 index fa1df056fd62..000000000000 --- a/Spigot-Server-Patches/0469-Add-villager-reputation-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:29:20 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0f10c333d88f2e1c56a6c7f22d421084adfd3789 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -@@ -0,0 +1,9 @@ -+package com.destroystokyo.paper.entity.villager; -+// Must have own package due to package-level constructor. -+ -+public final class ReputationConstructor { -+ // Abuse the package-level constructor. -+ public static Reputation construct(int[] values) { -+ return new Reputation(values); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index a7f5e4a499c1f6fb1450e536dbf117a8af3b3b84..9cc3a18636a356977577076e96cb7be706c61abf 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -27,7 +27,7 @@ import net.minecraft.core.MinecraftSerializableUUID; - - public class Reputation { - -- private final Map a = Maps.newHashMap(); -+ private final Map a = Maps.newHashMap(); public Map getReputations() { return this.a; } // Paper - add getter for reputations - - public Reputation() {} - -@@ -142,11 +142,11 @@ public class Reputation { - return k > reputationtype.h ? Math.max(reputationtype.h, i) : k; - } - -- static class a { -+ public static class a { // Paper - make public - - private final Object2IntMap a; - -- private a() { -+ public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - -@@ -200,6 +200,28 @@ public class Reputation { - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -+ -+ // Paper start - Add villager reputation API -+ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); -+ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { -+ int[] reputation = new int[REPUTATION_TYPES.length]; -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = a.getOrDefault(ReputationType.TRADING, 0); -+ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); -+ } -+ -+ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { -+ int val; -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.a.put(ReputationType.MAJOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.a.put(ReputationType.MAJOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.a.put(ReputationType.MINOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.a.put(ReputationType.MINOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.a.put(ReputationType.TRADING, val); -+ } -+ // Paper end - } - - static class b { -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index d2850b003f8672122e70da0d52da1de59b2b01dd..b7c16dfa4ed7d68596c5b5d5037ce0ac3810ecfa 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -1038,6 +1038,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bD = 0; - } - -+ public Reputation getReputation() { return this.fj(); } // Paper - OBFHELPER - public Reputation fj() { - return this.by; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 4b2451179cdda918808ea7001f5033c7e5a8b9ac..073c4c518be5a32fccd82e5739ede461214007b2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -17,6 +17,13 @@ import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; - import org.bukkit.entity.Villager.Type; - -+// Paper start -+import com.destroystokyo.paper.entity.villager.Reputation; -+import com.google.common.collect.Maps; -+import java.util.Map; -+import java.util.UUID; -+// Paper end -+ - public class CraftVillager extends CraftAbstractVillager implements Villager { - - public CraftVillager(CraftServer server, EntityVillager entity) { -@@ -126,4 +133,45 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { - return IRegistry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); - } -+ -+ // Paper start - Add villager reputation API -+ @Override -+ public Reputation getReputation(UUID uniqueId) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a rep = getHandle().getReputation().getReputations().get(uniqueId); -+ if (rep == null) { -+ return new Reputation(Maps.newHashMap()); -+ } -+ -+ return rep.getPaperReputation(); -+ } -+ -+ @Override -+ public Map getReputations() { -+ return getHandle().getReputation().getReputations().entrySet() -+ .stream() -+ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); -+ } -+ -+ @Override -+ public void setReputation(UUID uniqueId, Reputation reputation) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a nmsReputation = -+ getHandle().getReputation().getReputations().computeIfAbsent( -+ uniqueId, -+ key -> new net.minecraft.world.entity.ai.gossip.Reputation.a() -+ ); -+ nmsReputation.assignFromPaperReputation(reputation); -+ } -+ -+ @Override -+ public void setReputations(Map reputations) { -+ for (Map.Entry entry : reputations.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ @Override -+ public void clearReputations() { -+ getHandle().getReputation().getReputations().clear(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0470-Fix-Light-Command.patch b/Spigot-Server-Patches/0470-Fix-Light-Command.patch deleted file mode 100644 index 6b3d2eed34cc..000000000000 --- a/Spigot-Server-Patches/0470-Fix-Light-Command.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 7 May 2020 19:17:36 -0400 -Subject: [PATCH] Fix Light Command - -This lets you run /paper fixlight (max 5) to automatically -fix all light data in the chunks. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index eb1e86e8bb0f421e3686ffa02a4015a588107863..d165e8c232c38ba2e2faf93c60c8a127bb74c9b6 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -8,6 +8,8 @@ import com.google.common.collect.ImmutableSet; - import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; -@@ -15,12 +17,14 @@ import com.google.gson.stream.JsonWriter; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -31,6 +35,7 @@ import org.bukkit.command.Command; - import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.entity.Player; - - import java.io.File; -@@ -39,10 +44,12 @@ import java.io.PrintStream; - import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; -+import java.util.ArrayDeque; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; - import java.util.Collections; -+import java.util.Deque; - import java.util.Iterator; - import java.util.List; - import java.util.Locale; -@@ -52,7 +59,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); - - public PaperCommand(String name) { - super(name); -@@ -173,6 +180,9 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); - break; -+ case "fixlight": -+ this.doFixLight(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -190,6 +200,77 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doFixLight(CommandSender sender, String[] args) { -+ if (!(sender instanceof Player)) { -+ sender.sendMessage("Only players can use this command"); -+ return; -+ } -+ int radius = 2; -+ if (args.length > 1) { -+ try { -+ radius = Math.min(5, Integer.parseInt(args[1])); -+ } catch (Exception e) { -+ sender.sendMessage("Not a number"); -+ return; -+ } -+ -+ } -+ -+ CraftPlayer player = (CraftPlayer) sender; -+ EntityPlayer handle = player.getHandle(); -+ WorldServer world = (WorldServer) handle.world; -+ LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine(); -+ -+ BlockPosition center = MCUtil.toBlockPosition(player.getLocation()); -+ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); -+ updateLight(sender, world, lightengine, queue); -+ } -+ -+ private void updateLight(CommandSender sender, WorldServer world, LightEngineThreaded lightengine, Deque queue) { -+ ChunkCoordIntPair coord = queue.poll(); -+ if (coord == null) { -+ sender.sendMessage("All Chunks Light updated"); -+ return; -+ } -+ world.getChunkProvider().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { -+ if (ex != null) { -+ sender.sendMessage("Error loading chunk " + coord); -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ Chunk chunk = (Chunk) either.left().orElse(null); -+ if (chunk == null) { -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ lightengine.a(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue -+ sender.sendMessage("Updating Light " + coord); -+ int cx = chunk.getPos().x << 4; -+ int cz = chunk.getPos().z << 4; -+ for (int y = 0; y < world.getHeight(); y++) { -+ for (int x = 0; x < 16; x++) { -+ for (int z = 0; z < 16; z++) { -+ BlockPosition pos = new BlockPosition(cx + x, y, cz + z); -+ lightengine.a(pos); -+ } -+ } -+ } -+ lightengine.queueUpdate(); -+ PlayerChunk visibleChunk = world.getChunkProvider().playerChunkMap.getVisibleChunk(chunk.coordinateKey); -+ if (visibleChunk != null) { -+ world.getChunkProvider().playerChunkMap.addLightTask(visibleChunk, () -> { -+ MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunk.getPos(), lightengine, true), false); -+ updateLight(sender, world, lightengine, queue); -+ }); -+ }); -+ } else { -+ updateLight(sender, world, lightengine, queue); -+ } -+ lightengine.a(world.paperConfig.lightQueueSize); -+ }, MinecraftServer.getServer()); -+ } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 1f6333c2c26ad04e23d2881235ed1dcf707be038..e53054fc46e528f9c713eb4c03add61316e19396 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -350,6 +350,7 @@ public class PlayerChunk { - - } - -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { a(packet, flag); } // Paper - OBFHELPER - private void a(Packet packet, boolean flag) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index e4b5649fbc8cb9662e818581fe2891641de419b6..a7e3a979dca4dd7705a8f80366677378f0643f27 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -346,11 +346,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox threadedmailbox1 = ThreadedMailbox.a(executor, "light"); -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); -+ this.mailboxLight = this.p.a(lightthreaded, false);// Paper - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; diff --git a/Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch b/Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch deleted file mode 100644 index 790460d70774..000000000000 --- a/Spigot-Server-Patches/0471-Fix-PotionEffect-ignores-icon-flag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 8 May 2020 00:49:18 -0400 -Subject: [PATCH] Fix PotionEffect ignores icon flag - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index b18292ef2e00b4ef8a0b2da5f63a596dbd04b1fd..5563e7c1ecc9e607ba0be21ae16a544b24d6f030 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -420,7 +420,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - - @Override - public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon - return true; - } - diff --git a/Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch b/Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch deleted file mode 100644 index e32f00ecf884..000000000000 --- a/Spigot-Server-Patches/0472-Optimize-brigadier-child-sorting-performance.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: virustotalop -Date: Thu, 16 Apr 2020 20:51:32 -0700 -Subject: [PATCH] Optimize brigadier child sorting performance - - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index f0f25fa40d4a0aa0e299ad11847b6a5f9102c214..7ef6c99d2235eed38197aa76bc9553d7efbe52a4 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -27,7 +27,7 @@ import java.util.stream.Collectors; - import net.minecraft.commands.CommandListenerWrapper; // CraftBukkit - - public abstract class CommandNode implements Comparable> { -- private Map> children = Maps.newLinkedHashMap(); -+ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting - private Map> literals = Maps.newLinkedHashMap(); - private Map> arguments = Maps.newLinkedHashMap(); - private final Predicate requirement; -@@ -107,8 +107,7 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); - } - } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed - } - - public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/Spigot-Server-Patches/0473-Potential-bed-API.patch b/Spigot-Server-Patches/0473-Potential-bed-API.patch deleted file mode 100644 index f002048a710d..000000000000 --- a/Spigot-Server-Patches/0473-Potential-bed-API.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Sun, 10 May 2020 23:06:30 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -getPotentialBedLocation - Gets the last known location of a player's bed. This does not preform any check if the bed is still valid and does not load any chunks. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 5b142e96248278c6bb6068879bb5ad1578b0f79f..92501a415813b3b0f2be492a4711962320264a76 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -13,6 +13,7 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -@@ -127,6 +128,22 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepTicks; - } - -+ // Paper start - Potential bed api -+ @Override -+ public Location getPotentialBedLocation() { -+ EntityPlayer handle = (EntityPlayer) getHandle(); -+ BlockPosition bed = handle.getSpawn(); -+ if (bed == null) { -+ return null; -+ } -+ -+ WorldServer worldServer = handle.server.getWorldServer(handle.getSpawnDimension()); -+ if (worldServer == null) { -+ return null; -+ } -+ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); -+ } -+ // Paper end - @Override - public boolean sleep(Location location, boolean force) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch b/Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch deleted file mode 100644 index 0e7e30a5fec6..000000000000 --- a/Spigot-Server-Patches/0474-Wait-for-Async-Tasks-during-shutdown.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:16:17 -0400 -Subject: [PATCH] Wait for Async Tasks during shutdown - -Server.reload() had this logic to give time for tasks to shutdown, -however shutdown did not... - -Adds a 5 second grace period for any async tasks to finish and warns -if any are still running after that delay just as reload does. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e25539dd54956225e8b14d3b8c636130267f226d..9074646e8111c69c4875b0633a424b250a30bc5c 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -893,6 +893,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0) { -+ try { -+ Thread.sleep(100); -+ } catch (InterruptedException e) {} -+ pollCount++; -+ } -+ -+ List overdueWorkers = getScheduler().getActiveWorkers(); -+ for (BukkitWorker worker : overdueWorkers) { -+ Plugin plugin = worker.getOwner(); -+ String author = ""; -+ if (plugin.getDescription().getAuthors().size() > 0) { -+ author = plugin.getDescription().getAuthors().get(0); -+ } -+ getLogger().log(Level.SEVERE, String.format( -+ "Nag author: '%s' of '%s' about the following: %s", -+ author, -+ plugin.getDescription().getName(), -+ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." -+ )); -+ } -+ } -+ // Paper end -+ - @Override - public void reloadData() { - CommandReload.reload(console); diff --git a/Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch deleted file mode 100644 index a5eab26a70f7..000000000000 --- a/Spigot-Server-Patches/0475-Ensure-EntityRaider-respects-game-and-entity-rules-f.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 9 May 2020 02:01:48 -0400 -Subject: [PATCH] Ensure EntityRaider respects game and entity rules for - picking up items - - -diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -index b9f5ed4e9348648a248dcd23eb100ceac49f26df..ff41ee884e3e46af1b1e9fb550f0abc6998fd031 100644 ---- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -+++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -@@ -523,7 +523,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - public class b extends PathfinderGoal { - -- private final T b; -+ private final T b; private T getRaider() { return b; } // Paper - obfhelper - - public b(T entityraider) { // CraftBukkit - decompile error - this.b = entityraider; -@@ -532,6 +532,7 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - @Override - public boolean a() { -+ if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items - Raid raid = this.b.fa(); - - if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { diff --git a/Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch deleted file mode 100644 index c5742080fb52..000000000000 --- a/Spigot-Server-Patches/0476-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 May 2020 23:01:26 -0400 -Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed - -This fixes exploits that let players destroy bedrock by Pistons, explosions -and Mushrooom/Tree generation. - -These blocks are designed to not be broken except by creative players/commands. -So protect them from a multitude of methods of destroying them. - -A config is provided if you rather let players use these exploits, and let -them destroy the worlds End Portals and get on top of the nether easy. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 78271b400c79578d043b20a5389a37b1bef9a70d..5f3b0d95cc7e6a0434d78ea7305a70689c41c71c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -416,4 +416,17 @@ public class PaperConfig { - private static void midTickChunkTasks() { - midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); - } -+ -+ public static boolean allowBlockPermanentBreakingExploits = false; -+ private static void allowBlockPermanentBreakingExploits() { -+ if (config.contains("allow-perm-block-break-exploits")) { -+ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); -+ config.set("allow-perm-block-break-exploits", null); -+ } -+ -+ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); -+ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); -+ -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index a9ecc2b4da587ca3d3c99f8c8af38092a02fb572..0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -153,6 +153,7 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -+ if (!iblockdata.isDestroyable()) continue; // Paper - Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - -@@ -306,7 +307,7 @@ public class Explosion { - IBlockData iblockdata = this.world.getType(blockposition); - Block block = iblockdata.getBlock(); - -- if (!iblockdata.isAir()) { -+ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper - BlockPosition blockposition1 = blockposition.immutableCopy(); - - this.world.getMethodProfiler().enter("explosion_blocks"); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 7ead848342bfbb5b20e95d716805f4b4fd36eb63..9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -422,6 +422,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -+ // Paper start -+ IBlockData type = getType(blockposition); -+ if (!type.isDestroyable()) return false; -+ // Paper end - CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index e5c43b383a93fac76333a67b41535ab009d1dcf3..cc512bd2e89382e7fdbc59b41640e95ccafbbfe9 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -62,6 +62,19 @@ public class Block extends BlockBase implements IMaterial { - protected final BlockStateList blockStateList; - private IBlockData blockData; - // Paper start -+ public final boolean isDestroyable() { -+ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || -+ this != Blocks.BEDROCK && -+ this != Blocks.END_PORTAL_FRAME && -+ this != Blocks.END_PORTAL && -+ this != Blocks.END_GATEWAY && -+ this != Blocks.COMMAND_BLOCK && -+ this != Blocks.REPEATING_COMMAND_BLOCK && -+ this != Blocks.CHAIN_COMMAND_BLOCK && -+ this != Blocks.BARRIER && -+ this != Blocks.STRUCTURE_BLOCK && -+ this != Blocks.JIGSAW; -+ } - public co.aikar.timings.Timing timing; - public co.aikar.timings.Timing getTiming() { - if (timing == null) { -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 7de86d6232eb84642fb6423a1b0a9f30d9df9f2b..e062fd288098127fae22a55562e0207ceaf50163 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -194,6 +194,12 @@ public class BlockPiston extends BlockDirectional { - @Override - public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) { - EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING); -+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) -+ EnumDirection directionQueuedAs = EnumDirection.fromType1(j & 7); // Paper - copied from below -+ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { -+ return false; -+ } -+ // Paper end - prevent retracting when we're facing the wrong way - - if (!world.isClientSide) { - boolean flag = this.a(world, blockposition, enumdirection); -@@ -225,7 +231,7 @@ public class BlockPiston extends BlockDirectional { - IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPistonMoving.a, enumdirection)).set(BlockPistonMoving.b, this.sticky ? BlockPropertyPistonType.STICKY : BlockPropertyPistonType.DEFAULT); - - world.setTypeAndData(blockposition, iblockdata1, 20); -- world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); -+ world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above - world.update(blockposition, iblockdata1.getBlock()); - iblockdata1.a(world, blockposition, 2); - if (this.sticky) { -@@ -254,7 +260,14 @@ public class BlockPiston extends BlockDirectional { - } - } - } else { -- world.a(blockposition.shift(enumdirection), false); -+ // Paper start - fix headless pistons breaking blocks -+ BlockPosition headPos = blockposition.shift(enumdirection); -+ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getType(headPos) == Blocks.PISTON_HEAD.getBlockData().set(FACING, enumdirection)) { // double check to make sure we're not a headless piston. -+ world.setAir(headPos, false); -+ } else { -+ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync -+ } -+ // Paper end - fix headless pistons breaking blocks - } - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 57857cc33603cf278de424b540a3d4a5943584c9..2a785ea58a7bdc80c703a60bc6ed602dc8040aa0 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -190,7 +190,7 @@ public abstract class BlockBase { - - @Deprecated - public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) { -- return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()); -+ return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()) && (iblockdata.isDestroyable() || (blockactioncontext.getEntity() != null && blockactioncontext.getEntity().abilities.canInstantlyBuild)); // Paper - } - - @Deprecated -@@ -394,7 +394,11 @@ public abstract class BlockBase { - public Block getBlock() { - return (Block) this.c; - } -- -+ // Paper start -+ public final boolean isDestroyable() { -+ return getBlock().isDestroyable(); -+ } -+ // Paper end - public Material getMaterial() { - return this.g; - } -@@ -484,7 +488,7 @@ public abstract class BlockBase { - } - - public EnumPistonReaction getPushReaction() { -- return this.getBlock().getPushReaction(this.p()); -+ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper - } - - public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch b/Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index 0b519eafdf0b..000000000000 --- a/Spigot-Server-Patches/0477-Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -index 247d969e7d1aa59d9650fce1032aaa09db3903e5..9050ff7180f63c1f5756570446c4d0a8cc767779 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -@@ -1,12 +1,16 @@ - package net.minecraft.network.protocol.game; - - import com.google.common.collect.Lists; -+import io.netty.channel.ChannelFuture; // Paper -+ - import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -24,14 +28,43 @@ public class PacketPlayOutLightUpdate implements Packet { - private List h; - private boolean i; - -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ @Override -+ public void onPacketDispatch(EntityPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ -+ // Paper end - public PacketPlayOutLightUpdate() {} - - public PacketPlayOutLightUpdate(ChunkCoordIntPair chunkcoordintpair, LightEngine lightengine, boolean flag) { - this.a = chunkcoordintpair.x; - this.b = chunkcoordintpair.z; - this.i = flag; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int i = 0; i < 18; ++i) { - NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); -@@ -42,7 +75,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.e |= 1 << i; - } else { - this.c |= 1 << i; -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } - } - -@@ -51,7 +84,7 @@ public class PacketPlayOutLightUpdate implements Packet { - this.f |= 1 << i; - } else { - this.d |= 1 << i; -- this.h.add(nibblearray1.asBytes().clone()); -+ this.h.add(nibblearray1.getCloneIfSet()); // Paper - } - } - } -@@ -64,8 +97,8 @@ public class PacketPlayOutLightUpdate implements Packet { - this.i = flag; - this.c = i; - this.d = j; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int k = 0; k < 18; ++k) { - NibbleArray nibblearray; -@@ -73,7 +106,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.c & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.c &= ~(1 << k); - if (nibblearray != null) { -@@ -85,7 +118,7 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.d & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.h.add(nibblearray.asBytes().clone()); -+ this.h.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.d &= ~(1 << k); - if (nibblearray != null) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index 86b4db483787c5fd10461f7d7e90a772ee049599..b82420e9a5d42a4383d24921614fe613c640edb9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -1,18 +1,78 @@ - // mc-dev import - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.util.pooled.PooledObjects; // Paper -+ -+import javax.annotation.Nonnull; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.server.MCUtil; - - public class NibbleArray { - -- @Nullable -- protected byte[] a; -+ // Paper start -+ public static byte[] EMPTY_NIBBLE = new byte[2048]; -+ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); -+ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -+ public static final PooledObjects BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } -+ -+ public NibbleArray markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.a = bytes; -+ return markPoolSafe(); -+ } -+ public NibbleArray markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.a != null ? this.a : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (a == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public NibbleArray cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.a = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.a, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); -+ } else { -+ cleaner = MCUtil.once(() -> NibbleArray.releaseBytes(this.a)); -+ } -+ } -+ // Paper end -+ @Nullable protected byte[] a; -+ - - public NibbleArray() {} - - public NibbleArray(byte[] abyte) { -+ // Paper start -+ this(abyte, false); -+ } -+ public NibbleArray(byte[] abyte, boolean isSafe) { - this.a = abyte; -+ if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (abyte.length != 2048) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); - } -@@ -46,7 +106,8 @@ public class NibbleArray { - - public void a(int i, int j) { // PAIL: private -> public - if (this.a == null) { -- this.a = new byte[2048]; -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner();// Paper - } - - int k = this.d(i); -@@ -68,14 +129,36 @@ public class NibbleArray { - public byte[] asBytes() { - if (this.a == null) { - this.a = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.a = this.a.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } -+ } -+ // Paper end -+ -+ return this.a; -+ } -+ -+ @Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.a == null) { -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - -+ //noinspection ConstantConditions - return this.a; - } -+ // Paper end - - public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { -- return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); -+ return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index e16e046d165330326ed220c9c440a637007f3137..91bcbf7156dd90b00e2d53bb6bff4abc44ecb721 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -435,11 +435,11 @@ public class ChunkRegionLoader { - } - - if (nibblearray != null && !nibblearray.c()) { -- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytes()); -+ nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.c()) { -- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytes()); -+ nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - nbttaglist.add(nbttagcompound2); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 5b1ff4ff87591dd4ff0b79e4ac6ff0494fc3d0f8..9ba9efb181b9607f25b7c921e69e4c59b182d429 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -156,7 +156,7 @@ public abstract class LightEngineStorage> e - protected NibbleArray j(long i) { - NibbleArray nibblearray = (NibbleArray) this.i.get(i); - -- return nibblearray != null ? nibblearray : new NibbleArray(); -+ return nibblearray != null ? nibblearray : new NibbleArray().markPoolSafe(); // Paper - } - - protected void a(LightEngineLayer lightenginelayer, long i) { -@@ -338,12 +338,12 @@ public abstract class LightEngineStorage> e - - protected void a(long i, @Nullable NibbleArray nibblearray, boolean flag) { - if (nibblearray != null) { -- this.i.put(i, nibblearray); -+ NibbleArray remove = this.i.put(i, nibblearray); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!flag) { - this.n.add(i); - } - } else { -- this.i.remove(i); -+ NibbleArray remove = this.i.remove(i); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index ed7864c552054fc47c6010a094230ce4aebf1c54..da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - import javax.annotation.Nullable; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { -@@ -34,7 +35,9 @@ public abstract class LightEngineStorageArray -Date: Mon, 27 Apr 2020 02:48:06 -0700 -Subject: [PATCH] Reduce MutableInt allocations from light engine - -We can abuse the fact light is single threaded and share an instance -per light engine instance - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index 2a0a5a70c795ba33780c8db774eaf9769a85daa7..f6198069e3ca421b4f551939263c7cf8bd5b754e 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -16,6 +16,7 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 113c575a16121aa1146f21a6f41ebd9d12a0c924..37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -15,6 +15,7 @@ public final class LightEngineSky extends LightEngineLayer= 15) { - return k; - } else { -- MutableInt mutableint = new MutableInt(); -+ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - IBlockData iblockdata = this.a(j, mutableint); - - if (mutableint.getValue() >= 15) { diff --git a/Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch deleted file mode 100644 index 40cf99012870..000000000000 --- a/Spigot-Server-Patches/0479-Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 00:04:16 -0700 -Subject: [PATCH] Reduce allocation of Vec3D by entity tracker - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index b64aa6c9ce906b08e43891f8c465fa4e8b2a8906..58dd349adf2bc9bac6569464ef7a7aec81729e79 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -155,8 +155,12 @@ public class EntityTrackerEntry { - ++this.o; - i = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); - j = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); -- Vec3D vec3d = this.tracker.getPositionVector().d(PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc)); -- boolean flag1 = vec3d.g() >= 7.62939453125E-6D; -+ // Paper start - reduce allocation of Vec3D here -+ double vec3d_dx = this.tracker.locX() - 2.44140625E-4D*(this.xLoc); -+ double vec3d_dy = this.tracker.locY() - 2.44140625E-4D*(this.yLoc); -+ double vec3d_dz = this.tracker.locZ() - 2.44140625E-4D*(this.zLoc); -+ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; -+ // Paper end - reduce allocation of Vec3D here - Packet packet1 = null; - boolean flag2 = flag1 || this.tickCounter % 60 == 0; - boolean flag3 = Math.abs(i - this.yRot) >= 1 || Math.abs(j - this.xRot) >= 1; -@@ -173,9 +177,11 @@ public class EntityTrackerEntry { - // CraftBukkit end - - if (this.tickCounter > 0 || this.tracker instanceof EntityArrow) { -- long k = PacketPlayOutEntity.a(vec3d.x); -- long l = PacketPlayOutEntity.a(vec3d.y); -- long i1 = PacketPlayOutEntity.a(vec3d.z); -+ // Paper start - remove allocation of Vec3D here -+ long k = PacketPlayOutEntity.a(vec3d_dx); -+ long l = PacketPlayOutEntity.a(vec3d_dy); -+ long i1 = PacketPlayOutEntity.a(vec3d_dz); -+ // Paper end - remove allocation of Vec3D here - boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; - - if (!flag4 && this.o <= 400 && !this.q && this.r == this.tracker.isOnGround()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index a7e3a979dca4dd7705a8f80366677378f0643f27..c3394b22d1a22fd83ff43473da34704ad547836f 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -2235,9 +2235,14 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public void updatePlayer(EntityPlayer entityplayer) { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot - if (entityplayer != this.tracker) { -- Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ // Paper start - remove allocation of Vec3D here -+ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ double vec3d_dx = entityplayer.locX() - this.tracker.locX(); -+ double vec3d_dy = entityplayer.locY() - this.tracker.locY(); -+ double vec3d_dz = entityplayer.locZ() - this.tracker.locZ(); -+ // Paper end - remove allocation of Vec3D here - int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16); -- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.tracker.a(entityplayer); -+ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.tracker.a(entityplayer); // Paper - remove allocation of Vec3D here - - if (flag) { - boolean flag1 = this.tracker.attachedToPlayer; diff --git a/Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch b/Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch deleted file mode 100644 index cf98a288ea84..000000000000 --- a/Spigot-Server-Patches/0480-Ensure-safe-gateway-teleport.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 15 May 2020 01:10:03 -0400 -Subject: [PATCH] Ensure safe gateway teleport - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index b7548d0b3938d95328fc86db4000190532eaa8f5..855c49164277ca96ca08fb204d851a5ad6789990 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -89,9 +89,14 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - } else if (!this.world.isClientSide) { - List list = this.world.a(Entity.class, new AxisAlignedBB(this.getPosition()), TileEntityEndGateway::a); - -- if (!list.isEmpty()) { -- this.b((Entity) list.get(this.world.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canPortal()) { -+ this.b(entity); -+ break; -+ } - } -+ // Paper end - - if (this.age % 2400L == 0L) { - this.h(); diff --git a/Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch b/Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch deleted file mode 100644 index 908755e00423..000000000000 --- a/Spigot-Server-Patches/0481-Add-option-for-console-having-all-permissions.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:12:15 +0200 -Subject: [PATCH] Add option for console having all permissions - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 5f3b0d95cc7e6a0434d78ea7305a70689c41c71c..7f140333c2e62012fa572c1a061d84432426997f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -429,4 +429,9 @@ public class PaperConfig { - - } - -+ public static boolean consoleHasAllPermissions = false; -+ private static void consoleHasAllPermissions() { -+ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 202fa94d5dc55b549475ae0309bbcfca8f1b2c96..ec0956a98c133bcd3d4f92f696c667eab6ff98f1 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -1889,7 +1889,7 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- protected void releaseShoulderEntities() { -+ public void releaseShoulderEntities() { // Paper - protected -> public - if (this.e + 20L < this.world.getTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index af986adfdb547cb61fbd52f0f89858f1a9e52cc3..80a67deaeaae3b3f0ceb9a298de5bb38b8ee707b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -86,5 +86,15 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { - this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); - } -+ -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -index 24662d58cb4a9bf2f3b252858b504165d91d4419..a6f3594def0abe076ff44fcfa61dd05bee729387 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -@@ -39,4 +39,16 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme - public void setOp(boolean value) { - throw new UnsupportedOperationException("Cannot change operator status of remote controller."); - } -+ -+ // Paper start -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch deleted file mode 100644 index 5f3ad1df7976..000000000000 --- a/Spigot-Server-Patches/0482-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 01:31:06 -0400 -Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak - -Any full status chunk that was requested for any status less than full -would hold onto their entire nbt tree and every variable in that function. - -This was due to use of a lambda that persists on the Chunk object -until that chunk reaches FULL status. - -With introduction of no tick, we greatly increased the number of non -full chunks so this was really starting to hurt. - -We further improve it by making a copy of the nbt tag with only the memory -it needs, so that we dont have to hold a copy to the entire compound. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 91bcbf7156dd90b00e2d53bb6bff4abc44ecb721..8e4924cd649c350520cba54a0e1497d5acf089ff 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -22,6 +22,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.core.RegistryBlocks; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; -@@ -199,15 +200,9 @@ public class ChunkRegionLoader { - object2 = protochunkticklist1; - } - -- object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- loadEntities(nbttagcompound1, chunk); -- // CraftBukkit start - load chunk persistent data from nbt -- net.minecraft.nbt.NBTBase persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -- if (persistentBase instanceof NBTTagCompound) { -- chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -- } -- // CraftBukkit end -- }); -+ object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. -+ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here -+ );// Paper end - } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - -@@ -313,6 +308,50 @@ public class ChunkRegionLoader { - return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading - } - } -+ // Paper start -+ -+ /** -+ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update -+ */ -+ private static class SafeNBTCopy extends NBTTagCompound { -+ private final java.util.Set keys = new java.util.HashSet(); -+ public SafeNBTCopy(NBTTagCompound base, String... keys) { -+ for (String key : keys) { -+ this.keys.add(key); -+ final NBTBase nbtBase = base.get(key); -+ if (nbtBase != null) { -+ this.set(key, nbtBase); -+ } -+ } -+ } -+ -+ @Override -+ public boolean hasKey(String s) { -+ if (super.hasKey(s)) { -+ return true; -+ } else if (keys.contains(s)) { -+ return false; -+ } -+ throw new IllegalStateException("Missing Key " + s + " in SafeNBTCopy"); -+ } -+ -+ @Override -+ public boolean hasKeyOfType(String s, int i) { -+ return hasKey(s) && super.hasKeyOfType(s, i); -+ } -+ } -+ private static java.util.function.Consumer createLoadEntitiesConsumer(NBTTagCompound nbt) { -+ return (chunk) -> { -+ loadEntities(nbt, chunk); -+ // CraftBukkit start - load chunk persistent data from nbt -+ NBTBase persistentBase = nbt.get("ChunkBukkitValues"); -+ if (persistentBase instanceof NBTTagCompound) { -+ chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -+ } -+ // CraftBukkit end -+ }; -+ } -+ // Paper end - - // Paper start - async chunk save for unload - public static final class AsyncSaveData { diff --git a/Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch deleted file mode 100644 index 3581cde231aa..000000000000 --- a/Spigot-Server-Patches/0483-Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 12 May 2020 23:02:43 +0200 -Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) - -When crossing certain chunk boundaries, the client needlessly -calculates light maps for chunk neighbours. In some specific map -configurations, these calculations cause a 500ms+ freeze on the Client. - -This patch basically serves as a workaround by sending light maps -to the client, so that it doesn't attempt to calculate them. -This mitigates the frametime impact to a minimum (but it's still there). - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index c3394b22d1a22fd83ff43473da34704ad547836f..6ddbc83a08be4e7aa5cd85cf78f14604d4759f30 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -85,6 +85,7 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -+import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; -@@ -2063,9 +2064,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -+ // Paper start - add 8 for light fix workaround -+ if (apacket.length != 10) { // in case Plugins call sendChunk, resize -+ apacket = new Packet[10]; -+ } -+ // Paper end - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); -+ -+ // Paper start - Fix MC-162253 -+ final int lightMask = getLightMask(chunk); -+ int i = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++i; -+ -+ if (!chunk.isNeighbourLoaded(x, z)) { -+ continue; -+ } -+ -+ final Chunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); -+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); -+ -+ if (updateLightMask == 0) { -+ continue; -+ } -+ -+ apacket[i] = new PacketPlayOutLightUpdate(new ChunkCoordIntPair(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); -+ } -+ } -+ } -+ -+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(entityplayer); -+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(entityplayer); -+ -+ int j = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++j; -+ -+ Packet packet = apacket[j]; -+ if (packet == null) { -+ continue; -+ } -+ -+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); -+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); -+ -+ if (Math.max(distX, distZ) > viewDistance) { -+ continue; -+ } -+ entityplayer.playerConnection.sendPacket(packet); -+ } - } -+ // Paper end - Fix MC-162253 - - entityplayer.a(chunk.getPos(), apacket[0], apacket[1]); - PacketDebug.a(this.world, chunk.getPos()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 90e895e9eac6158a28de4a30589bf7538e5ec9cc..34a9f7b2f998f77b1279516cd09397ab6c2ac1cc 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -280,7 +280,7 @@ public class Chunk implements IChunkAccess { - - // broadcast - Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[2]; -+ Packet[] chunkPackets = new Packet[10]; - for (int index = 0, len = backingSet.length; index < len; ++index) { - Object temp = backingSet[index]; - if (!(temp instanceof EntityPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 973aa060d6964c7d470bc7aff89b879daf1df153..8fe060c3b2ad0873f96218eb7d02cdff3279224e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -107,6 +107,7 @@ public class ChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable ChunkSection chunksection) { return a(chunksection) ; } // Paper - OBFHELPER - public static boolean a(@Nullable ChunkSection chunksection) { - return chunksection == Chunk.a || chunksection.c(); - } diff --git a/Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch deleted file mode 100644 index 960c61888193..000000000000 --- a/Spigot-Server-Patches/0484-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ /dev/null @@ -1,1326 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 03:56:07 -0400 -Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks - -Mark chunks that are blocking main thread for world generation as urgent - -Implements a general priority system so that chunks that are sorted in -the generator queues can prioritize certain chunks over another. - -Urgent chunks will jump to the front of the line, ensuring that a -sync chunk load on an ungenerated chunk does not lag the server for -a long period of time if the servers generator queues are filled with -lots of chunks already. - -This massively reduces the lag spikes from sync chunk gens. - -Then we further prioritize loading order so nearby chunks have higher -priority than distant chunks, reducing the pressure a high no tick -view distance holds on you. - -Chunks in front of the player have higher priority, to help with -fast traveling players keep up with their movement. - -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -index 8e642f450b974d81f128d26edfd40915554db638..dc641664abe8ff6b36c69c7d21a3200d160ff1b6 100644 ---- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -108,7 +108,7 @@ public final class ChunkTaskManager { - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -@@ -129,6 +129,30 @@ public final class ChunkTaskManager { - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); -+ -+ if (!chunkHolder.neighbors.isEmpty()) { -+ if (indent >= maxDepth) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); -+ return; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); -+ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) { -+ ChunkStatus status = neighbor.getChunkHolderStatus(); -+ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) { -+ continue; -+ } -+ int nx = neighbor.location.x; -+ int nz = neighbor.location.z; -+ if (seenChunks.contains(neighbor)) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); -+ continue; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); -+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); -+ } -+ } -+ - } - } - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 17de074111a174f3a39a4477afc3ad62e04a73b5..1d72af9cace7aa8f1d20c7c1c5be621f533e2dad 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -673,6 +673,7 @@ public final class MCUtil { - chunkData.addProperty("x", playerChunk.location.x); - chunkData.addProperty("z", playerChunk.location.z); - chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); - chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); - chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); - chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 2bbdcedf4856080ea9232effdf3bdae9c26c425b..a3c44fdfca8290313b9b1117b984533183b583ad 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -21,7 +21,10 @@ import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ArraySetSorted; - import net.minecraft.util.thread.Mailbox; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -29,6 +32,7 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import org.spigotmc.AsyncCatcher; // Paper - - public abstract class ChunkMapDistance { - -@@ -52,7 +56,7 @@ public abstract class ChunkMapDistance { - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -- private final LongSet l = new LongOpenHashSet(); -+ private final LongSet l = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return l; } // Paper - OBFHELPER - private final Executor m; - private long currentTick; - -@@ -90,6 +94,7 @@ public abstract class ChunkMapDistance { - } - - private static int getLowestTicketLevel(ArraySetSorted> arraysetsorted) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper - return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.b()).b() : PlayerChunkMap.GOLDEN_TICKET + 1; - } - -@@ -103,6 +108,7 @@ public abstract class ChunkMapDistance { - - public boolean a(PlayerChunkMap playerchunkmap) { - //this.f.a(); // Paper - no longer used -+ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -113,11 +119,13 @@ public abstract class ChunkMapDistance { - - // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -+ this.pollingPendingChunkUpdates = true; try { - while(!this.pendingChunkUpdates.isEmpty()) { - PlayerChunk remove = this.pendingChunkUpdates.remove(); - remove.isUpdateQueued = false; - remove.a(playerchunkmap); - } -+ } finally { this.pollingPendingChunkUpdates = false; } - // Paper end - return true; - } else { -@@ -153,8 +161,10 @@ public abstract class ChunkMapDistance { - return flag; - } - } -+ boolean pollingPendingChunkUpdates = false; // Paper - - private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); - int j = getLowestTicketLevel(arraysetsorted); - Ticket ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error -@@ -168,7 +178,9 @@ public abstract class ChunkMapDistance { - } - - private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); -+ int oldLevel = getLowestTicketLevel(arraysetsorted); // Paper - - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { -@@ -179,7 +191,8 @@ public abstract class ChunkMapDistance { - this.tickets.remove(i); - } - -- this.ticketLevelTracker.update(i, getLowestTicketLevel(arraysetsorted), false); -+ int newLevel = getLowestTicketLevel(arraysetsorted); // Paper -+ if (newLevel > oldLevel) this.ticketLevelTracker.update(i, newLevel, false); // Paper - return removed; // CraftBukkit - } - -@@ -188,6 +201,135 @@ public abstract class ChunkMapDistance { - this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0); - } - -+ // Paper start -+ public static final int PRIORITY_TICKET_LEVEL = PlayerChunkMap.GOLDEN_TICKET; -+ public static final int URGENT_PRIORITY = 29; -+ public boolean delayDistanceManagerTick = false; -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); -+ } -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ return addPriorityTicket(coords, TicketType.PRIORITY, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ delayDistanceManagerTick = true; -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ int finalPriority = priority; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ delayDistanceManagerTick = true; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ private boolean hasPlayerTicket(ChunkCoordIntPair coords, int level) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null || tickets.isEmpty()) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType ticketType, int priority) { -+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); -+ long pair = coords.pair(); -+ PlayerChunk chunk = chunkMap.getUpdatingChunk(pair); -+ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); -+ -+ if (needsTicket) { -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -+ getOnPlayerTicketAddQueue().add(pair); -+ addTicket(pair, ticket); -+ } -+ if ((chunk != null && chunk.isFullChunkReady())) { -+ if (needsTicket) { -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ return needsTicket; -+ } -+ -+ boolean success; -+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { -+ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); -+ ticket.priority = priority; -+ success = this.addTicket(pair, ticket); -+ } else { -+ if (chunk == null) { -+ chunk = chunkMap.getUpdatingChunk(pair); -+ } -+ chunkMap.queueHolderUpdate(chunk); -+ } -+ -+ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); -+ -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ -+ return success; -+ } -+ -+ private boolean updatePriorityTicket(ChunkCoordIntPair coords, TicketType type, int priority) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == type) { -+ // We only support increasing, not decreasing, too complicated -+ ticket.setCurrentTick(this.currentTick); -+ ticket.priority = Math.max(ticket.priority, priority); -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ public int getChunkPriority(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return 0; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.URGENT) { -+ return URGENT_PRIORITY; -+ } -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PRIORITY && ticket.priority > 0) { -+ return ticket.priority; -+ } -+ } -+ return 0; -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ -+ public void clearUrgent(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ // Paper end - public boolean addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { - return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier)); - // CraftBukkit end -@@ -358,7 +500,7 @@ public abstract class ChunkMapDistance { - - class c extends ChunkMapDistance.b { - -- private int e = 0; -+ private int e = 0; private int getViewDistance() { return e; } private void setViewDistance(int value) { this.e = value; } // Paper - OBFHELPER - private final Long2IntMap f = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); - private final LongSet g = new LongOpenHashSet(); - -@@ -374,41 +516,68 @@ public abstract class ChunkMapDistance { - - public void a(int i) { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); -+ // Paper start - set the view distance before scheduling chunk loads/unloads -+ int lastViewDistance = getViewDistance(); -+ setViewDistance(i); -+ // Paper end - - while (objectiterator.hasNext()) { - Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -- this.a(j, b0, this.c(b0), b0 <= i - 2); -+ this.a(j, b0, b0 <= lastViewDistance - 2, this.c(b0)); // Paper - } - -- this.e = i; -+ //this.e = i; // Paper - view distance is now set further up - } - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance -+ ChunkCoordIntPair coords = new ChunkCoordIntPair(i); // Paper -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance - - if (flag1) { -- ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -+ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> { // Paper - smarter ticket delay based on frustum and distance -+ // Paper start - recheck its still valid if not cancel -+ if (!isChunkInRange(i)) { -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ ChunkMapDistance.this.m.execute(() -> { -+ ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); -+ }); -+ }, i, false)); -+ return; -+ } -+ // abort early if we got a ticket already -+ if (hasPlayerTicket(coords, 33)) return; -+ // skip player ticket throttle for near chunks -+ if (priority <= 3) { -+ ChunkMapDistance.this.addTicket(i, ticket); -+ ChunkMapDistance.this.l.add(i); -+ return; -+ } -+ // Paper end -+ ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - ChunkMapDistance.this.m.execute(() -> { -- if (this.c(this.c(i))) { -+ if (isChunkInRange(i)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it - ChunkMapDistance.this.addTicket(i, ticket); - ChunkMapDistance.this.l.add(i); -- } else { -- ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ }} else { // Paper -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - }, i, false)); - } - - }); - }, i, () -> { -- return j; -+ return Math.min(PlayerChunkMap.GOLDEN_TICKET, priority); // Paper - })); -+ }); // Paper - } else { - ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { - ChunkMapDistance.this.m.execute(() -> { - ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); // Paper - }); - }, i, true)); - } -@@ -416,6 +585,101 @@ public abstract class ChunkMapDistance { - - } - -+ // Paper start - smart scheduling of player tickets -+ private boolean isChunkInRange(long i) { -+ return this.isLoadedChunkLevel(this.getChunkLevel(i)); -+ } -+ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { -+ long elapsed = MinecraftServer.currentTick - startTick; -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(i); -+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(i); -+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above -+ // no longer needed -+ task.accept(1); -+ return; -+ } -+ -+ int desireDelay = 0; -+ double minDist = Double.MAX_VALUE; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); -+ if (elapsed == 0 && initialDistance <= 4) { -+ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 -+ minDist = initialDistance; -+ } else if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ -+ BlockPosition blockPos = chunkPos.asPosition(); -+ -+ boolean isFront = false; -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ if (!(backingSet[index] instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) backingSet[index]; -+ -+ ChunkCoordIntPair pointInFront = player.getChunkInFront(5); -+ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); -+ double frontDist = MCUtil.distanceSq(pos, blockPos); -+ -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double center = MCUtil.distanceSq(pos, blockPos); -+ -+ double dist = Math.min(frontDist, center); -+ if (!isFront) { -+ ChunkCoordIntPair pointInBack = player.getChunkInFront(-7); -+ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); -+ double backDist = MCUtil.distanceSq(pos, blockPos); -+ if (frontDist < backDist) { -+ isFront = true; -+ } -+ } -+ if (dist < minDist) { -+ minDist = dist; -+ } -+ } -+ if (minDist == Double.MAX_VALUE) { -+ minDist = 15; -+ } else { -+ minDist = Math.sqrt(minDist) / 16; -+ } -+ if (minDist > 4) { -+ int desiredTimeDelayMax = isFront ? -+ (minDist < 10 ? 7 : 15) : // Front -+ (minDist < 10 ? 15 : 45); // Back -+ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); -+ } -+ } else { -+ minDist = initialDistance; -+ desireDelay = 1; -+ } -+ long delay = desireDelay - elapsed; -+ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { -+ boolean hasAnyNeighbor = false; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) continue; -+ long pair = ChunkCoordIntPair.pair(chunkPos.x + x, chunkPos.z + z); -+ PlayerChunk neighbor = chunkMap.getUpdatingChunk(pair); -+ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; -+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { -+ hasAnyNeighbor = true; -+ } -+ } -+ } -+ if (!hasAnyNeighbor) { -+ delay += 20; -+ } -+ } -+ if (delay <= 0) { -+ task.accept((int) minDist); -+ } else { -+ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); -+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); -+ } -+ } -+ // Paper end -+ - @Override - public void a() { - super.a(); -@@ -447,6 +711,7 @@ public abstract class ChunkMapDistance { - - } - -+ private boolean isLoadedChunkLevel(int i) { return c(i); } // Paper - OBFHELPER - private boolean c(int i) { - return i <= this.e - 2; - } -@@ -463,6 +728,7 @@ public abstract class ChunkMapDistance { - this.a.defaultReturnValue((byte) (i + 2)); - } - -+ protected final int getChunkLevel(long i) { return c(i); } // Paper - OBFHELPER - @Override - protected int c(long i) { - return this.a.get(i); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 42bb00364375e5cf324b43557385345868b37ffe..19e02d12bb0c5a73066f7c57da40277918276210 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -468,6 +468,26 @@ public class ChunkProviderServer extends IChunkProvider { - public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { - this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); - } -+ -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return this.chunkMapDistance.markUrgent(coords); -+ } -+ -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ return this.chunkMapDistance.markHighPriority(coords, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ this.chunkMapDistance.markAreaHighPriority(center, priority, radius); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ this.chunkMapDistance.clearAreaPriorityTickets(center, radius); -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ this.chunkMapDistance.clearPriorityTickets(coords); -+ } - // Paper end - - @Nullable -@@ -506,6 +526,8 @@ public class ChunkProviderServer extends IChunkProvider { - - if (!completablefuture.isDone()) { // Paper - // Paper start - async chunk io/loading -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(x, z); -+ this.chunkMapDistance.markUrgent(pair); - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -@@ -514,6 +536,8 @@ public class ChunkProviderServer extends IChunkProvider { - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ this.chunkMapDistance.clearPriorityTickets(pair); // Paper -+ this.chunkMapDistance.clearUrgent(pair); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; -@@ -566,10 +590,12 @@ public class ChunkProviderServer extends IChunkProvider { - if (flag && !currentlyUnloading) { - // CraftBukkit end - this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); -+ if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper - if (this.a(playerchunk, l)) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.enter("chunkLoad"); -+ chunkMapDistance.delayDistanceManagerTick = false; // Paper - ensure this is never false - this.tickDistanceManager(); - playerchunk = this.getChunk(k); - gameprofilerfiller.exit(); -@@ -578,8 +604,13 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - } -- -- return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ // Paper start -+ CompletableFuture> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ if (isUrgent) { -+ future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); -+ } -+ return future; -+ // Paper end - } - - private boolean a(@Nullable PlayerChunk playerchunk, int i) { -@@ -630,6 +661,7 @@ public class ChunkProviderServer extends IChunkProvider { - } - - public boolean tickDistanceManager() { // Paper - private -> public -+ if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 89a66078b722f265abd73579545a1f24df9442aa..8055172c806f285aa9a9e6de681d03b008fbf785 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -73,6 +73,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.network.ITextFilter; - import net.minecraft.server.network.PlayerConnection; -@@ -188,6 +189,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private int lastArmorScored = Integer.MIN_VALUE; - private int lastExpLevelScored = Integer.MIN_VALUE; - private int lastExpTotalScored = Integer.MIN_VALUE; -+ public long lastHighPriorityChecked; // Paper -+ public void forceCheckHighPriority() { -+ lastHighPriorityChecked = -1; -+ getWorldServer().getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); -+ } -+ public boolean isRealPlayer; // Paper - private float lastHealthSent = -1.0E8F; - private int lastFoodSent = -99999999; - private boolean lastSentSaturationZero = true; -@@ -275,6 +282,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.maxHealthCache = this.getMaxHealth(); - this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } -+ // Paper start -+ public BlockPosition getPointInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + inFront * Math.cos(rads); -+ final double z = locZ() + inFront * Math.sin(rads); -+ return new BlockPosition(x, locY(), z); -+ } -+ -+ public ChunkCoordIntPair getChunkInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + (inFront * 16) * Math.cos(rads); -+ final double z = locZ() + (inFront * 16) * Math.sin(rads); -+ return new ChunkCoordIntPair(MathHelper.floor(x) >> 4, MathHelper.floor(z) >> 4); -+ } -+ // Paper end - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome -@@ -622,6 +644,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } -+ if (valid && isAlive() && playerConnection != null) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper - - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack = this.inventory.getItem(i); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index e53054fc46e528f9c713eb4c03add61316e19396..fc79a73c884ceb7e0ce56443c36b135c4e525193 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - import it.unimi.dsi.fastutil.shorts.ShortArraySet; - import it.unimi.dsi.fastutil.shorts.ShortSet; - import java.util.List; -@@ -19,6 +20,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; -@@ -53,8 +55,8 @@ public class PlayerChunk { - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -- private int n; -- final ChunkCoordIntPair location; // Paper - private -> package -+ volatile int n; public final int getCurrentPriority() { return n; } // Paper - OBFHELPER - make volatile since this is concurrently accessed -+ public final ChunkCoordIntPair location; // Paper - private -> public - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -@@ -66,6 +68,7 @@ public class PlayerChunk { - private boolean x; - - private final PlayerChunkMap chunkMap; // Paper -+ public WorldServer getWorld() { return chunkMap.world; } // Paper - - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave -@@ -93,6 +96,120 @@ public class PlayerChunk { - return null; - } - // Paper end - no-tick view distance -+ // Paper start - Chunk gen/load priority system -+ volatile int neighborPriority = -1; -+ volatile int priorityBoost = 0; -+ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); -+ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); -+ -+ private int getDemandedPriority() { -+ int priority = neighborPriority; // if we have a neighbor priority, use it -+ int myPriority = getMyPriority(); -+ -+ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { -+ priority = myPriority; -+ } -+ -+ return Math.max(1, Math.min(Math.max(ticketLevel, PlayerChunkMap.GOLDEN_TICKET), priority)); -+ } -+ -+ private int getMyPriority() { -+ if (priorityBoost == ChunkMapDistance.URGENT_PRIORITY) { -+ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents -+ } -+ return ticketLevel - priorityBoost; -+ } -+ -+ private int getNeighborsPriority() { -+ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; -+ } -+ -+ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) { -+ neighbor.setNeighborPriority(this, getNeighborsPriority()); -+ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { -+ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { -+ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); -+ return status; -+ } else { -+ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); -+ return currentWantedStatus; -+ } -+ }); -+ -+ } -+ -+ public void onNeighborDone(PlayerChunk neighbor, ChunkStatus chunkstatus, IChunkAccess chunk) { -+ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { -+ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { -+ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); -+ neighbor.removeNeighborPriority(this); -+ return null; -+ } else { -+ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); -+ return wantedStatus; -+ } -+ }); -+ } -+ -+ private void removeNeighborPriority(PlayerChunk requester) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.remove(requester.location.pair()); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ -+ private void setNeighborPriority(PlayerChunk requester, int priority) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.put(requester.location.pair(), Integer.valueOf(priority)); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ private void recalcNeighborPriority() { -+ neighborPriority = -1; -+ if (!neighborPriorities.isEmpty()) { -+ synchronized (neighborPriorities) { -+ for (Integer neighbor : neighborPriorities.values()) { -+ if (neighbor < neighborPriority || neighborPriority == -1) { -+ neighborPriority = neighbor; -+ } -+ } -+ } -+ } -+ } -+ private void checkPriority() { -+ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); -+ } -+ -+ public final double getDistance(EntityPlayer player) { -+ return getDistance(player.locX(), player.locZ()); -+ } -+ public final double getDistance(double blockX, double blockZ) { -+ int cx = MCUtil.fastFloor(blockX) >> 4; -+ int cz = MCUtil.fastFloor(blockZ) >> 4; -+ final double x = location.x - cx; -+ final double z = location.z - cz; -+ return (x * x) + (z * z); -+ } -+ -+ public final double getDistanceFrom(BlockPosition pos) { -+ return getDistance(pos.getX(), pos.getZ()); -+ } -+ -+ @Override -+ public String toString() { -+ return "PlayerChunk{" + -+ "location=" + location + -+ ", ticketLevel=" + ticketLevel + "/" + getChunkStatus(this.ticketLevel) + -+ ", chunkHolderStatus=" + getChunkHolderStatus() + -+ ", neighborPriority=" + getNeighborsPriority() + -+ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + -+ '}'; -+ } -+ // Paper end - - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); -@@ -195,6 +312,18 @@ public class PlayerChunk { - } - return null; - } -+ public static ChunkStatus getNextStatus(ChunkStatus status) { -+ if (status == ChunkStatus.FULL) { -+ return status; -+ } -+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); -+ } -+ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { -+ return ensureMain(getStatusFutureUnchecked(chunkstatus)); -+ } -+ public CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -441,6 +570,7 @@ public class PlayerChunk { - return this.n; - } - -+ private void setPriority(int i) { d(i); } // Paper - OBFHELPER - private void d(int i) { - this.n = i; - } -@@ -459,7 +589,7 @@ public class PlayerChunk { - // CraftBukkit start - // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. - if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -524,12 +654,13 @@ public class PlayerChunk { - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk fullChunk = either.left().get(); - PlayerChunk.this.isFullChunkReady = true; - fullChunk.playerChunk = PlayerChunk.this; -+ this.chunkMap.chunkDistanceManager.clearPriorityTickets(location); - - - } -@@ -554,7 +685,7 @@ public class PlayerChunk { - - if (!flag4 && flag5) { - // Paper start - cache ticking ready status -- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk tickingChunk = either.left().get(); -@@ -585,7 +716,7 @@ public class PlayerChunk { - } - - // Paper start - cache ticking ready status -- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk entityTickingChunk = either.left().get(); -@@ -605,12 +736,29 @@ public class PlayerChunk { - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -- this.u.a(this.location, this::k, this.ticketLevel, this::d); -+ // Paper start - raise IO/load priority if priority changes, use our preferred priority -+ priorityBoost = chunkMap.chunkDistanceManager.getChunkPriority(location); -+ int priority = getDemandedPriority(); -+ if (getCurrentPriority() > priority) { -+ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ if (priority <= 10) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (priority <= 20) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ } -+ if (getCurrentPriority() != priority) { -+ this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -+ int neighborsPriority = getNeighborsPriority(); -+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); -+ } -+ // Paper end - this.oldTicketLevel = this.ticketLevel; - // CraftBukkit start - // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. - if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -692,6 +840,7 @@ public class PlayerChunk { - - public interface c { - -+ default void changePriority(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { a(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER - void a(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 6ddbc83a08be4e7aa5cd85cf78f14604d4759f30..5bea15ba1ee3d2c8e8d78ab34ba75723164b7117 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper - import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongIterator; -@@ -51,6 +52,7 @@ import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.SystemUtils; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -@@ -105,6 +107,7 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - import org.bukkit.entity.Player; // CraftBukkit -+import org.spigotmc.AsyncCatcher; - - public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - -@@ -142,6 +145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -+ final java.util.concurrent.Executor mainInvokingExecutor; // Paper - public final ChunkGenerator chunkGenerator; - private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; -@@ -179,6 +183,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void execute(Runnable runnable) { -+ AsyncCatcher.catchOp("Callback Executor execute"); - if (queued == null) { - queued = new java.util.ArrayDeque<>(); - } -@@ -187,6 +192,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void run() { -+ AsyncCatcher.catchOp("Callback Executor run"); - if (queued == null) { - return; - } -@@ -341,6 +347,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.world = worldserver; - this.chunkGenerator = chunkgenerator; - this.executor = iasynctaskhandler; -+ // Paper start -+ this.mainInvokingExecutor = (run) -> { -+ if (MCUtil.isMainThread()) { -+ run.run(); -+ } else { -+ iasynctaskhandler.execute(run); -+ } -+ }; -+ // Paper end - ThreadedMailbox threadedmailbox = ThreadedMailbox.a(executor, "worldgen"); - - iasynctaskhandler.getClass(); -@@ -435,6 +450,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ checkHighPriorityChunks(player); - if (newState.size() != 1) { - return; - } -@@ -453,7 +469,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); - PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -- }); -+ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos); -+ }, (player, prevPos, newPos) -> { -+ player.lastHighPriorityChecked = -1; // reset and recheck -+ checkHighPriorityChunks(player); -+ }); - this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -470,6 +490,115 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - // Paper end - no-tick view distance - } -+ // Paper start - Chunk Prioritization -+ public void queueHolderUpdate(PlayerChunk playerchunk) { -+ Runnable runnable = () -> { -+ if (isUnloading(playerchunk)) { -+ return; // unloaded -+ } -+ chunkDistanceManager.pendingChunkUpdates.add(playerchunk); -+ if (!chunkDistanceManager.pollingPendingChunkUpdates) { -+ world.getChunkProvider().tickDistanceManager(); -+ } -+ }; -+ if (MCUtil.isMainThread()) { -+ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... -+ runnable.run(); -+ } else { -+ executor.execute(runnable); -+ } -+ } -+ -+ private boolean isUnloading(PlayerChunk playerchunk) { -+ return playerchunk == null || unloadQueue.contains(playerchunk.location.pair()); -+ } -+ -+ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { -+ int prev = map.getOrDefault(chunk, -1); -+ if (level > prev) { -+ map.put(chunk, level); -+ } -+ } -+ -+ public void checkHighPriorityChunks(EntityPlayer player) { -+ int currentTick = MinecraftServer.currentTick; -+ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players -+ return; -+ } -+ player.lastHighPriorityChecked = currentTick; -+ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); -+ -+ int viewDistance = getEffectiveNoTickViewDistance(); -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ -+ // Prioritize circular near -+ double playerChunkX = MathHelper.floor(player.locX()) >> 4; -+ double playerChunkZ = MathHelper.floor(player.locZ()) >> 4; -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double twoThirdModifier = 2D / 3D; -+ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ // Prioritize immediate -+ if (dist <= 4) { -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (27 - dist)); -+ return; -+ } -+ -+ // Prioritize nearby chunks -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (20 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 3 -+ ChunkCoordIntPair front3 = player.getChunkInFront(3); -+ pos.setValues(front3.x << 4, 0, front3.z << 4); -+ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 5 -+ if (viewDistance > 4) { -+ ChunkCoordIntPair front5 = player.getChunkInFront(5); -+ pos.setValues(front5.x << 4, 0, front5.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ // Prioritize Frustum far 7 -+ if (viewDistance > 6) { -+ ChunkCoordIntPair front7 = player.getChunkInFront(7); -+ pos.setValues(front7.x << 4, 0, front7.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) { -+ return; -+ } -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ if (priorities.isEmpty()) return; -+ chunkDistanceManager.delayDistanceManagerTick = true; -+ priorities.long2IntEntrySet().fastForEach(entry -> chunkDistanceManager.markHighPriority(new ChunkCoordIntPair(entry.getLongKey()), entry.getIntValue())); -+ chunkDistanceManager.delayDistanceManagerTick = false; -+ world.getChunkProvider().tickDistanceManager(); -+ -+ } -+ -+ private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) { -+ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.pair()) == null) return true; -+ PlayerChunk chunk = getUpdatingChunk(coord.pair()); -+ return chunk != null && (chunk.isFullChunkReady()); -+ } -+ // Paper end - - public void updatePlayerMobTypeMap(Entity entity) { - if (!this.world.paperConfig.perPlayerMobSpawns) { -@@ -599,6 +728,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; - int k = chunkcoordintpair.z; -+ PlayerChunk requestingNeighbor = getUpdatingChunk(chunkcoordintpair.pair()); // Paper - - for (int l = -i; l <= i; ++l) { - for (int i1 = -i; i1 <= i; ++i1) { -@@ -617,6 +747,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1); - CompletableFuture> completablefuture = playerchunk.a(chunkstatus, this); -+ // Paper start -+ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { -+ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); -+ completablefuture.thenAccept(either -> { -+ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); -+ }); -+ } -+ // Paper end - - list.add(completablefuture); - } -@@ -1084,14 +1222,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - - CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair()); -+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; -+ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ -+ if (chunkPriority <= 10) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (chunkPriority <= 20) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; - if (chunkSaveFuture != null) { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); - } else { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority); - } -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority); - return ret; - // Paper end - } -@@ -1236,7 +1382,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - long i = playerchunk.i().pair(); - - playerchunk.getClass(); -- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getTicketLevel)); -+ mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent! - }); - } - -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index e06fe77f6ea05a93e95fce223bcfd0d16394f96f..90cbd12611b7b078f35f08f910453bcc02f6665b 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -8,6 +8,7 @@ public final class Ticket implements Comparable> { - private final int b; - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER -+ public int priority = 0; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -56,6 +57,7 @@ public final class Ticket implements Comparable> { - return this.b; - } - -+ public final void setCurrentTick(long i) { this.a(i); } // Paper - OBFHELPER - protected void a(long i) { - this.d = i; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 2c932d36f982e7f8713aabff9a6c631055810366..f5d18834e0e2ee0e3bcf55810456766d2f134450 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -28,6 +28,8 @@ public class TicketType { - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper -+ public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 6db70005ebc99b19185b8efca550a0783ea05cad..42190a8c6c2eadf05f57df50e3ca997384327b67 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1529,6 +1529,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.A = this.e; - this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66fcd68f0a0a21b113e8741cc42c841f49009118..b4c5915cc68a838259129b8973b3a6a39c1fc963 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -275,8 +275,8 @@ public abstract class PlayerList { - final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); - PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; - playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -- worldserver1.getChunkProvider().tickDistanceManager(); -- worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ worldserver1.getChunkProvider().markAreaHighPriority(pos, 28, 3); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { - PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); - if (updatingChunk != null) { - return updatingChunk.getEntityTickingFuture(); -@@ -696,6 +696,7 @@ public abstract class PlayerList { - SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); - - EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); -+ entity.isRealPlayer = true; // Paper - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -@@ -902,6 +903,7 @@ public abstract class PlayerList { - // CraftBukkit end - - worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper -+ entityplayer1.forceCheckHighPriority(); // Player - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 9a88791be443a5b18934e7d752aee6dcdb8aa38f..e41d63596c32eee5f0c04a6f043d576d8021ff1a 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -104,6 +104,7 @@ public class ChunkCoordIntPair { - return "[" + this.x + ", " + this.z + "]"; - } - -+ public final BlockPosition asPosition() { return l(); } // Paper - OBFHELPER - public BlockPosition l() { - return new BlockPosition(this.d(), 0, this.e()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 2d90ecf04f522a4e16f44c905450a61becaa1ed2..6034ef65ee6030948a5b76fa493addb44188ef62 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2541,6 +2541,10 @@ public class CraftWorld implements World { - return future; - } - -+ if (!urgent) { -+ // if not urgent, at least use a slightly boosted priority -+ world.getChunkProvider().markHighPriority(new ChunkCoordIntPair(x, z), 1); -+ } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 935b5668a81db4d19a08b09c61519114532a23d9..0f8d10c2bc7728b58528096fc0686c3aeee623a7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -60,6 +60,7 @@ import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -@@ -72,6 +73,7 @@ import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; -@@ -851,6 +853,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); - } - -+ // Paper start -+ @Override -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { -+ ((CraftWorld)loc.getWorld()).getHandle().getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(MathHelper.floor(loc.getX()) >> 4, MathHelper.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority -+ return super.teleportAsync(loc, cause); -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { - Preconditions.checkArgument(location != null, "location"); diff --git a/Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch deleted file mode 100644 index ee6a2dd544aa..000000000000 --- a/Spigot-Server-Patches/0485-Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 17:03:41 -0400 -Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) - -Instead of using the entire world or player list, use the distance -maps to only iterate players who are even seeing the chunk the packet -is originating from. - -This will drastically cut down on packet sending cost for worlds with -lots of players in them. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b4c5915cc68a838259129b8973b3a6a39c1fc963..4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1153,16 +1153,40 @@ public abstract class PlayerList { - } - - public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, ResourceKey resourcekey, Packet packet) { -- for (int i = 0; i < this.players.size(); ++i) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); -+ WorldServer world = null; -+ if (entityhuman != null && entityhuman.world instanceof WorldServer) { -+ world = (WorldServer) entityhuman.world; -+ } - -- // CraftBukkit start - Test if player receiving packet can see the source of the packet -- if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { -- continue; -+ // Paper start -+ if (world == null) { -+ world = server.getWorldServer(resourcekey); -+ } -+ PlayerChunkMap chunkMap = world != null ? world.getChunkProvider().playerChunkMap : null; -+ Object[] backingSet; -+ if (chunkMap == null) { -+ // Really shouldn't happen... -+ backingSet = world != null ? world.players.toArray() : players.toArray(); -+ } else { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); -+ if (nearbyPlayers == null) { -+ return; - } -+ backingSet = nearbyPlayers.getBackingSet(); -+ } -+ -+ for (Object object : backingSet) { -+ if (!(object instanceof EntityPlayer)) continue; -+ EntityPlayer entityplayer = (EntityPlayer) object; -+ // Paper end -+ -+ // CraftBukkit start - Test if player receiving packet can see the source of the packet -+ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper -+ //continue; // Paper -+ //} // Paper - // CraftBukkit end - -- if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey) { -+ if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey && (!(entityhuman instanceof EntityPlayer) || entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity()))) { // Paper - double d4 = d0 - entityplayer.locX(); - double d5 = d1 - entityplayer.locY(); - double d6 = d2 - entityplayer.locZ(); diff --git a/Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch b/Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch deleted file mode 100644 index 969bc53a1c41..000000000000 --- a/Spigot-Server-Patches/0486-Improve-Chunk-Status-Transition-Speed.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 23:32:14 -0400 -Subject: [PATCH] Improve Chunk Status Transition Speed - -When a chunk is loaded from disk that has already been generated, -the server has to promote the chunk through the system to reach -it's current desired status level. - -This results in every single status transition going from the main thread -to the world gen threads, only to discover it has no work it actually -needs to do.... and then it returns back to main. - -This back and forth costs a lot of time and can really delay chunk loads -when the server is under high TPS due to their being a lot of time in -between chunk load times, as well as hogs up the chunk threads from doing -actual generation and light work. - -Additionally, the whole task system uses a lot of CPU on the server threads anyways. - -So by optimizing status transitions for status's that are already complete, -we can run them to the desired level while on main thread (where it has -to happen anyways) instead of ever jumping to world gen thread. - -This will improve chunk loading effeciency to be reduced down to the following -scenario / path: - -1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue -2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread -3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue -4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) -5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task -6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done -7) MAIN: Task returns to main, finish processing to FULL/TICKING status - -Previously would have hopped to SERVER around 12+ times there extra. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index fc79a73c884ceb7e0ce56443c36b135c4e525193..88022e3ccd04f9c041ced68be66a95247c1017e9 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -84,6 +84,13 @@ public class PlayerChunk { - this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); - } - // Paper end - optimise isOutsideOfRange -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ public boolean canAdvanceStatus() { -+ ChunkStatus status = getChunkHolderStatus(); -+ IChunkAccess chunk = getAvailableChunkNow(); -+ return chunk != null && (status == null || chunk.getChunkStatus().isAtLeastStatus(getNextStatus(status))); -+ } -+ // Paper end - - // Paper start - no-tick view distance - public final Chunk getSendingChunk() { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 5bea15ba1ee3d2c8e8d78ab34ba75723164b7117..74146ab6bd172807fb8545c1a29e376b1224e34d 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -795,7 +795,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return either.mapLeft((list) -> { - return (Chunk) list.get(list.size() / 2); - }); -- }, this.executor); -+ }, this.mainInvokingExecutor); // Paper - } - - @Nullable -@@ -1145,7 +1145,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - IChunkAccess ichunkaccess = (IChunkAccess) optional.get(); - - if (ichunkaccess.getChunkStatus().b(chunkstatus)) { -- CompletableFuture completablefuture1; -+ CompletableFuture> completablefuture1; // Paper - - if (chunkstatus == ChunkStatus.LIGHT) { - completablefuture1 = this.b(playerchunk, chunkstatus); -@@ -1161,7 +1161,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return this.b(playerchunk, chunkstatus); - } - } -- }, this.executor); -+ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main - } - } - -@@ -1282,6 +1282,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); - }); - }, (runnable) -> { -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ if (playerchunk.canAdvanceStatus()) { -+ this.mainInvokingExecutor.execute(runnable); -+ return; -+ } -+ // Paper end - this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); - }); - } diff --git a/Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch b/Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch deleted file mode 100644 index b6b2585f20e9..000000000000 --- a/Spigot-Server-Patches/0487-Fix-villager-trading-demand-MC-163962.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 5 Jun 2020 20:02:04 -0500 -Subject: [PATCH] Fix villager trading demand - MC-163962 - -Prevent demand from going negative and tending to negative infinity - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index d840c657a6a992c86364a5f4536da0b217515c53..9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -109,7 +109,7 @@ public class MerchantRecipe { - } - - public void e() { -- this.demand = this.demand + this.uses - (this.maxUses - this.uses); -+ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - } - - public ItemStack f() { diff --git a/Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch b/Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch deleted file mode 100644 index 28c169e754be..000000000000 --- a/Spigot-Server-Patches/0488-Maps-shouldn-t-load-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sun, 7 Jun 2020 21:43:42 +0100 -Subject: [PATCH] Maps shouldn't load chunks - -Previously maps would load all chunks in a certain radius depending on - their scale when trying to update their content. This would result in - main thread chunk loads when they weren't really necessary, especially - on low view distances or "slow" async chunk loads after teleports or - other prioritisation. - - This changes it to only try to render already loaded chunks based on - the assumption that the chunks around the player will get loaded - eventually anyways and that maps will get checked for update every - five ticks that movement occur in anyways. - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index b18149cf048e78fefc019b50ed8f20ff8b609f5c..a1945e9ac1dd8961c5758a22bef3908d3adf0704 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -120,9 +120,9 @@ public class ItemWorldMap extends ItemWorldMapBase { - int k2 = (j / i + k1 - 64) * i; - int l2 = (k / i + l1 - 64) * i; - Multiset multiset = LinkedHashMultiset.create(); -- Chunk chunk = world.getChunkAtWorldCoords(new BlockPosition(k2, 0, l2)); -+ Chunk chunk = world.getChunkIfLoaded(new BlockPosition(k2, 0, l2)); // Paper - Maps shouldn't load chunks - -- if (!chunk.isEmpty()) { -+ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - int i3 = k2 & 15; - int j3 = l2 & 15; diff --git a/Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch deleted file mode 100644 index e62a5c265fe5..000000000000 --- a/Spigot-Server-Patches/0489-Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 7 Jun 2020 19:25:13 -0400 -Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from - carto/sunken maps - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 795c4a9e3e33660af888ff80204bfd47a3b327fd..5401db70b4516ab960cffae0aae9b3ea297288b5 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -421,8 +421,8 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setThundering(flag1); - } - -- @Override -- public BiomeBase a(int i, int j, int k) { -+ public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER -+ @Override public BiomeBase a(int i, int j, int k) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().getBiome(i, j, k); - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index a1945e9ac1dd8961c5758a22bef3908d3adf0704..3aa0f19d4a924d40005a38bb95a08d4a109c5b2e 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -253,7 +253,7 @@ public class ItemWorldMap extends ItemWorldMapBase { - - for (l = 0; l < 128 * i; ++l) { - for (i1 = 0; i1 < 128 * i; ++i1) { -- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPosition((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); -+ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper - } - } - diff --git a/Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch b/Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch deleted file mode 100644 index 3e547b0e8945..000000000000 --- a/Spigot-Server-Patches/0490-Optimize-Bit-Operations-by-inlining.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 02:24:49 -0400 -Subject: [PATCH] Optimize Bit Operations by inlining - -Inline bit operations and reduce instruction count to make these hot -operations faster - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 1fb931d4c0720a5e496030e25c865771aea3ec70..eb67af795dd716d9f92ac32843accc1ec4efd647 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -31,14 +31,16 @@ public class BlockPosition extends BaseBlockPosition { - }).stable(); - private static final Logger LOGGER = LogManager.getLogger(); - public static final BlockPosition ZERO = new BlockPosition(0, 0, 0); -- private static final int f = 1 + MathHelper.f(MathHelper.c(30000000)); -- private static final int g = BlockPosition.f; -- private static final int h = 64 - BlockPosition.f - BlockPosition.g; -- private static final long i = (1L << BlockPosition.f) - 1L; -- private static final long j = (1L << BlockPosition.h) - 1L; -- private static final long k = (1L << BlockPosition.g) - 1L; -- private static final int l = BlockPosition.h; -- private static final int m = BlockPosition.h + BlockPosition.g; -+ // Paper start - static constants -+ private static final int f = 26; -+ private static final int g = 26; -+ private static final int h = 12; -+ private static final long i = 67108863; -+ private static final long j = 4095; -+ private static final long k = 67108863; -+ private static final int l = 12; -+ private static final int m = 38; -+ // Paper end - - public BlockPosition(int i, int j, int k) { - super(i, j, k); -@@ -60,28 +62,29 @@ public class BlockPosition extends BaseBlockPosition { - this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public static long getAdjacent(int baseX, int baseY, int baseZ, EnumDirection enumdirection) { return asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); } // Paper - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - - public static long a(long i, int j, int k, int l) { -- return a(b(i) + j, c(i) + k, d(i) + l); -+ return a((int) (i >> 38) + j, (int) ((i << 52) >> 52) + k, (int) ((i << 26) >> 38) + l); // Paper - simplify/inline - } - - public static int b(long i) { -- return (int) (i << 64 - BlockPosition.m - BlockPosition.f >> 64 - BlockPosition.f); -+ return (int) (i >> 38); // Paper - simplify/inline - } - - public static int c(long i) { -- return (int) (i << 64 - BlockPosition.h >> 64 - BlockPosition.h); -+ return (int) ((i << 52) >> 52); // Paper - simplify/inline - } - - public static int d(long i) { -- return (int) (i << 64 - BlockPosition.l - BlockPosition.g >> 64 - BlockPosition.g); -+ return (int) ((i << 26) >> 38); // Paper - simplify/inline - } - - public static BlockPosition fromLong(long i) { -- return new BlockPosition(b(i), c(i), d(i)); -+ return new BlockPosition((int) (i >> 38), (int) ((i << 52) >> 52), (int) ((i << 26) >> 38)); // Paper - simplify/inline - } - - public long asLong() { -@@ -90,12 +93,7 @@ public class BlockPosition extends BaseBlockPosition { - - public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & BlockPosition.i) << BlockPosition.m; -- l |= ((long) j & BlockPosition.j) << 0; -- l |= ((long) k & BlockPosition.k) << BlockPosition.l; -- return l; -+ return (((long) i & (long) 67108863) << 38) | (((long) j & (long) 4095)) | (((long) k & (long) 67108863) << 12); // Paper - inline constants and simplify - } - - public static long f(long i) { -diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java -index 97126ae5a43bb7acb04a1ab14fb7f364c8c2675f..7d9a16eb81288b74425319c60525f57c98ad3b69 100644 ---- a/src/main/java/net/minecraft/core/SectionPosition.java -+++ b/src/main/java/net/minecraft/core/SectionPosition.java -@@ -19,7 +19,7 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(BlockPosition blockposition) { -- return new SectionPosition(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ())); -+ return new SectionPosition(blockposition.getX() >> 4, blockposition.getY() >> 4, blockposition.getZ() >> 4); // Paper - } - - public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) { -@@ -31,15 +31,23 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(long i) { -- return new SectionPosition(b(i), c(i), d(i)); -+ return new SectionPosition((int) (i >> 42), (int) (i << 44 >> 44), (int) (i << 22 >> 42)); // Paper - } - - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - -+ // Paper start -+ public static long getAdjacentFromBlockPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) ((x >> 4) + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ public static long getAdjacentFromSectionPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) (x + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) (z + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ // Paper end - public static long a(long i, int j, int k, int l) { -- return b(b(i) + j, c(i) + k, d(i) + l); -+ return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static int a(int i) { -@@ -51,11 +59,7 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static short b(BlockPosition blockposition) { -- int i = b(blockposition.getX()); -- int j = b(blockposition.getY()); -- int k = b(blockposition.getZ()); -- -- return (short) (i << 8 | k << 4 | j << 0); -+ return (short) ((blockposition.getX() & 15) << 8 | (blockposition.getZ() & 15) << 4 | blockposition.getY() & 15); // Paper - simplify/inline - } - - public static int a(short short0) { -@@ -114,16 +118,16 @@ public class SectionPosition extends BaseBlockPosition { - return this.getZ(); - } - -- public int d() { -- return this.a() << 4; -+ public final int d() { // Paper -+ return this.getX() << 4; // Paper - } - -- public int e() { -- return this.b() << 4; -+ public final int e() { // Paper -+ return this.getY() << 4; // Paper - } - -- public int f() { -- return this.c() << 4; -+ public final int f() { // Paper -+ return this.getZ() << 4; // Paper - } - - public int g() { -@@ -138,8 +142,10 @@ public class SectionPosition extends BaseBlockPosition { - return (this.c() << 4) + 15; - } - -+ public static long blockToSection(long i) { return e(i); } // Paper - OBFHELPER - public static long e(long i) { -- return b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ return (((long) (int) (i >> 42) & 4194303L) << 42) | (((long) (int) ((i << 52) >> 56) & 1048575L)) | (((long) (int) ((i << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static long f(long i) { -@@ -160,17 +166,18 @@ public class SectionPosition extends BaseBlockPosition { - return new ChunkCoordIntPair(this.a(), this.c()); - } - -+ // Paper start -+ public static long blockPosAsSectionLong(int i, int j, int k) { -+ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); -+ } -+ // Paper end -+ public static long asLong(int i, int j, int k) { return b(i, j, k); } // Paper - OBFHELPER - public static long b(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & 4194303L) << 42; -- l |= ((long) j & 1048575L) << 0; -- l |= ((long) k & 4194303L) << 20; -- return l; -+ return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public long s() { -- return b(this.a(), this.b(), this.c()); -+ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public Stream t() { -@@ -178,18 +185,11 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static Stream a(SectionPosition sectionposition, int i) { -- int j = sectionposition.a(); -- int k = sectionposition.b(); -- int l = sectionposition.c(); -- -- return a(j - i, k - i, l - i, j + i, k + i, l + i); -+ return a(sectionposition.getX() - i, sectionposition.getY() - i, sectionposition.getZ() - i, sectionposition.getX() + i, sectionposition.getY() + i, sectionposition.getZ() + i); // Paper - simplify/inline - } - - public static Stream b(ChunkCoordIntPair chunkcoordintpair, int i) { -- int j = chunkcoordintpair.x; -- int k = chunkcoordintpair.z; -- -- return a(j - i, 0, k - i, j + i, 15, k + i); -+ return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline - } - - public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { diff --git a/Spigot-Server-Patches/0491-Optimize-Light-Engine.patch b/Spigot-Server-Patches/0491-Optimize-Light-Engine.patch deleted file mode 100644 index 58ff4e06013a..000000000000 --- a/Spigot-Server-Patches/0491-Optimize-Light-Engine.patch +++ /dev/null @@ -1,1433 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 22:43:29 -0400 -Subject: [PATCH] Optimize Light Engine - -Massive update to light to improve performance and chunk loading/generation. - -1) Massive bit packing/unpacking optimizations and inlining. - A lot of performance has to do with constant packing and unpacking of bits. - We now inline a most bit operations, and re-use base x/y/z bits in many places. - This helps with cpu level processing to just do all the math at once instead - of having to jump in and out of function calls. - - This much logic also is likely over the JVM Inline limit for JIT too. -2) Applied a few of JellySquid's Phosphor mod optimizations such as - - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified - - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. -3) Optimize hot path accesses to getting updating chunk to have less branching -4) Optimize getBlock accesses to have less branching, and less unpacking -5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. -6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full - of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. - this applies for both urgent and non urgent tasks. -7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. -8) Fix NPE risk that crashes server in getting nibble data - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 19e02d12bb0c5a73066f7c57da40277918276210..326c52f9f2cc729fd52162aeae18ec9dae3a4eaf 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -1070,7 +1070,7 @@ public class ChunkProviderServer extends IChunkProvider { - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { -- ChunkProviderServer.this.lightEngine.queueUpdate(); -+ ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - not needed - return super.executeNext() || execChunkTask; // Paper - } - } finally { -diff --git a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -index c8bb040e7ed848877ec9c2f9b30dcda137cadf35..4ee7070364a8989eece4fa4237b529926821f9c9 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -@@ -16,14 +16,20 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - - @Override - protected void a(long i, int j, boolean flag) { -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int k = -1; k <= 1; ++k) { - for (int l = -1; l <= 1; ++l) { - for (int i1 = -1; i1 <= 1; ++i1) { -- long j1 = SectionPosition.a(i, k, l, i1); -+ if (k == 0 && l == 0 && i1 == 0) continue; // Paper -+ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper - -- if (j1 != i) { -+ //if (j1 != i) { // Paper - checked above - this.b(i, j1, j, flag); -- } -+ //} // Paper - } - } - } -@@ -34,10 +40,15 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - protected int a(long i, long j, int k) { - int l = k; - -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int i1 = -1; i1 <= 1; ++i1) { - for (int j1 = -1; j1 <= 1; ++j1) { - for (int k1 = -1; k1 <= 1; ++k1) { -- long l1 = SectionPosition.a(i, i1, j1, k1); -+ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper - - if (l1 == i) { - l1 = Long.MAX_VALUE; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index e066848127cb9a42e8c39422691cc65132cac6bb..0b80569648c1df01aab52d0b8d47028cda925d86 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -1,6 +1,7 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper - import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import it.unimi.dsi.fastutil.objects.ObjectList; - import it.unimi.dsi.fastutil.objects.ObjectListIterator; -@@ -16,6 +17,7 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -27,15 +29,149 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ThreadedMailbox b; -- private final ObjectList> c = new ObjectArrayList(); -- private final PlayerChunkMap d; -+ // Paper start -+ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2; -+ -+ private boolean isChunkLightStatus(long pair) { -+ PlayerChunk playerChunk = playerChunkMap.getVisibleChunk(pair); -+ if (playerChunk == null) { -+ return false; -+ } -+ ChunkStatus status = PlayerChunk.getChunkStatus(playerChunk.getTicketLevel()); -+ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); -+ } -+ -+ static class ChunkLightQueue { -+ public boolean shouldFastUpdate; -+ java.util.ArrayDeque pre = new java.util.ArrayDeque(); -+ java.util.ArrayDeque post = new java.util.ArrayDeque(); -+ -+ ChunkLightQueue(long chunk) {} -+ } -+ -+ static class PendingLightTask { -+ long chunkId; -+ IntSupplier priority; -+ Runnable pre; -+ Runnable post; -+ boolean fastUpdate; -+ -+ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { -+ this.chunkId = chunkId; -+ this.priority = priority; -+ this.pre = pre; -+ this.post = post; -+ this.fastUpdate = fastUpdate; -+ } -+ } -+ -+ -+ // Retain the chunks priority level for queued light tasks -+ class LightQueue { -+ private int size = 0; -+ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; -+ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ -+ private LightQueue() { -+ for (int i = 0; i < buckets.length; i++) { -+ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ } -+ -+ public void changePriority(long pair, int currentPriority, int priority) { -+ this.priorityChanges.add(() -> { -+ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); -+ if (remove != null) { -+ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); -+ if (existing != null) { -+ remove.pre.addAll(existing.pre); -+ remove.post.addAll(existing.post); -+ } -+ } -+ }); -+ } -+ -+ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); -+ queueUpdate(); -+ } -+ -+ public final void add(long chunkId, IntSupplier priority, LightEngineThreaded.Update type, Runnable run) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, type == Update.PRE_UPDATE ? run : null, type == Update.POST_UPDATE ? run : null, false)); -+ } -+ public final void add(PendingLightTask update) { -+ int priority = update.priority.getAsInt(); -+ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); -+ -+ if (update.pre != null) { -+ this.size++; -+ lightQueue.pre.add(update.pre); -+ } -+ if (update.post != null) { -+ this.size++; -+ lightQueue.post.add(update.post); -+ } -+ if (update.fastUpdate) { -+ lightQueue.shouldFastUpdate = true; -+ } -+ } -+ -+ public final boolean isEmpty() { -+ return this.size == 0 && this.pendingTasks.isEmpty(); -+ } -+ -+ public final int size() { -+ return this.size; -+ } -+ -+ public boolean poll(java.util.List pre, java.util.List post) { -+ PendingLightTask pending; -+ while ((pending = pendingTasks.poll()) != null) { -+ add(pending); -+ } -+ Runnable run; -+ while ((run = priorityChanges.poll()) != null) { -+ run.run(); -+ } -+ boolean hasWork = false; -+ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; -+ int priority = 0; -+ while (priority < MAX_PRIORITIES && !isEmpty()) { -+ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; -+ if (bucket.isEmpty()) { -+ priority++; -+ if (hasWork) { -+ return true; -+ } else { -+ continue; -+ } -+ } -+ ChunkLightQueue queue = bucket.removeFirst(); -+ this.size -= queue.pre.size() + queue.post.size(); -+ pre.addAll(queue.pre); -+ post.addAll(queue.post); -+ queue.pre.clear(); -+ queue.post.clear(); -+ hasWork = true; -+ if (queue.shouldFastUpdate) { -+ return true; -+ } -+ } -+ return hasWork; -+ } -+ } -+ -+ final LightQueue queue = new LightQueue(); -+ // Paper end -+ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper - private final Mailbox> e; - private volatile int f = 5; - private final AtomicBoolean g = new AtomicBoolean(); - - public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox threadedmailbox, Mailbox> mailbox) { - super(ilightaccess, true, flag); -- this.d = playerchunkmap; -+ this.d = playerchunkmap; this.playerChunkMap = d; // Paper - this.e = mailbox; - this.b = threadedmailbox; - } -@@ -122,13 +258,9 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - } - - private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { -- this.e.a(ChunkTaskQueueSorter.a(() -> { -- this.c.add(Pair.of(lightenginethreaded_update, runnable)); -- if (this.c.size() >= this.f) { -- this.b(); -- } -- -- }, ChunkCoordIntPair.pair(i, j), intsupplier)); -+ // Paper start - replace method -+ this.queue.add(ChunkCoordIntPair.pair(i, j), intsupplier, lightenginethreaded_update, runnable); -+ // Paper end - } - - @Override -@@ -145,8 +277,19 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - public CompletableFuture a(IChunkAccess ichunkaccess, boolean flag) { - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - -- ichunkaccess.b(false); -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -+ // Paper start -+ //ichunkaccess.b(false); // Don't need to disable this -+ long pair = chunkcoordintpair.pair(); -+ CompletableFuture future = new CompletableFuture<>(); -+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); -+ boolean[] skippedPre = {false}; -+ this.queue.addChunk(pair, prioritySupplier, SystemUtils.a(() -> { -+ if (!isChunkLightStatus(pair)) { -+ future.complete(ichunkaccess); -+ skippedPre[0] = true; -+ return; -+ } -+ // Paper end - ChunkSection[] achunksection = ichunkaccess.getSections(); - - for (int i = 0; i < 16; ++i) { -@@ -164,55 +307,48 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - }); - } - -- this.d.c(chunkcoordintpair); -+ // this.d.c(chunkcoordintpair); // Paper - move into post task below - }, () -> { - return "lightChunk " + chunkcoordintpair + " " + flag; -- })); -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - merge the 2 together -+ }), () -> { -+ this.d.c(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done -+ if (skippedPre[0]) return; // Paper - future's already complete - ichunkaccess.b(true); - super.b(chunkcoordintpair, false); -- return ichunkaccess; -- }, (runnable) -> { -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); -+ // Paper start -+ future.complete(ichunkaccess); - }); -+ return future; -+ // Paper end - } - - public void queueUpdate() { -- if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -+ if ((!this.queue.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { // Paper - this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); -+ queueUpdate(); // Paper - if we still have work to do, do it! - })); - } - - } - -+ // Paper start - replace impl -+ private final java.util.List pre = new java.util.ArrayList<>(); -+ private final java.util.List post = new java.util.ArrayList<>(); - private void b() { -- int i = Math.min(this.c.size(), this.f); -- ObjectListIterator> objectlistiterator = this.c.iterator(); -- -- Pair pair; -- int j; -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -+ if (queue.poll(pre, post)) { -+ pre.forEach(Runnable::run); -+ pre.clear(); -+ super.a(Integer.MAX_VALUE, true, true); -+ post.forEach(Runnable::run); -+ post.clear(); -+ } else { -+ // might have level updates to go still -+ super.a(Integer.MAX_VALUE, true, true); - } -- -- objectlistiterator.back(j); -- super.a(Integer.MAX_VALUE, true, true); -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -- -- objectlistiterator.remove(); -- } -- -+ // Paper end - } - - public void a(int i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 88022e3ccd04f9c041ced68be66a95247c1017e9..d6a5a0b17308913a5efd97cd27fabd0825ef68c6 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -754,6 +754,7 @@ public class PlayerChunk { - ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; - } - chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ chunkMap.world.getChunkProvider().getLightEngine().queue.changePriority(location.pair(), getCurrentPriority(), priority); - } - if (getCurrentPriority() != priority) { - this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 74146ab6bd172807fb8545c1a29e376b1224e34d..169fa174f86f8a8dc42d3b9c4954a39d0a738c06 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -99,6 +99,7 @@ import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -+import net.minecraft.world.level.storage.WorldDataServer; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper -@@ -331,6 +332,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ private final java.util.concurrent.ExecutorService lightThread; - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning -@@ -362,7 +364,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper -+ // Paper start - use light thread -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { -+ Thread thread = new Thread(r); -+ thread.setName(((WorldDataServer)world.getWorldData()).getName() + " - Light"); -+ thread.setDaemon(true); -+ thread.setPriority(Thread.NORM_PRIORITY+1); -+ return thread; -+ }), "light"); -+ // Paper end - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); -@@ -708,6 +718,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - } - -+ protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER - protected IntSupplier c(long i) { - return () -> { - PlayerChunk playerchunk = this.getVisibleChunk(i); -@@ -835,6 +846,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - @Override - public void close() throws IOException { - try { -+ this.lightThread.shutdown(); // Paper - this.p.close(); - this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); -diff --git a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -index 2efca1fe92b2e93dcbf5337eea8855b1b2b9a564..72bfda620f073fd3c3e4c43d78583386dadf95e6 100644 ---- a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -@@ -110,7 +110,8 @@ public class ThreadedMailbox implements Mailbox, AutoCloseable, Runnable { - - } - -- @Override -+ -+ public final void queue(T t0) { a(t0); } @Override // Paper - OBFHELPER - public void a(T t0) { - this.a.a(t0); - this.f(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index b82420e9a5d42a4383d24921614fe613c640edb9..0fec15e141051863dbf51a2b3e1ace5028cd2fc1 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -11,6 +11,13 @@ import net.minecraft.server.MCUtil; - public class NibbleArray { - - // Paper start -+ public static final NibbleArray EMPTY_NIBBLE_ARRAY = new NibbleArray() { -+ @Override -+ public byte[] asBytes() { -+ throw new IllegalStateException(); -+ } -+ }; -+ public long lightCacheKey = Long.MIN_VALUE; - public static byte[] EMPTY_NIBBLE = new byte[2048]; - private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); - private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index f6198069e3ca421b4f551939263c7cf8bd5b754e..29e98864209c51368a91fa9e530c33cbf9830b51 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -23,9 +23,11 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int k = (int) ((i << 52) >> 52); -+ int l = (int) ((i << 26) >> 38); -+ // Paper end - IBlockAccess iblockaccess = this.a.c(j >> 4, l >> 4); - - return iblockaccess != null ? iblockaccess.g(this.f.d(j, k, l)) : 0; -@@ -40,25 +42,33 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { - return k; - } else { -- int l = Integer.signum(BlockPosition.b(j) - BlockPosition.b(i)); -- int i1 = Integer.signum(BlockPosition.c(j) - BlockPosition.c(i)); -- int j1 = Integer.signum(BlockPosition.d(j) - BlockPosition.d(i)); -+ // Paper start - reuse math - credit to JellySquid for idea -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ int l = Integer.signum(jx - ix); -+ int i1 = Integer.signum(jy - iy); -+ int j1 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection = EnumDirection.a(l, i1, j1); - - if (enumdirection == null) { - return 15; - } else { - //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded -- IBlockData iblockdata = this.a(j, mutableint); -- -- if (mutableint.getValue() >= 15) { -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper -+ int blockedLight = mutableint.getValue(); // Paper -+ if (blockedLight >= 15) { // Paper - return 15; - } else { -- IBlockData iblockdata1 = this.a(i, (MutableInt) null); -+ IBlockData iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper - VoxelShape voxelshape = this.a(iblockdata1, i, enumdirection); - VoxelShape voxelshape1 = this.a(iblockdata, j, enumdirection.opposite()); - -- return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, mutableint.getValue()); -+ return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -66,14 +76,19 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int l = aenumdirection.length; - - for (int i1 = 0; i1 < l; ++i1) { - EnumDirection enumdirection = aenumdirection[i1]; -- long j1 = BlockPosition.a(i, enumdirection); -- long k1 = SectionPosition.e(j1); -+ long j1 = BlockPosition.getAdjacent(x, y, z, enumdirection); // Paper -+ long k1 = SectionPosition.blockToSection(j1); // Paper - - if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) { - this.b(i, j1, j, flag); -@@ -98,27 +113,37 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); - - if (i2 != j) { -- long j2 = SectionPosition.e(i2); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageBlock) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageBlock) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -index 944a8c295ff9df0d96800ddc4f6763598cf61d0d..64dad8ed7c16011d9cb3e9d22ac6f892c638e3b2 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -@@ -10,6 +10,7 @@ import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -23,10 +24,37 @@ public abstract class LightEngineLayer, S e - protected final EnumSkyBlock b; - protected final S c; - private boolean f; -- protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); -+ protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); protected final BlockPosition.MutableBlockPosition pos = d; // Paper - private final long[] g = new long[2]; -- private final IBlockAccess[] h = new IBlockAccess[2]; -+ private final IChunkAccess[] h = new IChunkAccess[2]; // Paper - -+ // Paper start - see fully commented out method below (look for Bedrock) -+ // optimized method with less branching for when scenarios arent needed. -+ // avoid using mutable version if can -+ protected final IBlockData getBlockOptimized(int x, int y, int z, MutableInt mutableint) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ mutableint.setValue(16); -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ this.pos.setValues(x, y, z); -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ mutableint.setValue(iblockdata.b(this.a.getWorld(), this.pos)); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ protected final IBlockData getBlockOptimized(int x, int y, int z) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ // Paper end - public LightEngineLayer(ILightAccess ilightaccess, EnumSkyBlock enumskyblock, S s0) { - super(16, 256, 8192); - this.a = ilightaccess; -@@ -45,7 +73,7 @@ public abstract class LightEngineLayer, S e - } - - @Nullable -- private IBlockAccess a(int i, int j) { -+ private IChunkAccess a(int i, int j) { // Paper - long k = ChunkCoordIntPair.pair(i, j); - - for (int l = 0; l < 2; ++l) { -@@ -54,7 +82,7 @@ public abstract class LightEngineLayer, S e - } - } - -- IBlockAccess iblockaccess = this.a.c(i, j); -+ IChunkAccess iblockaccess = (IChunkAccess) this.a.c(i, j); // Paper - - for (int i1 = 1; i1 > 0; --i1) { - this.g[i1] = this.g[i1 - 1]; -@@ -71,37 +99,39 @@ public abstract class LightEngineLayer, S e - Arrays.fill(this.h, (Object) null); - } - -- protected IBlockData a(long i, @Nullable MutableInt mutableint) { -- if (i == Long.MAX_VALUE) { -- if (mutableint != null) { -- mutableint.setValue(0); -- } -- -- return Blocks.AIR.getBlockData(); -- } else { -- int j = SectionPosition.a(BlockPosition.b(i)); -- int k = SectionPosition.a(BlockPosition.d(i)); -- IBlockAccess iblockaccess = this.a(j, k); -- -- if (iblockaccess == null) { -- if (mutableint != null) { -- mutableint.setValue(16); -- } -- -- return Blocks.BEDROCK.getBlockData(); -- } else { -- this.d.g(i); -- IBlockData iblockdata = iblockaccess.getType(this.d); -- boolean flag = iblockdata.l() && iblockdata.e(); -- -- if (mutableint != null) { -- mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -- } -- -- return flag ? iblockdata : Blocks.AIR.getBlockData(); -- } -- } -- } -+ // Paper start - comment out, see getBlockOptimized -+// protected IBlockData a(long i, @Nullable MutableInt mutableint) { -+// if (i == Long.MAX_VALUE) { -+// if (mutableint != null) { -+// mutableint.setValue(0); -+// } -+// -+// return Blocks.AIR.getBlockData(); -+// } else { -+// int j = SectionPosition.a(BlockPosition.b(i)); -+// int k = SectionPosition.a(BlockPosition.d(i)); -+// IBlockAccess iblockaccess = this.a(j, k); -+// -+// if (iblockaccess == null) { -+// if (mutableint != null) { -+// mutableint.setValue(16); -+// } -+// -+// return Blocks.BEDROCK.getBlockData(); -+// } else { -+// this.d.g(i); -+// IBlockData iblockdata = iblockaccess.getType(this.d); -+// boolean flag = iblockdata.l() && iblockdata.e(); -+// -+// if (mutableint != null) { -+// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -+// } -+// -+// return flag ? iblockdata : Blocks.AIR.getBlockData(); -+// } -+// } -+// } -+ // Paper end - - protected VoxelShape a(IBlockData iblockdata, long i, EnumDirection enumdirection) { - return iblockdata.l() ? iblockdata.a(this.a.getWorld(), this.d.g(i), enumdirection) : VoxelShapes.a(); -@@ -136,8 +166,9 @@ public abstract class LightEngineLayer, S e - return i == Long.MAX_VALUE ? 0 : 15 - this.c.i(i); - } - -+ protected int getNibbleLightInverse(NibbleArray nibblearray, int x, int y, int z) { return 15 - nibblearray.a(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below - protected int a(NibbleArray nibblearray, long i) { -- return 15 - nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return 15 - nibblearray.a((int) (i >> 38) & 15, (int) ((i << 52) >> 52) & 15, (int) ((i << 26) >> 38) & 15); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 37fa5faea6e2972e3eb8a3cbd1913ef38dc9456f..9cd2dfbfa216fdc58297fd25066d31bb92e13ec2 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.SectionPosition; - import net.minecraft.world.level.EnumSkyBlock; -+import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -38,21 +39,25 @@ public final class LightEngineSky extends LightEngineLayer= 15) { -+ // Paper start - use x/y/z and optimized block lookup -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); -+ int blockedLight = mutableint.getValue(); -+ if (blockedLight >= 15) { -+ // Paper end - return 15; - } else { -- int l = BlockPosition.b(i); -- int i1 = BlockPosition.c(i); -- int j1 = BlockPosition.d(i); -- int k1 = BlockPosition.b(j); -- int l1 = BlockPosition.c(j); -- int i2 = BlockPosition.d(j); -- boolean flag = l == k1 && j1 == i2; -- int j2 = Integer.signum(k1 - l); -- int k2 = Integer.signum(l1 - i1); -- int l2 = Integer.signum(i2 - j1); -+ // Paper start - inline math -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ boolean flag = ix == jx && iz == jz; -+ int j2 = Integer.signum(jx - ix); -+ int k2 = Integer.signum(jy - iy); -+ int l2 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection; - - if (i == Long.MAX_VALUE) { -@@ -61,7 +66,7 @@ public final class LightEngineSky extends LightEngineLayer l1; -+ boolean flag1 = i == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy - -- return flag1 && k == 0 && mutableint.getValue() == 0 ? 0 : k + Math.max(1, mutableint.getValue()); -+ return flag1 && k == 0 && blockedLight == 0 ? 0 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -101,10 +106,14 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ int i1 = baseY & 15; -+ int j1 = baseY >> 4; -+ // Paper end - int k1; - - if (i1 != 0) { -@@ -119,15 +128,16 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineSky.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -- long j2 = SectionPosition.e(i2); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageSky) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageSky) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { - if (i2 != j) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -@@ -215,7 +235,7 @@ public final class LightEngineSky extends LightEngineLayer> e - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); - protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -- protected final M f; // Paper - diff on change, should be "updating" -+ protected final M f; protected final M updating; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); -- protected final LongSet h = new LongOpenHashSet(); -+ protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); - private final LongSet n = new LongOpenHashSet(); - private final LongSet o = new LongOpenHashSet(); -@@ -37,33 +37,33 @@ public abstract class LightEngineStorage> e - protected volatile boolean j; - - protected LightEngineStorage(EnumSkyBlock enumskyblock, ILightAccess ilightaccess, M m0) { -- super(3, 16, 256); -+ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) - this.l = enumskyblock; - this.m = ilightaccess; -- this.f = m0; -+ this.f = m0; updating = m0; // Paper - this.e_visible = m0.b(); // Paper - avoid copying light data - this.e_visible.d(); // Paper - avoid copying light data - } - -- protected boolean g(long i) { -- return this.a(i, true) != null; -+ protected final boolean g(long i) { // Paper - final to help inlining -+ return this.updating.getUpdatingOptimized(i) != null; // Paper - inline to avoid branching - } - - @Nullable - protected NibbleArray a(long i, boolean flag) { - // Paper start - avoid copying light data - if (flag) { -- return this.a(this.f, i); -+ return this.updating.getUpdatingOptimized(i); - } else { - synchronized (this.visibleUpdateLock) { -- return this.a(this.e_visible, i); -+ return this.e_visible.lookup.apply(i); - } - } - // Paper end - avoid copying light data - } - - @Nullable -- protected NibbleArray a(M m0, long i) { -+ protected final NibbleArray a(M m0, long i) { // Paper - return m0.c(i); - } - -@@ -77,27 +77,57 @@ public abstract class LightEngineStorage> e - protected abstract int d(long i); - - protected int i(long i) { -- long j = SectionPosition.e(i); -- NibbleArray nibblearray = this.a(j, true); -+ // Paper start - reuse and inline math, use Optimized Updating path -+ final int x = (int) (i >> 38); -+ final int y = (int) ((i << 52) >> 52); -+ final int z = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(x, y, z); -+ NibbleArray nibblearray = this.updating.getUpdatingOptimized(j); -+ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. -+ if (nibblearray == null) { -+ nibblearray = this.e_visible.lookup.apply(j); -+ } -+ if (nibblearray == null) { -+ System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i)); -+ return 0; -+ } - -- return nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return nibblearray.a(x & 15, y & 15, z & 15); // Paper - inline operations -+ // Paper end - } - - protected void b(long i, int j) { -- long k = SectionPosition.e(i); -+ // Paper start - cache part of the math done in loop below -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - - if (this.g.add(k)) { - this.f.a(k); - } - - NibbleArray nibblearray = this.a(k, true); -- -- nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)), j); -- -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ nibblearray.a(x & 15, y & 15, z & 15, j); // Paper - use already calculated x/y/z -+ -+ // Paper start - credit to JellySquid for a major optimization here: -+ /* -+ * An extremely important optimization is made here in regards to adding items to the pending notification set. The -+ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position -+ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. -+ * -+ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only -+ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. -+ * -+ * @reason Use faster implementation -+ * @author JellySquid -+ */ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -129,17 +159,23 @@ public abstract class LightEngineStorage> e - } - - if (k >= 2 && j != 2) { -- if (this.p.contains(i)) { -- this.p.remove(i); -- } else { -+ if (!this.p.remove(i)) { // Paper - remove useless contains - credit to JellySquid -+ //this.p.remove(i); // Paper -+ //} else { // Paper - this.f.a(i, this.j(i)); - this.g.add(i); - this.k(i); - -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -165,9 +201,9 @@ public abstract class LightEngineStorage> e - return SectionPosition.e(j) == i; - }); - } else { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ int j = (int) (i >> 42) << 4; // Paper - inline -+ int k = (int) (i << 44 >> 44) << 4; // Paper - inline -+ int l = (int) (i << 22 >> 42) << 4; // Paper - inline - - for (int i1 = 0; i1 < 16; ++i1) { - for (int j1 = 0; j1 < 16; ++j1) { -@@ -194,7 +230,7 @@ public abstract class LightEngineStorage> e - NibbleArray nibblearray; - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.a(lightenginelayer, i); - NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i); - -@@ -212,7 +248,7 @@ public abstract class LightEngineStorage> e - longiterator = this.p.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.l(i); - } - -@@ -223,12 +259,13 @@ public abstract class LightEngineStorage> e - Entry entry; - long j; - -+ NibbleArray test = null; // Paper - while (objectiterator.hasNext()) { - entry = (Entry) objectiterator.next(); - j = entry.getLongKey(); -- if (this.g(j)) { -+ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice - nibblearray = (NibbleArray) entry.getValue(); -- if (this.f.c(j) != nibblearray) { -+ if (test != nibblearray) { // Paper - this.a(lightenginelayer, j); - this.f.a(j, nibblearray); - this.g.add(j); -@@ -241,14 +278,14 @@ public abstract class LightEngineStorage> e - longiterator = this.i.keySet().iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } else { - longiterator = this.n.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } -@@ -269,15 +306,20 @@ public abstract class LightEngineStorage> e - - private void b(LightEngineLayer lightenginelayer, long i) { - if (this.g(i)) { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ // Paper start -+ int secX = (int) (i >> 42); -+ int secY = (int) (i << 44 >> 44); -+ int secZ = (int) (i << 22 >> 42); -+ int j = secX << 4; // baseX -+ int k = secY << 4; // baseY -+ int l = secZ << 4; // baseZ -+ // Paper end - EnumDirection[] aenumdirection = LightEngineStorage.k; - int i1 = aenumdirection.length; - - for (int j1 = 0; j1 < i1; ++j1) { - EnumDirection enumdirection = aenumdirection[j1]; -- long k1 = SectionPosition.a(i, enumdirection); -+ long k1 = SectionPosition.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking - - if (!this.i.containsKey(k1) && this.g(k1)) { - for (int l1 = 0; l1 < 16; ++l1) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index da78d4c4b5f8af4648ac82d63c21f6a2a5b73ecb..2ce5cf2e5b6e1dae463439fbfde519fa54677714 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -7,13 +7,18 @@ import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { - -- private final long[] b = new long[2]; -- private final NibbleArray[] c = new NibbleArray[2]; -+ // private final long[] b = new long[2]; // Paper - unused -+ private final NibbleArray[] c = new NibbleArray[]{NibbleArray.EMPTY_NIBBLE_ARRAY, NibbleArray.EMPTY_NIBBLE_ARRAY}; private final NibbleArray[] cache = c; // Paper - OBFHELPER - private boolean d; - protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data - protected final boolean isVisible; // Paper - avoid copying light data -- java.util.function.Function lookup; // Paper - faster branchless lookup - -+ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function -+ public final NibbleArrayAccess lookup; -+ public interface NibbleArrayAccess { -+ NibbleArray apply(long id); -+ } -+ // Paper end - // Paper start - avoid copying light data - protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { - if (isVisible) { -@@ -21,12 +26,14 @@ public abstract class LightEngineStorageArray 0; --k) { -- this.b[k] = this.b[k - 1]; -- this.c[k] = this.c[k - 1]; -- } -- -- this.b[0] = i; -- this.c[0] = nibblearray; -- } -- -+ cache[1] = cache[0]; -+ cache[0] = nibblearray; - return nibblearray; - } - } -+ // Paper end -+ -+ @Nullable -+ public final NibbleArray c(final long i) { // Paper - final -+ // Paper start - optimize visible case or missed updating cases -+ if (this.d) { -+ // short circuit to optimized -+ return getUpdatingOptimized(i); -+ } -+ -+ return this.lookup.apply(i); -+ // Paper end -+ } - - @Nullable - public NibbleArray d(long i) { -@@ -82,13 +91,14 @@ public abstract class LightEngineStorageArray> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); -+ NibbleArray nibblearray = this.e_visible.lookup.apply(j); -+ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15); -+ // Paper end - } - - public static final class a extends LightEngineStorageArray { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 488403a6765598317faedc2d600ae82238e99e39..6d31b19c851081a37e6fcefdcdfcb7018fce6b26 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -28,7 +28,12 @@ public class LightEngineStorageSky extends LightEngineStorage> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ // Paper end - int k = SectionPosition.c(j); - synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -@@ -49,7 +54,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above - } else { - return 15; - } -@@ -168,7 +173,7 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - j = this.c(i); - if (j != 2 && !this.n.contains(i) && this.l.add(i)) { - int l; -@@ -203,10 +211,10 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - if (this.l.remove(i) && this.g(i)) { - for (j = 0; j < 16; ++j) { - for (k = 0; k < 16; ++k) { -- long l3 = BlockPosition.a(SectionPosition.c(SectionPosition.b(i)) + j, SectionPosition.c(SectionPosition.c(i)) + 16 - 1, SectionPosition.c(SectionPosition.d(i)) + k); -+ long l3 = BlockPosition.a(baseX + j, baseY + 16 - 1, baseZ + k); // Paper - - lightenginelayer.a(Long.MAX_VALUE, l3, 15, false); - } diff --git a/Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch deleted file mode 100644 index d2c3fa92571b..000000000000 --- a/Spigot-Server-Patches/0492-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Jun 2016 23:22:12 -0400 -Subject: [PATCH] Delay Chunk Unloads based on Player Movement - -When players are moving in the world, doing things such as building or exploring, -they will commonly go back and forth in a small area. This causes a ton of chunk load -and unload activity on the edge chunks of their view distance. - -A simple back and forth movement in 6 blocks could spam a chunk to thrash a -loading and unload cycle over and over again. - -This is very wasteful. This system introduces a delay of inactivity on a chunk -before it actually unloads, which will be handled by the ticket expiry process. - -This allows servers with smaller worlds who do less long distance exploring to stop -wasting cpu cycles on saving/unloading/reloading chunks repeatedly. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6463d3e4837d032a35654a035f42b8a805e0e286..1655bca0502e7b871de4addaa163536d86547a02 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -637,4 +637,13 @@ public class PaperWorldConfig { - private void viewDistance() { - this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); - } -+ -+ public long delayChunkUnloadsBy; -+ private void delayChunkUnloadsBy() { -+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); -+ if (delayChunkUnloadsBy > 0) { -+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); -+ delayChunkUnloadsBy *= 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index a3c44fdfca8290313b9b1117b984533183b583ad..3644e8b24b082e17752ef52934625416130aaa08 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -185,6 +185,27 @@ public abstract class ChunkMapDistance { - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { - removed = true; // CraftBukkit -+ // Paper start - delay chunk unloads for player tickets -+ long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy; -+ if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { -+ boolean hasPlayer = false; -+ for (Ticket ticket1 : arraysetsorted) { -+ if (ticket1.getTicketType() == TicketType.PLAYER) { -+ hasPlayer = true; -+ break; -+ } -+ } -+ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); -+ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { -+ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); -+ delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.currentTick); -+ arraysetsorted.remove(delayUnload); -+ // refresh ticket -+ arraysetsorted.add(delayUnload); -+ } -+ } -+ // Paper end - } - - if (arraysetsorted.isEmpty()) { -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 90cbd12611b7b078f35f08f910453bcc02f6665b..6e5ae954c6eb40590bf8c83f592c22088d489be8 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -9,11 +9,13 @@ public final class Ticket implements Comparable> { - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - public int priority = 0; // Paper -+ public long delayUnloadBy; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; - this.b = i; - this.identifier = t0; -+ this.delayUnloadBy = tickettype.loadPeriod; // Paper - } - - public int compareTo(Ticket ticket) { -@@ -63,7 +65,7 @@ public final class Ticket implements Comparable> { - } - - protected boolean b(long i) { -- long j = this.a.b(); -+ long j = delayUnloadBy; // Paper - - return j != 0L && i - this.d > j; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index f5d18834e0e2ee0e3bcf55810456766d2f134450..3c804c7b20a14ea6e510810e2be10c1cc89ff5c1 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -30,6 +30,7 @@ public class TicketType { - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); diff --git a/Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch deleted file mode 100644 index bdda9347f5ea..000000000000 --- a/Spigot-Server-Patches/0493-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 9 Jun 2020 03:33:03 -0400 -Subject: [PATCH] Add Plugin Tickets to API Chunk Methods - -Like previous versions, plugins loading chunks kept them loaded until -they garbage collected to avoid constant spamming of chunk loads - -This adds tickets to a few more places so that they can be unloaded. - -Additionally, this drops their ticket level to BORDER so they wont be ticking -so they will just sit inactive instead. - -Using .loadChunk to keep a chunk ticking was a horrible idea for upstream -when we have TWO methods that are able to do that already in the API. - -Also reduce their collection count down to a maximum of 1 second. Barely -anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and -since this wasn't spigot behavior, this is safe to mostly ignore (unless someone -wants it to collect even faster, they can restore that setting back to 1 instead of 20+) - -Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 81627e0774442c15c62b8a13db865378411d7801..02de2c985e0dcb43ff10e686b608052e83629064 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -346,7 +346,7 @@ public final class CraftServer implements Server { - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); - } -@@ -837,7 +837,7 @@ public final class CraftServer implements Server { - waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - printSaveWarning = false; - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6034ef65ee6030948a5b76fa493addb44188ef62..80cd8ce4e70dbb740439ac530a7bc70a7a54cb85 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.PlayerChunkMap; -@@ -407,8 +408,21 @@ public class CraftWorld implements World { - - @Override - public Chunk getChunkAt(int x, int z) { -- return this.world.getChunkProvider().getChunkAt(x, z, true).bukkitChunk; -+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it -+ net.minecraft.world.level.chunk.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (chunk == null) { -+ addTicket(x, z); -+ chunk = this.world.getChunkProvider().getChunkAt(x, z, true); -+ } -+ return chunk.bukkitChunk; -+ // Paper end -+ } -+ -+ // Paper start -+ private void addTicket(int x, int z) { -+ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE)); // Paper - } -+ // Paper end - - @Override - public Chunk getChunkAt(Block block) { -@@ -483,7 +497,7 @@ public class CraftWorld implements World { - public boolean unloadChunkRequest(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot - if (isChunkLoaded(x, z)) { -- world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -+ world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE); // Paper - } - - return true; -@@ -560,9 +574,12 @@ public class CraftWorld implements World { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot - // Paper start - Optimize this method - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); // Paper -+ if (immediate != null) return true; // Paper - - if (!generate) { -- IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ -+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper - if (immediate == null) { - immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); - } -@@ -570,7 +587,7 @@ public class CraftWorld implements World { - if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; // not full status - } -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower - return true; - } -@@ -597,7 +614,7 @@ public class CraftWorld implements World { - // we do this so we do not re-read the chunk data on disk - } - -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); - return true; - // Paper end -@@ -2547,6 +2564,7 @@ public class CraftWorld implements World { - } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ if (chunk != null) addTicket(x, z); // Paper - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } diff --git a/Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch b/Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch deleted file mode 100644 index 15f03e8c361d..000000000000 --- a/Spigot-Server-Patches/0494-Fix-missing-chunks-due-to-integer-overflow.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Slovikosky -Date: Tue, 9 Jun 2020 00:10:03 -0700 -Subject: [PATCH] Fix missing chunks due to integer overflow - -This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance -from 0,0 squared overflows the maximum size of an integer. The overflow leads -to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there -is a few hundred thousand block gap before end land resuming to generate at -530,000 blocks from spawn. This is due to the integer flipping back and forth. - -The fix for the issue is quite simple, casting chunk coordinates to longs -allows the distance calculation to avoid overflow and work as intended. - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 1d46e2c4e06cfe32eac06223e1966ce39c41685e..1077972d694d604c3ec97d333d34a9ab81819c33 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -75,7 +75,9 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - int l = j / 2; - int i1 = i % 2; - int j1 = j % 2; -- float f = 100.0F - MathHelper.c((float) (i * i + j * j)) * 8.0F; -+ // Paper start - cast ints to long to avoid integer overflow -+ float f = 100.0F - MathHelper.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; -+ // Paper end - - f = MathHelper.a(f, -100.0F, 80.0F); - diff --git a/Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch deleted file mode 100644 index 423af0ebf967..000000000000 --- a/Spigot-Server-Patches/0495-Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ossi -Date: Fri, 12 Jun 2020 01:38:06 +0300 -Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, - Consumer, long, long) scheduling a non-repeating task instead of - a repeating one. - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index ca90237a53c9a026919d28adaedf483ca3c7c2a8..13e461ffb2ee2e7d0440c0f60809ea99629b843c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -184,7 +184,7 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { -- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); - } - - @Override diff --git a/Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch b/Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch deleted file mode 100644 index 86e65e4b6fc2..000000000000 --- a/Spigot-Server-Patches/0496-Fix-piston-physics-inconsistency-MC-188840.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 11 Jun 2020 17:29:42 -0700 -Subject: [PATCH] Fix piston physics inconsistency - MC-188840 - -Pistons invoke physics when they move blocks. The physics can cause -tnt blocks to ignite. However, pistons (when storing the blocks they "moved") -don't actually go back to the world state sometimes to check if something -like that happened. As a result they end up moving the tnt like it was -never ignited. This resulted in the ability to create machines -that can duplicate tnt, called "world eaters". -This patch makes the piston logic retrieve the block state from the world -prevent this from occuring. - -This patch also sets the moved pos to air immediately after creating -the moving piston TE. This prevents the block from being updated from -other physics calls by the piston. - -Tested against the following tnt duper design: -https://www.youtube.com/watch?v=mS7xxNGhjxs - -This patch also affects every type of machine that utilises -this mechanic. For example, dead coral is removed by a physics -update when being moved while it is attached to slimeblocks. - -Standard piston machines that don't destroy or modify the -blocks they move by physics updates should be entirely -unaffected. - -This patch fixes https://bugs.mojang.com/browse/MC-188840 - -This patch also fixes rail duping and carpet duping. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7f140333c2e62012fa572c1a061d84432426997f..b67ba8f75e4a3358d7c2462918b85b0bf9b5a922 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -434,4 +434,10 @@ public class PaperConfig { - consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); - } - -+ public static boolean allowPistonDuplication; -+ private static void allowPistonDuplication() { -+ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); -+ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); -+ set("settings.unsupported-settings.allow-tnt-duplication", null); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index e062fd288098127fae22a55562e0207ceaf50163..8aa51fb207820a7629d50b80ea821ec6cccf8b54 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -399,12 +399,24 @@ public class BlockPiston extends BlockDirectional { - } - - for (k = list.size() - 1; k >= 0; --k) { -- blockposition3 = (BlockPosition) list.get(k); -- iblockdata1 = world.getType(blockposition3); -+ // Paper start - fix a variety of piston desync dupes -+ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; -+ BlockPosition oldPos = blockposition3 = (BlockPosition) list.get(k); -+ iblockdata1 = allowDesync ? world.getType(oldPos) : null; -+ // Paper end - fix a variety of piston desync dupes - blockposition3 = blockposition3.shift(enumdirection1); - map.remove(blockposition3); - world.setTypeAndData(blockposition3, (IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPiston.FACING, enumdirection), 68); -- world.setTileEntity(blockposition3, BlockPistonMoving.a((IBlockData) list1.get(k), enumdirection, flag, false)); -+ // Paper start - fix a variety of piston desync dupes -+ if (!allowDesync) { -+ iblockdata1 = world.getType(oldPos); -+ map.replace(oldPos, iblockdata1); -+ } -+ world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); -+ if (!allowDesync) { -+ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block -+ } -+ // Paper end - fix a variety of piston desync dupes - aiblockdata[j++] = iblockdata1; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index 8d13e60f40e1b760e9e69969dc3f37bc6c70dbe9..e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -279,7 +279,7 @@ public class TileEntityPiston extends TileEntity implements ITickable { - IBlockData iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position); - - if (iblockdata.isAir()) { -- this.world.setTypeAndData(this.position, this.a, 84); -+ this.world.setTypeAndData(this.position, this.a, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air - Block.a(this.a, iblockdata, this.world, this.position, 3); - } else { - if (iblockdata.b(BlockProperties.C) && (Boolean) iblockdata.get(BlockProperties.C)) { diff --git a/Spigot-Server-Patches/0497-Fix-sand-duping.patch b/Spigot-Server-Patches/0497-Fix-sand-duping.patch deleted file mode 100644 index e3e2417078bb..000000000000 --- a/Spigot-Server-Patches/0497-Fix-sand-duping.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 13:33:19 -0700 -Subject: [PATCH] Fix sand duping - -If the falling block dies during teleportation (entity#move), then we need -to detect that by placing a check after the move. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 411e3915c0aa00249aacb6658ed04309665d2fb4..62d8b53c024888aa43b8fddf8a475dfb8284a4cc 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -103,6 +103,11 @@ public class EntityFallingBlock extends Entity { - - @Override - public void tick() { -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping - if (this.block.isAir()) { - this.die(); - } else { -@@ -125,6 +130,12 @@ public class EntityFallingBlock extends Entity { - - this.move(EnumMoveType.SELF, this.getMot()); - -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping -+ - // Paper start - Configurable EntityFallingBlock height nerf - if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { - if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { diff --git a/Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch b/Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch deleted file mode 100644 index 4422c552fec4..000000000000 --- a/Spigot-Server-Patches/0498-Prevent-position-desync-in-playerconnection-causing-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 16:51:39 -0700 -Subject: [PATCH] Prevent position desync in playerconnection causing tp - exploit - -Caused the server to revert to the player's overworld coordinates -after teleporting into the end. - -Sidenote: The underlying issue is that the move call can teleport -entities and do other things like kill the entity. In the future, -to fix all exploits derieved from this usually unexpected -behaviour, we need to move all of this dangerous logic outside -of the move call and into an appropriate place in the tick method. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 42190a8c6c2eadf05f57df50e3ca997384327b67..dd26d1ad34600250de7572c09bd4d74331142ad9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1326,6 +1326,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); - this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move -+ // Paper start - prevent position desync -+ if (this.teleportPos != null) { -+ return; // ... thanks Mojang for letting move calls teleport across dimensions. -+ } -+ // Paper end - prevent position desync - double d12 = d8; - - d7 = d4 - this.player.locX(); diff --git a/Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch b/Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch deleted file mode 100644 index 6217196c7731..000000000000 --- a/Spigot-Server-Patches/0499-Fix-enderdragon-exp-dupe.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 22:25:11 -0700 -Subject: [PATCH] Fix enderdragon exp dupe - -Properly track death stage when unloading/loading in the -dragon - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 5168a40eb53565bb3028efe559601acf72bddae5..c296fcf80c2f3f210fa020416973ec8d5db541ba 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -879,6 +879,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); - nbttagcompound.setInt("DragonPhase", this.bG.a().getControllerPhase().b()); -+ nbttagcompound.setInt("Paper.DeathTick", this.deathAnimationTicks); // Paper - } - - @Override -@@ -887,6 +888,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (nbttagcompound.hasKey("DragonPhase")) { - this.bG.setControllerPhase(DragonControllerPhase.getById(nbttagcompound.getInt("DragonPhase"))); - } -+ this.deathAnimationTicks = nbttagcompound.getInt("Paper.DeathTick"); // Paper - - } - diff --git a/Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch b/Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index eeb9b623520b..000000000000 --- a/Spigot-Server-Patches/0500-Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:15 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 45634fded9916dca35a246921efb87964c860339..c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -9,6 +9,7 @@ import net.minecraft.world.inventory.InventoryCrafting; - import net.minecraft.world.inventory.InventoryEnderChest; - import net.minecraft.world.inventory.InventoryMerchant; - import net.minecraft.world.level.block.entity.IHopper; -+import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityBarrel; - import net.minecraft.world.level.block.entity.TileEntityBlastFurnace; - import net.minecraft.world.level.block.entity.TileEntityBrewingStand; -@@ -526,6 +527,13 @@ public class CraftInventory implements Inventory { - return inventory.getOwner(); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof TileEntity ? ((TileEntity) inventory).getOwner(useSnapshot) : getHolder(); -+ } -+ // Paper end -+ - @Override - public int getMaxStackSize() { - return inventory.getMaxStackSize(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -index 47029af761e26453090980b9a231fd53d4238cc4..d22abb4259dfcfd3ec0e0516f87fc838a81353ce 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -@@ -64,6 +64,13 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC - return new DoubleChest(this); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public DoubleChest getHolder(boolean useSnapshot) { -+ return getHolder(); -+ } -+ // Paper end -+ - @Override - public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch b/Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch deleted file mode 100644 index 07e4be337010..000000000000 --- a/Spigot-Server-Patches/0501-Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Sat, 23 May 2020 10:31:11 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index c325c9fe680d9033b20909bcd6100ecc4b0195f6..ce754e0da047050daa08e5e0564fa399d334c04b 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -558,6 +558,7 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ public final ItemStack getOriginalItemStack() { return getItemStack(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all - protected abstract ItemStack getItemStack(); - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index ea33a36dfa6f304946f5b998eb536678a9b2f98c..2ab41a24a22e736753276b95fa0d060017cca0bc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -@@ -103,6 +103,13 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { - getHandle().fromPlayer = EntityArrow.PickupStatus.a(status.ordinal()); - } - -+ // Paper start -+ @Override -+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); -+ } -+ //Paper end -+ - @Override - public void setTicksLived(int value) { - super.setTicksLived(value); diff --git a/Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch b/Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index 554173a965b5..000000000000 --- a/Spigot-Server-Patches/0502-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Fri, 5 Jun 2020 18:24:06 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index dd26d1ad34600250de7572c09bd4d74331142ad9..20c6a61101e40b09babf0ce6ad05a889d9fdfe46 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2771,9 +2771,15 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { -- this.minecraftServer.getCraftingManager().getRecipe(packetplayinautorecipe.c()).ifPresent((irecipe) -> { -- ((ContainerRecipeBook) this.player.activeContainer).a(packetplayinautorecipe.d(), irecipe, this.player); -- }); -+ // Paper start - fire event for clicking recipes in the recipe book -+ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( -+ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packetplayinautorecipe.c()), packetplayinautorecipe.d()); -+ if (event.callEvent()) { -+ this.minecraftServer.getCraftingManager().getRecipe(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { -+ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); -+ }); -+ } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch b/Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch deleted file mode 100644 index 9b9dd4ede4c7..000000000000 --- a/Spigot-Server-Patches/0503-Hide-sync-chunk-writes-behind-flag.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 26 Jun 2020 22:35:08 -0700 -Subject: [PATCH] Hide sync chunk writes behind flag - -Syncing writes on each write call has terrible performance -on harddrives. - --DPaper.enable-sync-chunk-writes=true to enable - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index b7cf02301c02ed0a6b696384e656426762ae2105..1fab9b9c7d41a0d2a551096c2c15f741a887fa2d 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -111,7 +111,7 @@ public class DedicatedServerProperties extends PropertyManager { - return MathHelper.clamp(integer, 1, 29999984); - }, 29999984); -- this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true); -+ this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag - this.enableJmxMonitoring = this.getBoolean("enable-jmx-monitoring", false); - this.enableStatus = this.getBoolean("enable-status", true); - this.entityBroadcastRangePercentage = this.a("entity-broadcast-range-percentage", (integer) -> { diff --git a/Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch b/Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch deleted file mode 100644 index 779333c56daa..000000000000 --- a/Spigot-Server-Patches/0504-Limit-lightning-strike-effect-distance.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 14 Sep 2018 17:42:08 +0200 -Subject: [PATCH] Limit lightning strike effect distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -646,4 +646,26 @@ public class PaperWorldConfig { - delayChunkUnloadsBy *= 20; - } - } -+ -+ public double sqrMaxThunderDistance; -+ public double sqrMaxLightningImpactSoundDistance; -+ public double maxLightningFlashDistance; -+ private void lightningStrikeDistanceLimit() { -+ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); -+ if (sqrMaxThunderDistance > 0) { -+ sqrMaxThunderDistance *= sqrMaxThunderDistance; -+ } -+ -+ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); -+ if (sqrMaxLightningImpactSoundDistance < 0) { -+ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value -+ } else { -+ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; -+ } -+ -+ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); -+ if (maxLightningFlashDistance < 0) { -+ maxLightningFlashDistance = 512; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 8946fcd93bd785a8c21683b932aa954fbf15d566..834ced9d9b385c8f1d66355244313d62a97d9c98 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -76,6 +76,17 @@ public class EntityLightning extends Entity { - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -+ // Paper start - Limit lightning strike effect distance -+ if (distanceSquared <= this.world.paperConfig.sqrMaxLightningImpactSoundDistance) { -+ player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, -+ SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); -+ } -+ -+ if (world.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= world.paperConfig.sqrMaxThunderDistance) { -+ continue; -+ } -+ -+ // Paper end - if (distanceSquared > viewDistance * viewDistance) { - double deltaLength = Math.sqrt(distanceSquared); - double relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; -@@ -86,7 +97,7 @@ public class EntityLightning extends Entity { - } - } - // CraftBukkit end -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) - } - - --this.lifeTicks; diff --git a/Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch b/Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch deleted file mode 100644 index 591d3130bfc5..000000000000 --- a/Spigot-Server-Patches/0505-Add-permission-for-command-blocks.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:05:30 +0200 -Subject: [PATCH] Add permission for command blocks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index fbd8a6985a261396789c87e4b687140bd49cea0d..984209e4f66ad23d85d2c5d02318caab1aff7324 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -387,7 +387,7 @@ public class PlayerInteractManager { - TileEntity tileentity = this.world.getTileEntity(blockposition); - Block block = iblockdata.getBlock(); - -- if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp()) { -+ if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp() && !(block instanceof BlockCommand && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - this.world.notify(blockposition, iblockdata, iblockdata, 3); - return false; - } else if (this.player.a((World) this.world, blockposition, this.gamemode)) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 20c6a61101e40b09babf0ce6ad05a889d9fdfe46..eecf23aa41c8b21fce58ff33a3124186a4fdccd1 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -798,7 +798,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandblock, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = null; -@@ -861,7 +861,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandminecart, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = packetplayinsetcommandminecart.a(this.player.world); -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 3fcdff3649c725580456dfc965d6c83bd5afe3da..85e7957103d2b2e16e4d3a3ea0bd7de4935f61cd 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -192,7 +192,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - } - - public EnumInteractionResult a(EntityHuman entityhuman) { -- if (!entityhuman.isCreativeAndOp()) { -+ if (!entityhuman.isCreativeAndOp() && !entityhuman.isCreative() && !entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - return EnumInteractionResult.PASS; - } else { - if (entityhuman.getWorld().isClientSide) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCommand.java b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -index ad50f86d11ff22f055ca9f26cd02a84e75c7d8c8..f7d22282a59277375d146e9459f9f43962dd7d09 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCommand.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -@@ -128,7 +128,7 @@ public class BlockCommand extends BlockTileEntity { - public EnumInteractionResult interact(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { - TileEntity tileentity = world.getTileEntity(blockposition); - -- if (tileentity instanceof TileEntityCommand && entityhuman.isCreativeAndOp()) { -+ if (tileentity instanceof TileEntityCommand && (entityhuman.isCreativeAndOp() || (entityhuman.isCreative() && entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - entityhuman.a((TileEntityCommand) tileentity); - return EnumInteractionResult.a(world.isClientSide); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -index 525ebf961e5da0687183a5e2ead23ed92cbd9d79..a4a809f302c5ff9c76cde5fc0add2ceec1bdf9b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -@@ -16,6 +16,7 @@ public final class CraftDefaultPermissions { - DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); -+ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper - // Spigot end - parent.recalculatePermissibles(); - } diff --git a/Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch b/Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch deleted file mode 100644 index df29f83aa1d5..000000000000 --- a/Spigot-Server-Patches/0506-Ensure-Entity-AABB-s-are-never-invalid.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index da2b5bfd3966ded2d5dde0d65646583576a088c5..c50b89ee8f16821923933025bf19243771dd1604 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -66,6 +66,7 @@ import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.animal.EntityAnimal; - import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -479,7 +480,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public void setPosition(double d0, double d1, double d2) { - this.setPositionRaw(d0, d1, d2); -- this.a(this.size.a(d0, d1, d2)); -+ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw - if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit - } - -@@ -2994,6 +2995,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return new AxisAlignedBB(vec3d, vec3d1); - } - -+ public final void setBoundingBox(AxisAlignedBB axisalignedbb) { a(axisalignedbb); } // Paper - OBFHELPER - public void a(AxisAlignedBB axisalignedbb) { - // CraftBukkit start - block invalid bounding boxes - double minX = axisalignedbb.minX, -@@ -3432,6 +3434,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRaw(double d0, double d1, double d2) { -+ // Paper start - never allow AABB to become desynced from position -+ // hanging has its own special logic -+ if (!(this instanceof EntityHanging) && (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2)) { -+ this.setBoundingBox(this.size.a(d0, d1, d2)); -+ } -+ // Paper end - if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { - this.loc = new Vec3D(d0, d1, d2); - int i = MathHelper.floor(d0); diff --git a/Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch b/Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch deleted file mode 100644 index b153f9d172af..000000000000 --- a/Spigot-Server-Patches/0507-Optimize-WorldBorder-collision-checks-and-air.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 10 May 2020 22:49:05 -0400 -Subject: [PATCH] Optimize WorldBorder collision checks and air - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c50b89ee8f16821923933025bf19243771dd1604..27e5ba64ed6406c1ece318bf79fca0f261a77818 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -909,7 +909,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); - VoxelShape voxelshape = this.world.getWorldBorder().c(); -- Stream stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape); -+ Stream stream = !this.world.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper - Stream stream1 = this.world.c(this, axisalignedbb.b(vec3d), (entity) -> { - return true; - }); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index d0cc8677f2be422722160fee9b71894b5ddd3186..03584572fa5bf0d96fc4cecece573547f9c94cea 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -143,10 +143,10 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - AxisAlignedBB axisalignedbb = this.a.getBoundingBox(); - - if (!a(worldborder, axisalignedbb)) { -- VoxelShape voxelshape = worldborder.c(); -- -- if (!b(voxelshape, axisalignedbb) && a(voxelshape, axisalignedbb)) { -- consumer.accept(voxelshape); -+ // Paper start -+ if (worldborder.isInBounds(axisalignedbb.shrink(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { -+ consumer.accept(worldborder.asVoxelShape()); -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 50e2085766caabec1125ca24a2117549efd1a354..bedaa9dd6390e81df5872c2dd6e202a038367bf6 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -52,6 +52,7 @@ public class WorldBorder { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } - -+ public final boolean isInBounds(AxisAlignedBB aabb) { return this.a(aabb); } // Paper - OBFHELPER - public boolean a(AxisAlignedBB axisalignedbb) { - return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 2d7405d1fa7c8f378bebe86f5d0de57a129ed92d..858d4689e618c72250447adb61e0bcc3c156f8f3 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -252,7 +252,7 @@ public final class VoxelShapes { - IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper - if (iblockdata == null) return 0.0D; // Paper - -- if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { -+ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { // Paper - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); - if (Math.abs(d0) < 1.0E-7D) { - return 0.0D; diff --git a/Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch deleted file mode 100644 index ca06222fdd2c..000000000000 --- a/Spigot-Server-Patches/0508-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 03:59:10 -0400 -Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty - -Fixes per world difficulty with /difficulty command and also -makes it so that the server keeps the last difficulty used instead -of restoring the server.properties every single load. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9074646e8111c69c4875b0633a424b250a30bc5c..c3635577b1796e6ca84709469ecf95c815fe53a5 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1646,11 +1646,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sun, 28 Jun 2020 19:27:20 -0400 -Subject: [PATCH] Paper dumpitem command - -Let's you quickly view the item in your hands NBT data - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index d165e8c232c38ba2e2faf93c60c8a127bb74c9b6..4b3efe01750d79bcc27a42b5a145d9aa6b124d18 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -9,6 +9,7 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; -@@ -36,7 +37,9 @@ import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.Player; -+import org.bukkit.inventory.ItemStack; - - import java.io.File; - import java.io.FileOutputStream; -@@ -59,7 +62,7 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); - - public PaperCommand(String name) { - super(name); -@@ -168,6 +171,9 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "dumpitem": -+ doDumpItem(sender); -+ break; - case "debug": - doDebug(sender, args); - break; -@@ -200,6 +206,19 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doDumpItem(CommandSender sender) { -+ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); -+ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ NBTTagCompound tag = itemStack.getTag(); -+ if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); -+ } else { -+ sender.sendMessage("Item does not have NBT"); -+ } -+ } -+ - private void doFixLight(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("Only players can use this command"); -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index d6e51f82f6df2d7058806f3e483766e18398af77..3921b99b9a4c1a867b5159668d2cd62d7463e1ff 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -26,6 +26,7 @@ public interface NBTBase { - return this.toString(); - } - -+ default IChatBaseComponent getNbtPrettyComponent() { return this.l(); } // Paper - OBFHELPER - default IChatBaseComponent l() { - return this.a("", 0); - } diff --git a/Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch b/Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch deleted file mode 100644 index b5584efc91c8..000000000000 --- a/Spigot-Server-Patches/0510-Don-t-allow-null-UUID-s-for-chat.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:36:55 -0400 -Subject: [PATCH] Don't allow null UUID's for chat - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index fefcacf27d71c67403555502685a992a5a706099..267e1baeaaed83befc7f6d6445a9416f7b8dfc0f 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -3,6 +3,7 @@ package net.minecraft.network.protocol.game; - - import java.io.IOException; - import java.util.UUID; -+import net.minecraft.SystemUtils; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatMessageType; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -21,7 +22,7 @@ public class PacketPlayOutChat implements Packet { - public PacketPlayOutChat(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.a = ichatbasecomponent; - this.b = chatmessagetype; -- this.c = uuid; -+ this.c = uuid != null ? uuid : SystemUtils.getNullUUID(); // Paper - } - - @Override diff --git a/Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch b/Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch deleted file mode 100644 index f63ad3aa3227..000000000000 --- a/Spigot-Server-Patches/0511-Improve-Legacy-Component-serialization-size.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:08:41 -0400 -Subject: [PATCH] Improve Legacy Component serialization size - -Don't constantly send format: false for all formatting options when parent already -has it false - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 666af6cc91bd12ba5d5a846d663a5aabf861fbc4..189a416bd033c9ff390d359aa19cec515d0461e4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -46,6 +46,7 @@ public final class CraftChatMessage { - // Separate pattern with no group 3, new lines are part of previous string - private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); - // ChatColor.b does not explicitly reset, its more of empty -+ private static final ChatModifier EMPTY = ChatModifier.a.setItalic(false); // Paper - OBFHELPER - private static final ChatModifier RESET = ChatModifier.a.setBold(false).setItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); - - private final List list = new ArrayList(); -@@ -67,6 +68,7 @@ public final class CraftChatMessage { - Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); - String match = null; - boolean needsAdd = false; -+ boolean hasReset = false; // Paper - while (matcher.find()) { - int groupId = 0; - while ((match = matcher.group(++groupId)) == null) { -@@ -112,7 +114,26 @@ public final class CraftChatMessage { - throw new AssertionError("Unexpected message format"); - } - } else { // Color resets formatting -- modifier = RESET.setColor(format); -+ // Paper start - improve legacy formatting -+ ChatModifier previous = modifier; -+ modifier = (!hasReset ? RESET : EMPTY).setColor(format); -+ hasReset = true; -+ if (previous.isBold()) { -+ modifier = modifier.setBold(false); -+ } -+ if (previous.isItalic()) { -+ modifier = modifier.setItalic(false); -+ } -+ if (previous.isRandom()) { -+ modifier = modifier.setRandom(false); -+ } -+ if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); -+ } -+ if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); -+ } -+ // Paper end - } - needsAdd = true; - break; diff --git a/Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch b/Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch deleted file mode 100644 index 8ba6c36f4a57..000000000000 --- a/Spigot-Server-Patches/0512-Support-old-UUID-format-for-NBT.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Jun 2020 03:26:17 -0400 -Subject: [PATCH] Support old UUID format for NBT - -We have stored UUID in plenty of places that did not get DFU'd - -So just look for old format and load it if it exists. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 0560d115288c67e46d921ce529e603f424e601f5..50515cd9287505fcc8ab52e47393fb1dc771bfc3 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -41,6 +41,11 @@ public final class GameProfileSerializer { - s = nbttagcompound.getString("Name"); - } - -+ // Paper start - support string UUID's -+ if (nbttagcompound.hasKeyOfType("Id", 8)) { -+ uuid = UUID.fromString(nbttagcompound.getString("Id")); -+ } -+ // Paper end - if (nbttagcompound.b("Id")) { - uuid = nbttagcompound.a("Id"); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 77afbaad5b2cb8d912f5404fcbd3a0970490f4f3..945df83d4a2170cdcc29cb6d7b9f0f5f3940cb96 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -142,6 +142,12 @@ public class NBTTagCompound implements NBTBase { - - public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ this.map.remove(s + "Most"); -+ this.map.remove(s + "Least"); -+ } -+ // Paper end - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -@@ -151,11 +157,21 @@ public class NBTTagCompound implements NBTBase { - */ - public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { -+ // Paper start - support old format -+ if (!hasKeyOfType(s, 11) && this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); -+ } -+ // Paper end - return GameProfileSerializer.a(this.get(s)); - } - - public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return true; -+ } -+ // Paper end - NBTBase nbtbase = this.get(s); - - return nbtbase != null && nbtbase.b() == NBTTagIntArray.a && ((NBTTagIntArray) nbtbase).getInts().length == 4; diff --git a/Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch b/Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch deleted file mode 100644 index 7309e30816ab..000000000000 --- a/Spigot-Server-Patches/0513-Clean-up-duplicated-GameProfile-Properties.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 03:12:06 -0400 -Subject: [PATCH] Clean up duplicated GameProfile Properties - -We had a bug where we accidently cloned properties resulting in skulls -growing to large sizes and preventing login. - -This now automatically cleans up the extra properties. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 50515cd9287505fcc8ab52e47393fb1dc771bfc3..a654ea9e43c4e7dd9cde1c47d0b07834f47aa751 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -60,8 +60,8 @@ public final class GameProfileSerializer { - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); - NBTTagList nbttaglist = nbttagcompound1.getList(s1, 10); -- -- for (int i = 0; i < nbttaglist.size(); ++i) { -+ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties -+ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties - NBTTagCompound nbttagcompound2 = nbttaglist.getCompound(i); - String s2 = nbttagcompound2.getString("Value"); - -@@ -247,7 +247,7 @@ public final class GameProfileSerializer { - Optional optional = iblockstate.b(nbttagcompound.getString(s)); - - if (optional.isPresent()) { -- return (IBlockDataHolder) s0.set(iblockstate, (Comparable) optional.get()); -+ return s0.set(iblockstate, optional.get()); // Paper - decompile error - } else { - GameProfileSerializer.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", s, nbttagcompound.getString(s), nbttagcompound1.toString()); - return s0; -@@ -277,8 +277,8 @@ public final class GameProfileSerializer { - return nbttagcompound; - } - -- private static > String a(IBlockState iblockstate, Comparable comparable) { -- return iblockstate.a(comparable); -+ private static > String a(IBlockState iblockstate, Comparable comparable) {// Paper - decompile error -+ return iblockstate.a((T) comparable);// Paper - decompile error - } - - public static NBTTagCompound a(DataFixer datafixer, DataFixTypes datafixtypes, NBTTagCompound nbttagcompound, int i) { -diff --git a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -index 70207d1ca5b971f829911b1231160f4664062da0..47eed24fa28db8c12ce98b6b72ca1671e13e9f52 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -@@ -59,6 +59,18 @@ public class ItemSkullPlayer extends ItemBlockWallable { - return true; - } else { - // CraftBukkit start -+ // Paper start - clean up old duplicated properties -+ NBTTagCompound properties = nbttagcompound.getCompound("SkullOwner").getCompound("Properties"); -+ for (String key : properties.getKeys()) { -+ net.minecraft.nbt.NBTTagList values = properties.getList(key, 10); -+ if (values.size() > 1) { -+ net.minecraft.nbt.NBTBase texture = values.get(values.size() - 1); -+ values = new net.minecraft.nbt.NBTTagList(); -+ values.add(texture); -+ properties.set(key, values); -+ } -+ } -+ // Paper end - net.minecraft.nbt.NBTTagList textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts - for (int i = 0; i < textures.size(); i++) { - if (textures.get(i) instanceof NBTTagCompound && !((NBTTagCompound) textures.get(i)).hasKeyOfType("Signature", 8) && ((NBTTagCompound) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch b/Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch deleted file mode 100644 index 025b86e719ca..000000000000 --- a/Spigot-Server-Patches/0514-Convert-legacy-attributes-in-Item-Meta.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 04:50:22 -0400 -Subject: [PATCH] Convert legacy attributes in Item Meta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 43fa8d3c573540682fc87ee2bf8d61ba80d3732d..673948947bd918c1dbb6c4c99486b4200e3c09fe 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -13,6 +13,20 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - public class CraftAttributeMap implements Attributable { - - private final AttributeMapBase handle; -+ // Paper start - convert legacy attributes -+ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); -+ -+ public static String convertIfNeeded(String nms) { -+ if (nms == null) { -+ return null; -+ } -+ nms = legacyNMS.getOrDefault(nms, nms); -+ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { -+ return null; -+ } -+ return nms; -+ } -+ // Paper end - - public CraftAttributeMap(AttributeMapBase handle) { - this.handle = handle; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 8f8dccd6fb2e49d65383d6e8f3fc5ffbabd2b7a5..8398ac45e988c621b3e059d75101185513ddd9ab 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -481,7 +481,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); - -- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); -+ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper - if (attributeName == null || attributeName.isEmpty()) { - continue; - } diff --git a/Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch b/Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch deleted file mode 100644 index 67b43bca11d5..000000000000 --- a/Spigot-Server-Patches/0515-Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Mon, 29 Jun 2020 17:03:06 -0400 -Subject: [PATCH] Remove some streams from structures - -This showed up a lot in the spark profiler, should have a low-medium performance improvement. - -diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java -index 6fe276b29aa9fe1b312ef2773484fa780506fded..07dcfd56af1014ad159828dd9ee2d89c2010b9f4 100644 ---- a/src/main/java/net/minecraft/world/level/StructureManager.java -+++ b/src/main/java/net/minecraft/world/level/StructureManager.java -@@ -2,6 +2,7 @@ - package net.minecraft.world.level; - - import com.mojang.datafixers.DataFixUtils; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -12,11 +13,12 @@ import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IStructureAccess; - import net.minecraft.world.level.levelgen.GeneratorSettings; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; -+import net.minecraft.world.level.levelgen.structure.StructurePiece; - import net.minecraft.world.level.levelgen.structure.StructureStart; - - public class StructureManager { - -- private final GeneratorAccess a; -+ private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER - private final GeneratorSettings b; - - public StructureManager(GeneratorAccess generatoraccess, GeneratorSettings generatorsettings) { -@@ -42,6 +44,20 @@ public class StructureManager { - }); - } - -+ // Paper start - remove structure streams -+ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { -+ java.util.List> list = new ObjectArrayList<>(); -+ for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { -+ SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); -+ StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); -+ if (structurestart != null && structurestart.e()) { -+ list.add(structurestart); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - @Nullable - public StructureStart a(SectionPosition sectionposition, StructureGenerator structuregenerator, IStructureAccess istructureaccess) { - return istructureaccess.a(structuregenerator); -@@ -60,13 +76,21 @@ public class StructureManager { - } - - public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { -- return (StructureStart) DataFixUtils.orElse(this.a(SectionPosition.a(blockposition), structuregenerator).filter((structurestart) -> { -- return structurestart.c().b((BaseBlockPosition) blockposition); -- }).filter((structurestart) -> { -- return !flag || structurestart.d().stream().anyMatch((structurepiece) -> { -- return structurepiece.g().b((BaseBlockPosition) blockposition); -- }); -- }).findFirst(), StructureStart.a); -+ // Paper start - remove structure streams -+ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ if (structurestart.c().b(blockposition)) { -+ if (!flag) { -+ return structurestart; -+ } -+ for (StructurePiece structurepiece : structurestart.d()) { -+ if (structurepiece.g().b(blockposition)) { -+ return structurestart; -+ } -+ } -+ } -+ } -+ return StructureStart.a; -+ // Paper end - } - - // Spigot start -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 7147cdda756ccb3d4f6880802128f68601783883..15096a9c2719b8b4c099f62d0a1c808e56b63a8e 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -39,6 +39,7 @@ import net.minecraft.world.level.levelgen.WorldGenStage; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; - import net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.surfacebuilders.WorldGenSurfaceComposite; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; - import net.minecraft.world.level.material.Fluid; -@@ -238,9 +239,11 @@ public final class BiomeBase { - int l1 = j1 << 4; - - try { -- structuremanager.a(SectionPosition.a(blockposition), structuregenerator).forEach((structurestart) -> { -- structurestart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -- }); -+ // Paper start - remove structure streams -+ for (StructureStart structureStart : structuremanager.getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ structureStart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -+ } -+ // Paper end - } catch (Exception exception) { - CrashReport crashreport = CrashReport.a(exception, "Feature placement"); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index 700b32322e8d0fbb8ec2824e50a340be16b48f81..369fb0bda22f02e76b901b6eb8990651c53c7577 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -40,6 +40,7 @@ import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefi - import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefinedStructurePoolTemplate; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; - import net.minecraft.world.level.levelgen.structure.StructurePiece; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.WorldGenFeaturePillagerOutpostPoolPiece; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; -@@ -455,7 +456,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - while (iterator.hasNext()) { - StructureGenerator structuregenerator = (StructureGenerator) iterator.next(); - -- structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { -+ for (StructureStart structurestart : structuremanager.getFeatureStarts(SectionPosition.a(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams - Iterator iterator1 = structurestart.d().iterator(); - - while (iterator1.hasNext()) { -@@ -487,7 +488,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - } - } - -- }); -+ } // Paper - remove structure streams - } - - double[][][] adouble = new double[2][this.p + 1][this.o + 1]; diff --git a/Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch b/Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch deleted file mode 100644 index 2e8b2273351b..000000000000 --- a/Spigot-Server-Patches/0516-Remove-streams-from-classes-related-villager-gossip.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 1 Jul 2020 18:01:49 -0400 -Subject: [PATCH] Remove streams from classes related villager gossip - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 9cc3a18636a356977577076e96cb7be706c61abf..7d34d1157786227ac210edc1595a024ccb61a3e9 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -9,6 +9,7 @@ import com.mojang.serialization.DynamicOps; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.util.Arrays; - import java.util.Collection; -@@ -51,8 +52,21 @@ public class Reputation { - }); - } - -+ // Paper start - Remove streams from reputation -+ private List decompress() { -+ List list = new ObjectArrayList<>(); -+ for (Map.Entry entry : getReputations().entrySet()) { -+ for (Reputation.b cur : entry.getValue().decompress(entry.getKey())) { -+ if (cur.a() != 0) -+ list.add(cur); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - private Collection a(Random random, int i) { -- List list = (List) this.c().collect(Collectors.toList()); -+ List list = decompress(); // Paper - Remove streams from reputation - - if (list.isEmpty()) { - return Collections.emptyList(); -@@ -119,7 +133,7 @@ public class Reputation { - } - - public Dynamic a(DynamicOps dynamicops) { -- return new Dynamic(dynamicops, dynamicops.createList(this.c().map((reputation_b) -> { -+ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { - return reputation_b.a(dynamicops); - }).map(Dynamic::getValue))); - } -@@ -144,18 +158,30 @@ public class Reputation { - - public static class a { // Paper - make public - -- private final Object2IntMap a; -+ private final Object2IntMap a; private Object2IntMap getEntries() { return a; } // Paper - OBFHELPER - - public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - - public int a(Predicate predicate) { -- return this.a.object2IntEntrySet().stream().filter((entry) -> { -- return predicate.test(entry.getKey()); -- }).mapToInt((entry) -> { -- return entry.getIntValue() * ((ReputationType) entry.getKey()).g; -- }).sum(); -+ // Paper start - Remove streams from reputation -+ int weight = 0; -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ if (predicate.test(entry.getKey())) { -+ weight += entry.getIntValue() * entry.getKey().getWeight(); -+ } -+ } -+ return weight; -+ } -+ -+ public List decompress(UUID uuid) { -+ List list = new ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ list.add(new Reputation.b(uuid, entry.getKey(), entry.getIntValue())); -+ } -+ return list; -+ // Paper - end - } - - public Stream a(UUID uuid) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -index 89651e6e3bb1cfbb8eb8a120b3c3e553cd831a68..6036476aac4a81152e8b142445041ecdb2d6e5d1 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -@@ -11,7 +11,7 @@ public enum ReputationType { - MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); - - public final String f; -- public final int g; -+ public final int g; public int getWeight() { return g; } // Paper - OBFHELPER - public final int h; - public final int i; - public final int j; diff --git a/Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch b/Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch deleted file mode 100644 index 6f1e33b76d31..000000000000 --- a/Spigot-Server-Patches/0517-Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Sat, 6 Jun 2020 18:13:42 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 8398ac45e988c621b3e059d75101185513ddd9ab..5c1319a86f6314c1d0a979af34424ee025a8030f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -875,11 +875,23 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return CraftChatMessage.fromJSONComponent(displayName); - } - -+ // Paper start -+ @Override -+ public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { -+ return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(displayName); -+ } -+ // Paper end - @Override - public final void setDisplayName(String name) { - this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); - } - -+ // Paper start -+ @Override -+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -+ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); -+ } -+ // Paper end - @Override - public boolean hasDisplayName() { - return displayName != null; -@@ -1022,6 +1034,14 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); - } - -+ // Paper start -+ @Override -+ public List getLoreComponents() { -+ return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> -+ net.md_5.bungee.chat.ComponentSerializer.parse(entry) -+ ).collect(java.util.stream.Collectors.toList())); -+ } -+ // Paper end - @Override - public void setLore(List lore) { - if (lore == null || lore.isEmpty()) { -@@ -1036,6 +1056,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ @Override -+ public void setLoreComponents(List lore) { -+ if (lore == null) { -+ this.lore = null; -+ } else { -+ if (this.lore == null) { -+ safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); -+ } else { -+ this.lore.clear(); -+ safelyAdd(lore, this.lore, false); -+ } -+ } -+ } -+ // Paper end - @Override - public boolean hasCustomModelData() { - return customModelData != null; -@@ -1497,6 +1532,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - for (Object object : addFrom) { -+ // Paper start - support components -+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { -+ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); -+ } else -+ // Paper end - if (!(object instanceof String)) { - if (object != null) { - throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch deleted file mode 100644 index c5d87e17dbd3..000000000000 --- a/Spigot-Server-Patches/0518-Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:03:33 -0700 -Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs - -CraftBukkit has a bug in their implementation and is incorrectly handling forget -Also adds more target reasons for why it forgot target. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -index ad2e4be7483d39aeb7be3727aba6a5fe89ea9602..05c507270ff5b4c0d684d0fc4a69ee47618cd281 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -@@ -33,15 +33,15 @@ public class BehaviorAttackTargetForget extends Beha - - protected void a(WorldServer worldserver, E e0, long i) { - if (a((EntityLiving) e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper - } else if (this.c(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper - } else if (this.a(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper - } else if (!IEntitySelector.f.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } else if (this.b.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } - } - -@@ -65,17 +65,20 @@ public class BehaviorAttackTargetForget extends Beha - return optional.isPresent() && !((EntityLiving) optional.get()).isAlive(); - } - -- private void d(E e0) { -+ private void d(E e0, EntityTargetEvent.TargetReason reason) { - // CraftBukkit start -- EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); -+ // Paper start - fix this event -+ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); - if (event.isCancelled()) { - return; - } -- if (event.getTarget() != null) { -+ // comment out, bad logic - bad -+ /*if (event.getTarget() != null) { - e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); - return; -- } -+ }*/ -+ // Paper end - // CraftBukkit end - e0.getBehaviorController().removeMemory(MemoryModuleType.ATTACK_TARGET); - } diff --git a/Spigot-Server-Patches/0519-Add-entity-liquid-API.patch b/Spigot-Server-Patches/0519-Add-entity-liquid-API.patch deleted file mode 100644 index abbec1c1e731..000000000000 --- a/Spigot-Server-Patches/0519-Add-entity-liquid-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:43 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 27e5ba64ed6406c1ece318bf79fca0f261a77818..743d4725c0a26a8abd0a98eed2ec45ffba6211ad 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1166,12 +1166,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.inWater; - } - -- private boolean isInRain() { -+ public boolean isInRain() { // Paper - private -> public - BlockPosition blockposition = this.getChunkCoordinates(); - - return this.world.isRainingAt(blockposition) || this.world.isRainingAt(new BlockPosition((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); - } - -+ public final boolean isInBubbleColumn() { return k(); } // Paper - OBFHELPER - private boolean k() { - return this.world.getType(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); - } -@@ -1185,6 +1186,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain() || this.k(); - } - -+ public final boolean isInWaterOrBubbleColumn() { return aH(); } // Paper - OBFHELPER - public boolean aH() { - return this.isInWater() || this.k(); - } -@@ -1327,6 +1329,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.O == tag; - } - -+ public final boolean isInLava() { return aQ(); } // Paper - OBFHELPER - public boolean aQ() { - return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 266b2cbd6bfaf10743929a1eeb9732a5d1fb4c62..387f6f6fa9bbb1cce544cfb907f68c7993752dd7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1137,5 +1137,29 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { - return getHandle().spawnReason; - } -+ -+ public boolean isInRain() { -+ return getHandle().isInRain(); -+ } -+ -+ public boolean isInBubbleColumn() { -+ return getHandle().isInBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRain() { -+ return getHandle().isInWaterOrRain(); -+ } -+ -+ public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); -+ } -+ -+ public boolean isInLava() { -+ return getHandle().isInLava(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch b/Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch deleted file mode 100644 index 2398718e403c..000000000000 --- a/Spigot-Server-Patches/0520-Update-itemstack-legacy-name-and-lore.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 1 Jul 2020 11:57:40 -0500 -Subject: [PATCH] Update itemstack legacy name and lore - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index b88aec3b97d43018cf2733bad069a90338aa98cb..800d10db92a956d3ca8a3d569d12862f36044ee9 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -27,6 +27,7 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatComponentUtils; - import net.minecraft.network.chat.ChatHoverable; -@@ -137,6 +138,44 @@ public final class ItemStack { - list.sort((Comparator) enchantSorter); // Paper - } catch (Exception ignored) {} - } -+ -+ private void processText() { -+ NBTTagCompound display = getSubTag("display"); -+ if (display != null) { -+ if (display.hasKeyOfType("Name", 8)) { -+ String json = display.getString("Name"); -+ if (json != null && json.contains("\u00A7")) { -+ try { -+ display.set("Name", convert(json)); -+ } catch (JsonParseException jsonparseexception) { -+ display.remove("Name"); -+ } -+ } -+ } -+ if (display.hasKeyOfType("Lore", 9)) { -+ NBTTagList list = display.getList("Lore", 8); -+ for (int index = 0; index < list.size(); index++) { -+ String json = list.getString(index); -+ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json -+ try { -+ list.set(index, convert(json)); -+ } catch (JsonParseException e) { -+ list.set(index, NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new ChatComponentText("")))); -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ private NBTTagString convert(String json) { -+ IChatBaseComponent component = IChatBaseComponent.ChatSerializer.jsonToComponent(json); -+ if (component instanceof ChatComponentText && component.getText().contains("\u00A7") && component.getSiblings().isEmpty()) { -+ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components -+ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getText())[0]; -+ } -+ return NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); -+ } - // Paper end - - public ItemStack(IMaterial imaterial) { -@@ -182,6 +221,7 @@ public final class ItemStack { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); - processEnchantOrder(this.tag); // Paper -+ processText(); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -665,6 +705,7 @@ public final class ItemStack { - } - } - -+ @Nullable public NBTTagCompound getSubTag(String s) { return b(s); } // Paper - OBFHELPER - @Nullable - public NBTTagCompound b(String s) { - return this.tag != null && this.tag.hasKeyOfType(s, 10) ? this.tag.getCompound(s) : null; diff --git a/Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch b/Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch deleted file mode 100644 index 0810b4a11b47..000000000000 --- a/Spigot-Server-Patches/0521-Spawn-player-in-correct-world-on-login.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Fri, 3 Jul 2020 14:57:05 -0400 -Subject: [PATCH] Spawn player in correct world on login - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 4c3a2e3cfd60321b3b74d143a32aa5f5d59d7e1e..34b45a6818209245fa5692a83cf4143030057095 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -196,7 +196,18 @@ public abstract class PlayerList { - }String lastKnownName = s; // Paper - // CraftBukkit end - -- if (nbttagcompound != null) { -+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. -+ if (nbttagcompound != null && nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) { -+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); -+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); -+ if (bWorld != null) { -+ resourcekey = ((CraftWorld) bWorld).getHandle().getDimensionKey(); -+ } else { -+ resourcekey = World.OVERWORLD; -+ } -+ } else if (nbttagcompound != null) { -+ // Vanilla migration support -+ // Paper end - DataResult dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("Dimension"))); - Logger logger = PlayerList.LOGGER; - diff --git a/Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch b/Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch deleted file mode 100644 index 253b6bc4dd04..000000000000 --- a/Spigot-Server-Patches/0522-Add-PrepareResultEvent.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index e9733fd9dac89d31dbad391cb22a8c84216045db..e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -142,6 +142,7 @@ public abstract class Container { - return nonnulllist; - } - -+ public final void notifyListeners() { this.c(); } // Paper - OBFHELPER - public void c() { - int i; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index ff618bbb3fc4acfce51f5e5e6a504a63e9ad77cd..ae5674ae9c539720a657838a640050cd3b4dc5b5 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -307,6 +307,7 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - } - - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -index 949042d4e4a1a63c0477704265fe32c371543e8c..9d47f2253a8adbcecbbe3d8a0a42e62f1dac1408 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -@@ -71,6 +71,7 @@ public abstract class ContainerAnvilAbstract extends Container { - super.a(iinventory); - if (iinventory == this.repairInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -index ce3c22d6f05703874eedf634331ea92ef4c039bf..031e75dc1f3dd6fc1cee684e8e7a105b3e402127 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -@@ -148,6 +148,7 @@ public class ContainerCartography extends Container { - this.a(itemstack, itemstack1, itemstack2); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - private void a(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2) { -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index fad7355a549aef811bca43be198af3d1c0a53980..1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -157,6 +157,7 @@ public class ContainerGrindstone extends Container { - super.a(iinventory); - if (iinventory == this.craftInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 350a9b6525a95a00e72e836f1cc9e1a6b99fdd7a..7980930cc712e37a788f894bf2d2ee2b1cfc1196 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -190,7 +190,8 @@ public class ContainerLoom extends Container { - } - - this.j(); -- this.c(); -+ //this.c(); // Paper - done below -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -index 1cc0ba5b8f182ac5105d2dc493463055e32a52e5..594cbd23c5d8ee2aa88106a1f0a79db0c8ba83a3 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -@@ -79,6 +79,7 @@ public class ContainerSmithing extends ContainerAnvilAbstract { - // CraftBukkit end - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index cfcb2469569edd51bbb74ca8d7a35a1ec0ecb434..1589d9ca201d386d11d9fd57fa8ba6848bae215c 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -156,6 +156,7 @@ public class ContainerStonecutter extends Container { - this.a(iinventory, itemstack); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper - } - - private void a(IInventory iinventory, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index ce02da607d07d22cb0b71e032efa0a8f45148d0c..703f2648dde7ad1620e83f88ac4184e5803ed9b4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1531,19 +1531,44 @@ public class CraftEventFactory { - return event; - } - -- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { -- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled below -+ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end - -- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { -- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled in callPrepareResultEvent -+ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end -+ -+ // Paper start - support specific overrides for prepare result -+ public static void callPrepareResultEvent(Container container, int resultSlot) { -+ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; -+ InventoryView view = container.getBukkitView(); -+ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); -+ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; -+ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { -+ event = new PrepareAnvilEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { -+ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { -+ event = new PrepareSmithingEvent(view, result); -+ } else { -+ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); -+ } -+ event.callEvent(); -+ event.getInventory().setItem(resultSlot, event.getResult()); -+ container.notifyListeners(); -+ } -+ // Paper end - - /** - * Mob spawner event. diff --git a/Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch b/Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index 60bc951d7091..000000000000 --- a/Spigot-Server-Patches/0523-Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger -Date: Wed, 29 Apr 2020 02:10:32 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -index 60ecd3a92af0f1968b10bb8babfb43147ef568d3..9077b70650d70dd294f53a1ef73e86e28ceaece9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; - public class ChunkConverter { - - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ChunkConverter a = new ChunkConverter(); -+ public static final ChunkConverter a = new ChunkConverter(); public static ChunkConverter getEmptyConverter() { return a; } // Paper - obfhelper - private static final EnumDirection8[] c = EnumDirection8.values(); - private final EnumSet d; - private final int[][] e; -@@ -322,7 +322,7 @@ public class ChunkConverter { - if ((Integer) iblockdata.get(BlockProperties.an) >= j) { - generatoraccess.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockProperties.an, j), 18); - if (i != 7) { -- EnumDirection[] aenumdirection = null.f; -+ EnumDirection[] aenumdirection = f; // Paper - decomp fix - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 02de2c985e0dcb43ff10e686b608052e83629064..1e0546a14506a41d1a7b74d306b992cfbdf6e0cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2034,6 +2034,32 @@ public final class CraftServer implements Server { - return new CraftChunkData(world); - } - -+ // Paper start -+ @Override -+ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { -+ // get empty object -+ CraftChunkData data = (CraftChunkData) createChunkData(world); -+ // do bunch of vanilla shit -+ net.minecraft.server.level.WorldServer nmsWorld = ((CraftWorld) world).getHandle(); -+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkCoordIntPair(x, z), net.minecraft.world.level.chunk.ChunkConverter.getEmptyConverter(), nmsWorld); -+ List list = new ArrayList<>(); -+ list.add(protoChunk); -+ net.minecraft.server.level.RegionLimitedWorldAccess genRegion = new net.minecraft.server.level.RegionLimitedWorldAccess(nmsWorld, list); -+ // call vanilla generator, one feature after another. Order here is important! -+ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkProvider().chunkGenerator; -+ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { -+ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; -+ } -+ chunkGenerator.createBiomes(nmsWorld.r().b(IRegistry.ay), protoChunk); -+ chunkGenerator.buildNoise(genRegion, nmsWorld.getStructureManager(), protoChunk); -+ chunkGenerator.buildBase(genRegion, protoChunk); -+ // copy over generated sections -+ data.setRawChunkData(protoChunk.getSections()); -+ // hooray! -+ return data; -+ } -+ // Paper end -+ - @Override - public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { - return new CraftBossBar(title, color, style, flags); -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index afca0038bb74ac53f07a25729a3c1542e244c6fd..d02281f954aac8d8b65f5d36ec70f0352e4c7cdd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -19,7 +19,7 @@ import org.bukkit.material.MaterialData; - */ - public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; -- private final ChunkSection[] sections; -+ private ChunkSection[] sections; // Paper - remove final - private Set tiles; - private World world; // Paper - Anti-Xray - Add world - -@@ -168,6 +168,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - return sections; - } - -+ // Paper start -+ public void setRawChunkData(ChunkSection[] sections) { -+ this.sections = sections; -+ } -+ // Paper end -+ - Set getTiles() { - return tiles; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index 7ce7e13032fe43b8998410937d07bfffa6f01527..fb7f68887efb1de8ff9167dd110fcb52627e9206 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -33,7 +33,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; - - public class CustomChunkGenerator extends InternalChunkGenerator { - -- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; -+ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public - private final ChunkGenerator generator; - private final WorldServer world; - private final Random random = new Random(); diff --git a/Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch deleted file mode 100644 index af390a029ebf..000000000000 --- a/Spigot-Server-Patches/0524-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Jul 2020 14:59:31 -0400 -Subject: [PATCH] Don't check chunk for portal on world gen entity add - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 850225509a5398ddcc9335bf88e99bde662bfc91..a5b731bab16bf05351fee7e64ab6ae4d830309f7 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3041,7 +3041,7 @@ public abstract class EntityLiving extends Entity { - Entity entity = this.getVehicle(); - - super.stopRiding(suppressCancellation); // Paper - suppress -- if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { -+ if (entity != null && entity != this.getVehicle() && !this.world.isClientSide && entity.valid) { // Paper - don't process on world gen - this.a(entity); - } - diff --git a/Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch b/Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch deleted file mode 100644 index 267d81608fac..000000000000 --- a/Spigot-Server-Patches/0525-Optimize-NetworkManager-Exception-Handling.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sun, 5 Jul 2020 22:38:18 -0400 -Subject: [PATCH] Optimize NetworkManager Exception Handling - - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index a892521db1197369bf6363bd2f5da24bf53643ab..46d8471ba98a5f2c659d35dd86c4c20c67f1ceac 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -286,6 +286,7 @@ public enum EnumProtocol { - - @Nullable - public Packet a(int i) { -+ if (i < 0 || i >= this.b.size()) return null; // Paper - Supplier> supplier = (Supplier) this.b.get(i); - - return supplier != null ? (Packet) supplier.get() : null; -diff --git a/src/main/java/net/minecraft/network/PacketSplitter.java b/src/main/java/net/minecraft/network/PacketSplitter.java -index 2c7de7ab6da2106394ec668cd7cb9be1f8dabeb3..e81bfd35b9a745eeb1457ceda5fda320654bd89a 100644 ---- a/src/main/java/net/minecraft/network/PacketSplitter.java -+++ b/src/main/java/net/minecraft/network/PacketSplitter.java -@@ -9,11 +9,21 @@ import java.util.List; - - public class PacketSplitter extends ByteToMessageDecoder { - -+ private final byte[] lenBuf = new byte[3]; // Paper - public PacketSplitter() {} - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { -+ // Paper start - if channel is not active just discard the packet -+ if (!channelhandlercontext.channel().isActive()) { -+ bytebuf.skipBytes(bytebuf.readableBytes()); -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); -- byte[] abyte = new byte[3]; -+ // Paper start - reuse temporary length buffer -+ byte[] abyte = lenBuf; -+ java.util.Arrays.fill(abyte, (byte) 0); -+ // Paper end - - for (int i = 0; i < abyte.length; ++i) { - if (!bytebuf.isReadable()) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index b644c91cecd8a347319dfe8c8923fd05919a9795..4c583593de4dc8ab27b3e1187f4dfe1740ef07a7 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -2,8 +2,10 @@ package net.minecraft.network.protocol; - - import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -+import net.minecraft.server.level.EntityPlayer; - - public interface Packet { - -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index e47da20ab8ce4da34755e105bf55d8542fb50138..67d8fe8ad036a9252c774bb6a914c8ec79981876 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -1,6 +1,9 @@ - package net.minecraft.network.protocol; - -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketListener; -+import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; -@@ -31,6 +34,21 @@ public class PlayerConnectionUtils { - try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); - } // Paper - timings -+ // Paper start -+ catch (Exception e) { -+ NetworkManager networkmanager = t0.a(); -+ if (networkmanager.getPlayer() != null) { -+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getName(), networkmanager.getSocketAddress(), e); -+ } else { -+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getSocketAddress(), e); -+ } -+ ChatComponentText error = new ChatComponentText("Packet processing error"); -+ networkmanager.sendPacket(new PacketPlayOutKickDisconnect(error), (future) -> { -+ networkmanager.close(error); -+ }); -+ networkmanager.stopReading(); -+ } -+ // Paper end - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } diff --git a/Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch deleted file mode 100644 index 9a961b6d3041..000000000000 --- a/Spigot-Server-Patches/0526-Fix-Concurrency-issue-in-WeightedList.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Jul 2020 18:36:41 -0400 -Subject: [PATCH] Fix Concurrency issue in WeightedList - -if multiple threads from worldgen sort at same time, it will crash. -So make a copy of the list for sorting purposes. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -index dc926f7e59fa350902d4a24aefc3df3eac7d75db..2d4345de154fb2d31f34695672ebdb4dac31b181 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -@@ -17,7 +17,7 @@ public class BehaviorGate extends Behavior { - private final Set> b; - private final BehaviorGate.Order c; - private final BehaviorGate.Execution d; -- private final WeightedList> e = new WeightedList<>(); -+ private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone - - public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { - super(map); -@@ -65,10 +65,9 @@ public class BehaviorGate extends Behavior { - }).forEach((behavior) -> { - behavior.g(worldserver, e0, i); - }); -- Set set = this.b; - BehaviorController behaviorcontroller = e0.getBehaviorController(); - -- set.forEach(behaviorcontroller::removeMemory); -+ this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix - } - - @Override -@@ -115,7 +114,7 @@ public class BehaviorGate extends Behavior { - - private final Consumer> c; - -- private Order(Consumer consumer) { -+ private Order(Consumer> consumer) { // Paper - decomp fix - this.c = consumer; - } - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -index f6f8c68ff3642e28901094e8b501fcf8ec2cecd7..1ca9b0595ae9d914d23590ec0b0c2e857c39b250 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -@@ -6,7 +6,7 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; --import com.mojang.serialization.OptionalDynamic; -+ - import java.util.Comparator; - import java.util.List; - import java.util.Random; -@@ -14,26 +14,32 @@ import java.util.stream.Stream; - - public class WeightedList { - -- protected final List> a; -+ protected final List> list; // Paper - decompile conflict - private final Random b; -+ private final boolean isUnsafe; // Paper - -- public WeightedList() { -- this(Lists.newArrayList()); -+ // Paper start - add useClone option -+ public WeightedList() { this(true); } -+ public WeightedList(boolean isUnsafe) { -+ this(Lists.newArrayList(), isUnsafe); - } - -- private WeightedList(List> list) { -+ private WeightedList(List> list) { this(list, true); } -+ private WeightedList(List> list, boolean isUnsafe) { -+ this.isUnsafe = isUnsafe; -+ // Paper end - this.b = new Random(); -- this.a = Lists.newArrayList(list); -+ this.list = Lists.newArrayList(list); // Paper - decompile conflict - } - - public static Codec> a(Codec codec) { -- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { -- return weightedlist.a; -+ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict -+ return weightedlist.list; // Paper - decompile conflict - }); - } - - public WeightedList a(U u0, int i) { -- this.a.add(new WeightedList.a<>(u0, i)); -+ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict - return this; - } - -@@ -42,21 +48,20 @@ public class WeightedList { - } - - public WeightedList a(Random random) { -- this.a.forEach((weightedlist_a) -> { -- weightedlist_a.a(random.nextFloat()); -- }); -- this.a.sort(Comparator.comparingDouble((object) -> { -- return ((WeightedList.a) object).c(); -- })); -- return this; -+ // Paper start - make concurrent safe, work off a clone of the list -+ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; -+ list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); -+ list.sort(Comparator.comparingDouble(a::c)); -+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; -+ // Paper end - } - - public boolean b() { -- return this.a.isEmpty(); -+ return this.list.isEmpty(); // Paper - decompile conflict - } - - public Stream c() { -- return this.a.stream().map(WeightedList.a::a); -+ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict - } - - public U b(Random random) { -@@ -64,7 +69,7 @@ public class WeightedList { - } - - public String toString() { -- return "WeightedList[" + this.a + "]"; -+ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict - } - - public static class a { -@@ -98,11 +103,7 @@ public class WeightedList { - return new Codec>() { - public DataResult, T>> decode(DynamicOps dynamicops, T t0) { - Dynamic dynamic = new Dynamic(dynamicops, t0); -- OptionalDynamic optionaldynamic = dynamic.get("data"); -- Codec codec1 = codec; -- -- codec.getClass(); -- return optionaldynamic.flatMap(codec1::parse).map((object) -> { -+ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error - return new WeightedList.a<>(object, dynamic.get("weight").asInt(1)); - }).map((weightedlist_a) -> { - return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch b/Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch deleted file mode 100644 index 434cd1b5f5ef..000000000000 --- a/Spigot-Server-Patches/0527-Optimize-the-advancement-data-player-iteration-to-be.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Sat, 4 Jul 2020 23:07:43 -0400 -Subject: [PATCH] Optimize the advancement data player iteration to be O(N) - rather than O(N^2) - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 7d37626277823d5db05189c20bb1ebf91aa2a286..e1d3f7e63c731f9376900a86abe17282e9b55ded 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -457,6 +457,16 @@ public class AdvancementDataPlayer { - } - - private void e(Advancement advancement) { -+ // Paper start -+ e(advancement, IterationEntryPoint.ROOT); -+ } -+ private enum IterationEntryPoint { -+ ROOT, -+ ITERATOR, -+ PARENT_OF_ITERATOR -+ } -+ private void e(Advancement advancement, IterationEntryPoint entryPoint) { -+ // Paper end - boolean flag = this.f(advancement); - boolean flag1 = this.h.contains(advancement); - -@@ -472,15 +482,23 @@ public class AdvancementDataPlayer { - } - - if (flag != flag1 && advancement.b() != null) { -- this.e(advancement.b()); -+ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise -+ // market that we're entering from the parent of an iterator. -+ this.e(advancement.b(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); - } - -+ // If this is true, we've went through a child iteration, entered the parent, processed the parent -+ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. -+ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { -+ return; -+ } // Paper end -+ - Iterator iterator = advancement.e().iterator(); - - while (iterator.hasNext()) { - Advancement advancement1 = (Advancement) iterator.next(); - -- this.e(advancement1); -+ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration - } - - } diff --git a/Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch b/Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch deleted file mode 100644 index 384b4e038210..000000000000 --- a/Spigot-Server-Patches/0528-Fix-arrows-never-despawning-MC-125757.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 8 Jul 2020 11:24:30 -0500 -Subject: [PATCH] Fix arrows never despawning MC-125757 - -This forces the despawn counter to start ticking regardless of -state after the arrow has been alive for 200 ticks (10 seconds) -instead of getting stuck in a never despawn state (bubble columns, -etc). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index ce754e0da047050daa08e5e0564fa399d334c04b..b0e8e9934edbb0cf7ac063e4903452be526afbc7 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -171,6 +171,7 @@ public abstract class EntityArrow extends IProjectile { - - ++this.c; - } else { -+ if (ticksLived > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds - this.c = 0; - Vec3D vec3d2 = this.getPositionVector(); - -@@ -292,6 +293,7 @@ public abstract class EntityArrow extends IProjectile { - - } - -+ protected final void tickDespawnCounter() { this.h(); } // Paper - OBFHELPER - protected void h() { - ++this.despawnCounter; - if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch b/Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch deleted file mode 100644 index 2786d49de262..000000000000 --- a/Spigot-Server-Patches/0529-Thread-Safe-Vanilla-Command-permission-checking.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Jul 2020 03:54:28 -0400 -Subject: [PATCH] Thread Safe Vanilla Command permission checking - -Datapacks check this on load and are built concurrently. This was breaking them badly due -to race conditions. - -Plus, .canUse we want to be safe for async anyways. - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 7ef6c99d2235eed38197aa76bc9553d7efbe52a4..c0fac7369b111e65b896a15848ae22457e5e8914 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -75,10 +75,10 @@ public abstract class CommandNode implements Comparable> { - public synchronized boolean canUse(final S source) { - if (source instanceof CommandListenerWrapper) { - try { -- ((CommandListenerWrapper) source).currentCommand = this; -+ ((CommandListenerWrapper) source).currentCommand.set(this); // Paper - return requirement.test(source); - } finally { -- ((CommandListenerWrapper) source).currentCommand = null; -+ ((CommandListenerWrapper) source).currentCommand.set(null); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index b5ee789c8dfb7f413ab60902ff3d2ef0cf8273cd..8402af32cc476d7f468842eb4f34c7521d72bcc8 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -55,7 +55,7 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - private final ResultConsumer l; - private final ArgumentAnchor.Anchor m; - private final Vec2F n; -- public volatile CommandNode currentCommand; // CraftBukkit -+ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper - - public CommandListenerWrapper(ICommandListener icommandlistener, Vec3D vec3d, Vec2F vec2f, WorldServer worldserver, int i, String s, IChatBaseComponent ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity) { - this(icommandlistener, vec3d, vec2f, worldserver, i, s, ichatbasecomponent, minecraftserver, entity, false, (commandcontext, flag, j) -> { -@@ -172,9 +172,11 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -- CommandNode currentCommand = this.currentCommand; -+ // Paper start - fix concurrency issue -+ CommandNode currentCommand = this.currentCommand.get(); - if (currentCommand != null) { - return hasPermission(i, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); -+ // Paper end - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch b/Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch deleted file mode 100644 index 097afc0b77a8..000000000000 --- a/Spigot-Server-Patches/0530-Move-range-check-for-block-placing-up.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Jul 2020 19:34:11 -0700 -Subject: [PATCH] Move range check for block placing up - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 74cb85a424703e40a869568bf9c30d26a440b477..92d5a58f7d18aebf06e3cb868abf3f41825f2f84 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1662,15 +1662,19 @@ public class PlayerConnection implements PacketListenerPlayIn { - BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - -+ // Paper start - move check up -+ Location eyeLoc = this.getPlayer().getEyeLocation(); -+ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -+ return; -+ } -+ // Paper end - move check up -+ - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { - if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { - // CraftBukkit start - Check if we can actually do something over this large a distance -- Location eyeLoc = this.getPlayer().getEyeLocation(); -- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -- return; -- } -+ // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 - // CraftBukkit end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch b/Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch deleted file mode 100644 index 06e7d808b575..000000000000 --- a/Spigot-Server-Patches/0531-Fix-SPIGOT-5989.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 15 Jul 2020 21:42:52 -0400 -Subject: [PATCH] Fix SPIGOT-5989 - -Before this fix, if a player was respawning to a respawn anchor and -the respawn location was modified away from the anchor with the -PlayerRespawnEvent, the anchor would still lose some charge. -This fixes that by checking if the modified spawn location is -still at a respawn anchor. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 34b45a6818209245fa5692a83cf4143030057095..7f5311770f0a461f02039255fbbf1a48df4178f3 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -83,6 +83,7 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; -+import net.minecraft.world.level.block.BlockRespawnAnchor; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.border.IWorldBorderListener; -@@ -850,6 +851,7 @@ public abstract class PlayerList { - // Paper start - boolean isBedSpawn = false; - boolean isRespawn = false; -+ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end - - // CraftBukkit start - fire PlayerRespawnEvent -@@ -860,7 +862,7 @@ public abstract class PlayerList { - Optional optional; - - if (blockposition != null) { -- optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, flag); -+ optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 - } else { - optional = Optional.empty(); - } -@@ -903,7 +905,12 @@ public abstract class PlayerList { - } - // Spigot End - -- location = respawnEvent.getRespawnLocation(); -+ // Paper start - Fix SPIGOT-5989 -+ if (!location.equals(respawnEvent.getRespawnLocation()) ) { -+ location = respawnEvent.getRespawnLocation(); -+ isLocAltered = true; -+ } -+ // Paper end - if (!flag) entityplayer.reset(); // SPIGOT-4785 - isRespawn = true; // Paper - } else { -@@ -941,8 +948,12 @@ public abstract class PlayerList { - } - // entityplayer1.syncInventory(); - entityplayer1.setHealth(entityplayer1.getHealth()); -- if (flag2) { -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); -+ // Paper start - Fix SPIGOT-5989 -+ if (flag2 && !isLocAltered) { -+ IBlockData data = worldserver1.getType(blockposition); -+ worldserver1.setTypeAndData(blockposition, data.set(BlockRespawnAnchor.a, data.get(BlockRespawnAnchor.a) - 1), 3); -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); -+ // Paper end - } - // Added from changeDimension - updateClient(entityplayer); // Update health, etc... diff --git a/Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch deleted file mode 100644 index c65973015644..000000000000 --- a/Spigot-Server-Patches/0532-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 13:12:33 -0500 -Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 1732fc552c290d294b68d6f92f2a58d985fbef21..3dcbeec94d86f3b56eaf05676b176f60d711f9cd 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,11 +132,20 @@ public class Main { - return; - } - -- File file = (File) optionset.valueOf("universe"); // CraftBukkit -+ // Paper start - fix SPIGOT-5824 -+ File file; -+ File userCacheFile = new File("usercache.json"); -+ if (optionset.has("universe")) { -+ file = (File) optionset.valueOf("universe"); // CraftBukkit -+ userCacheFile = new File(file, "usercache.json"); -+ } else { -+ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); -+ } -+ // Paper end - fix SPIGOT-5824 - YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); -- UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -+ UserCache usercache = new UserCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container - // CraftBukkit start - String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); - Convertable convertable = Convertable.a(file.toPath()); diff --git a/Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch deleted file mode 100644 index 3c64f53489f1..000000000000 --- a/Spigot-Server-Patches/0533-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 12:38:12 -0500 -Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 3dcbeec94d86f3b56eaf05676b176f60d711f9cd..6818f8496ab76ee6ffc747bd6848b43830ec8914 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -132,6 +132,7 @@ public class Main { - return; - } - -+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init - // Paper start - fix SPIGOT-5824 - File file; - File userCacheFile = new File("usercache.json"); diff --git a/Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch deleted file mode 100644 index e8ab744e2673..000000000000 --- a/Spigot-Server-Patches/0534-Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 Jul 2020 06:22:54 -0700 -Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in - login - -Move the criterion storage to the AdvancementDataPlayer object -itself, so the criterion object stores no references - and thus -needs no cleanup. - -diff --git a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -index c2ee816af000f0c94782d704e6372cd93fd34bb3..c6388223daa26b200dc16cd562bcef19a5a59c8f 100644 ---- a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -+++ b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -@@ -16,25 +16,25 @@ import net.minecraft.world.level.storage.loot.LootTableInfo; - - public abstract class CriterionTriggerAbstract implements CriterionTrigger { - -- private final Map>> a = Maps.newIdentityHashMap(); -+ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak - - public CriterionTriggerAbstract() {} - - @Override - public final void a(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { -+ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak - return Sets.newHashSet(); - })).add(criteriontrigger_a); - } - - @Override - public final void b(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null) { - set.remove(criteriontrigger_a); - if (set.isEmpty()) { -- this.a.remove(advancementdataplayer); -+ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak - } - } - -@@ -42,7 +42,7 @@ public abstract class CriterionTriggerAbstract predicate) { - AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null && !set.isEmpty()) { - LootTableInfo loottableinfo = CriterionConditionEntity.b(entityplayer, entityplayer); -@@ -67,7 +67,7 @@ public abstract class CriterionTriggerAbstract> criterionData = Maps.newIdentityHashMap(); -+ // Paper end - fix advancement data player leakage -+ - public AdvancementDataPlayer(DataFixer datafixer, PlayerList playerlist, AdvancementDataWorld advancementdataworld, File file, EntityPlayer entityplayer) { - this.d = datafixer; - this.e = playerlist; diff --git a/Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch deleted file mode 100644 index 6c0360c41108..000000000000 --- a/Spigot-Server-Patches/0535-Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 26 Jul 2020 12:11:39 +0100 -Subject: [PATCH] Add missing strikeLighting call to - World#spigot()#strikeLightningEffect - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 80cd8ce4e70dbb740439ac530a7bc70a7a54cb85..74ee2013a47855cdd1d56a06a2e209776513fd14 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2627,6 +2627,7 @@ public class CraftWorld implements World { - lightning.teleportAndSync( loc.getX(), loc.getY(), loc.getZ() ); - lightning.isEffect = true; - lightning.isSilent = isSilent; -+ world.strikeLightning( lightning ); - return (LightningStrike) lightning.getBukkitEntity(); - } - }; diff --git a/Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch b/Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch deleted file mode 100644 index 9241cffb872c..000000000000 --- a/Spigot-Server-Patches/0536-Fix-some-rails-connecting-improperly.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 24 Jul 2020 15:56:05 -0700 -Subject: [PATCH] Fix some rails connecting improperly - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -index 61c4a57174237f5f77d841bb2274ace6297db8a4..27573a0334b06f4b6ada672057695d8f8a2bcfc4 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -@@ -71,6 +71,7 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { - - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.canPlace(iblockdata, world, blockposition)) { -+ if (iblockdata.getBlock() != this) { return; } // Paper - not our block, don't do anything - boolean flag = (Boolean) iblockdata.get(BlockMinecartDetector.POWERED); - boolean flag1 = false; - List list = this.a(world, blockposition, EntityMinecartAbstract.class, (Predicate) null); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -index f65a53347f26affd1ce8d79527a6486e6bf8fbdd..0545dd68ea1f0a27739fac1a358c7def849e6b6a 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -@@ -62,6 +62,7 @@ public abstract class BlockMinecartTrackAbstract extends Block { - iblockdata = this.a(world, blockposition, iblockdata, true); - if (this.c) { - iblockdata.doPhysics(world, blockposition, this, blockposition, flag); -+ iblockdata = world.getType(blockposition); // Paper - don't desync, update again - } - - return iblockdata; -diff --git a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -index 8a8e3af0290a9483ee59d5fab061a9a9f5613f0a..436cfcde89aa780bcd58150f6167a365d8d955bc 100644 ---- a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -+++ b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -@@ -12,13 +12,19 @@ import net.minecraft.world.level.block.state.properties.BlockPropertyTrackPositi - - public class MinecartTrackLogic { - -- private final World a; -- private final BlockPosition b; -+ private final World a; public final World getWorld() { return this.a; } // Paper - OBFHELPER -+ private final BlockPosition b; public final BlockPosition getPos() { return this.b; } // Paper - OBFHELPER - private final BlockMinecartTrackAbstract c; -- private IBlockData d; -+ private IBlockData d; public final IBlockData getRailState() { return this.d; } // Paper - OBFHELPER - private final boolean e; - private final List f = Lists.newArrayList(); - -+ // Paper start - prevent desync -+ public boolean isValid() { -+ return this.getWorld().getType(this.getPos()).getBlock() == this.getRailState().getBlock(); -+ } -+ // Paper end - prevent desync -+ - public MinecartTrackLogic(World world, BlockPosition blockposition, IBlockData iblockdata) { - this.a = world; - this.b = blockposition; -@@ -153,6 +159,11 @@ public class MinecartTrackLogic { - } - - private void c(MinecartTrackLogic minecarttracklogic) { -+ // Paper start - prevent desync -+ if (!this.isValid() || !minecarttracklogic.isValid()) { -+ return; -+ } -+ // Paper end - prevent desync - this.f.add(minecarttracklogic.b); - BlockPosition blockposition = this.b.north(); - BlockPosition blockposition1 = this.b.south(); -@@ -347,11 +358,16 @@ public class MinecartTrackLogic { - this.d = (IBlockData) this.d.set(this.c.d(), blockpropertytrackposition1); - if (flag1 || this.a.getType(this.b) != this.d) { - this.a.setTypeAndData(this.b, this.d, 3); -+ // Paper start - prevent desync -+ if (!this.isValid()) { -+ return this; -+ } -+ // Paper end - prevent desync - - for (int i = 0; i < this.f.size(); ++i) { - MinecartTrackLogic minecarttracklogic = this.b((BlockPosition) this.f.get(i)); - -- if (minecarttracklogic != null) { -+ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync - minecarttracklogic.d(); - if (minecarttracklogic.b(this)) { - minecarttracklogic.c(this); -@@ -364,6 +380,6 @@ public class MinecartTrackLogic { - } - - public IBlockData c() { -- return this.d; -+ return this.getWorld().getType(this.getPos()); // Paper - prevent desync - } - } diff --git a/Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch deleted file mode 100644 index f2749926991e..000000000000 --- a/Spigot-Server-Patches/0537-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 4 Aug 2020 22:24:15 +0200 -Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections - -I utilized the IDE to convert streams to non streams code, so shouldn't -be any risk of behavior change. Only did minor optimization of the -generated code set to remove unnecessary things. - -I expect us to just drop this patch on next major update and re-apply -it with the IDE again and re-apply the collections optimization. - -Optimize collection by creating a list instead of a set of the key and value. - -This lets us get faster foreach iteration, as well as avoids map lookups on -the values when needed. - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 5784be69098805e4d550a0923ac8daa5aada73f9..76e19f3a4ae988f6f3b59763d639fa5e084fa0bf 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -33,9 +33,12 @@ public class Pathfinder { - this.d.a(); - this.c.a(chunkcache, entityinsentient); - PathPoint pathpoint = this.c.b(); -- Map map = (Map) set.stream().collect(Collectors.toMap((blockposition) -> { -- return this.c.a((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); -- }, Function.identity())); -+ // Paper start - remove streams - and optimize collection -+ List> map = Lists.newArrayList(); -+ for (BlockPosition blockposition : set) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.c.a((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); -+ } -+ // Paper end - PathEntity pathentity = this.a(pathpoint, map, f, i, f1); - - this.c.a(); -@@ -43,17 +46,17 @@ public class Pathfinder { - } - - @Nullable -- private PathEntity a(PathPoint pathpoint, Map map, float f, int i, float f1) { -- Set set = map.keySet(); -+ private PathEntity a(PathPoint pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection -+ //Set set = map.keySet(); // Paper - - pathpoint.e = 0.0F; -- pathpoint.f = this.a(pathpoint, set); -+ pathpoint.f = this.a(pathpoint, list); // Paper - optimize collection - pathpoint.g = pathpoint.f; - this.d.a(); - this.d.a(pathpoint); - Set set1 = ImmutableSet.of(); - int j = 0; -- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); -+ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection - int k = (int) ((float) this.b * f1); - - while (!this.d.e()) { -@@ -65,14 +68,15 @@ public class Pathfinder { - PathPoint pathpoint1 = this.d.c(); - - pathpoint1.i = true; -- Iterator iterator = set.iterator(); -- -- while (iterator.hasNext()) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i1 = 0; i1 < list.size(); i1++) { -+ Map.Entry entry = list.get(i1); -+ PathDestination pathdestination = entry.getKey(); - - if (pathpoint1.c((PathPoint) pathdestination) <= (float) i) { - pathdestination.e(); -- set2.add(pathdestination); -+ set2.add(entry); -+ // Paper end - } - } - -@@ -93,7 +97,7 @@ public class Pathfinder { - if (pathpoint2.j < f && (!pathpoint2.c() || f3 < pathpoint2.e)) { - pathpoint2.h = pathpoint1; - pathpoint2.e = f3; -- pathpoint2.f = this.a(pathpoint2, set) * 1.5F; -+ pathpoint2.f = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set - if (pathpoint2.c()) { - this.d.a(pathpoint2, pathpoint2.e + pathpoint2.f); - } else { -@@ -105,28 +109,29 @@ public class Pathfinder { - } - } - -- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), true); -- }).min(Comparator.comparingInt(PathEntity::e)) : set.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), false); -- }).min(Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e)); -- -- if (!optional.isPresent()) { -- return null; -- } else { -- PathEntity pathentity = (PathEntity) optional.get(); -- -- return pathentity; -+ // Paper start - remove streams - and optimize collection -+ PathEntity best = null; -+ boolean useSet1 = set2.isEmpty(); -+ Comparator comparator = useSet1 ? Comparator.comparingInt(PathEntity::e) -+ : Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e); -+ for (Map.Entry entry : useSet1 ? list : set2) { -+ PathEntity pathEntity = this.a(entry.getKey().d(), entry.getValue(), !useSet1); -+ if (best == null || comparator.compare(pathEntity, best) < 0) -+ best = pathEntity; - } -+ return best; -+ // Paper end - } - -- private float a(PathPoint pathpoint, Set set) { -+ private float a(PathPoint pathpoint, List> list) { // Paper - optimize collection - float f = Float.MAX_VALUE; - - float f1; - -- for (Iterator iterator = set.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper -+ PathDestination pathdestination = list.get(i).getKey(); // Paper -+ // Paper end - - f1 = pathpoint.a(pathdestination); - pathdestination.a(f1, pathpoint); diff --git a/Spigot-Server-Patches/0538-Incremental-player-saving.patch b/Spigot-Server-Patches/0538-Incremental-player-saving.patch deleted file mode 100644 index 3b59431d25e6..000000000000 --- a/Spigot-Server-Patches/0538-Incremental-player-saving.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Aug 2020 08:59:25 +0300 -Subject: [PATCH] Incremental player saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index b67ba8f75e4a3358d7c2462918b85b0bf9b5a922..fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -440,4 +440,15 @@ public class PaperConfig { - allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); - set("settings.unsupported-settings.allow-tnt-duplication", null); - } -+ -+ public static int playerAutoSaveRate = -1; -+ public static int maxPlayerAutoSavePerTick = 10; -+ private static void playerAutoSaveRate() { -+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); -+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); -+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" -+ // 10 should be safe for everyone unless you mass spamming player auto save -+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c3635577b1796e6ca84709469ecf95c815fe53a5..bd6b9c7be8951393e7ba731f4d6a9486f0743be7 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1348,9 +1348,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper -+ // Paper start -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ // Paper end - this.methodProfiler.enter("save"); -- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper -- this.playerList.savePlayers(); -+ if (playerSaveInterval > 0) { // Paper -+ this.playerList.savePlayers(playerSaveInterval); // Paper - }// Paper - // Paper start - for (WorldServer world : getWorlds()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8055172c806f285aa9a9e6de681d03b008fbf785..3908dc27a5cf127ab3c3630da47318da1bf4e3c9 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -176,6 +176,7 @@ import org.bukkit.inventory.MainHand; - public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); -+ public long lastSave = MinecraftServer.currentTick; // Paper - public PlayerConnection playerConnection; - public NetworkManager networkManager; // Paper - public final MinecraftServer server; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 7f5311770f0a461f02039255fbbf1a48df4178f3..d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -563,6 +563,7 @@ public abstract class PlayerList { - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit - if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) -+ entityplayer.lastSave = MinecraftServer.currentTick; // Paper - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -1222,10 +1223,21 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ // Paper start - incremental player saving -+ savePlayers(null); -+ } -+ public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper -+ int numSaved = 0; -+ long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ EntityPlayer entityplayer = this.players.get(i); -+ if (interval == null || now - entityplayer.lastSave >= interval) { -+ this.savePlayerFile(entityplayer); -+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } -+ } -+ // Paper end - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/Spigot-Server-Patches/0539-Import-fastutil-classes.patch b/Spigot-Server-Patches/0539-Import-fastutil-classes.patch deleted file mode 100644 index a367d82509c1..000000000000 --- a/Spigot-Server-Patches/0539-Import-fastutil-classes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 12 Aug 2020 11:33:04 +0200 -Subject: [PATCH] Import fastutil classes - - -diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -index 3cdae5409989ea4bad8311b0083517b7815caae1..bb09b7be91b488ebc336b2b6f5deafc0ccab27a4 100644 ---- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java -+++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -@@ -17,6 +17,7 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.world.entity.Entity; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper - import org.apache.commons.lang3.ObjectUtils; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -26,7 +27,7 @@ public class DataWatcher { - private static final Logger LOGGER = LogManager.getLogger(); - private static final Map, Integer> b = Maps.newHashMap(); - private final Entity entity; -- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL -+ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL - // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required - private boolean f = true; - private boolean g; diff --git a/Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch b/Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch deleted file mode 100644 index c694cf589854..000000000000 --- a/Spigot-Server-Patches/0540-Don-t-mark-null-chunk-sections-for-block-updates.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:41:19 +0200 -Subject: [PATCH] Don't mark null chunk sections for block updates - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index d6a5a0b17308913a5efd97cd27fabd0825ef68c6..00cebd33101916f29bbc192d531ac0fba31e037b 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -450,6 +450,7 @@ public class PlayerChunk { - this.a(world, blockposition, iblockdata); - } else { - ChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; -+ if (chunksection == null) chunksection = new ChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found - PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection, this.x); - - this.a(packetplayoutmultiblockchange, false); diff --git a/Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch b/Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch deleted file mode 100644 index 835c6e761bd1..000000000000 --- a/Spigot-Server-Patches/0541-Remove-armour-stand-double-add-to-world.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:59:26 +0200 -Subject: [PATCH] Remove armour stand double add to world - - -diff --git a/src/main/java/net/minecraft/world/item/ItemArmorStand.java b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -index dd0dc2a321f2f99cbf1060e47deec0f690d6b948..cd46df5485ebfd597ea72360a27872d46174ee19 100644 ---- a/src/main/java/net/minecraft/world/item/ItemArmorStand.java -+++ b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -@@ -53,7 +53,7 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - -- worldserver.addAllEntities(entityarmorstand); -+ // Paper - moved down - float f = (float) MathHelper.d((MathHelper.g(itemactioncontext.h() - 180.0F) + 22.5F) / 45.0F) * 45.0F; - - entityarmorstand.setPositionRotation(entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), f, 0.0F); -@@ -63,7 +63,7 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - // CraftBukkit end -- world.addEntity(entityarmorstand); -+ worldserver.addAllEntities(entityarmorstand); // Paper - moved down - world.playSound((EntityHuman) null, entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), SoundEffects.ENTITY_ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); - } - diff --git a/Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch b/Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch deleted file mode 100644 index ba23e86875fb..000000000000 --- a/Spigot-Server-Patches/0542-Fix-MC-187716-Use-configured-height.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 15 Aug 2020 08:04:49 -0500 -Subject: [PATCH] Fix MC-187716 Use configured height - - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -index 9efe3a1dc5da760f0d8b0b39a10e642a53321aa5..ea2b107cddc7c9a6e8b8a0590e3b22a9cd7e34a6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -@@ -36,7 +36,7 @@ public class WorldGenSurfaceNether extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -index 22926296e66866c7fca13466004c20a16e94dc47..b9523f5611b5b8d786fddcc5fd265e8a2043ab6c 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -@@ -44,7 +44,7 @@ public abstract class WorldGenSurfaceNetherAbstract extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata5 = ichunkaccess.getType(blockposition_mutableblockposition); - int l2; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -index 3bd78b0fc75a536e4e37f5ac67843ff778cd1b5f..a2abfc8816f2dad6c95aa89b443af0d3dec480aa 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -@@ -34,7 +34,7 @@ public class WorldGenSurfaceNetherForest extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata3 = worldgensurfaceconfigurationbase.a(); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); diff --git a/Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch deleted file mode 100644 index fb98e08a740d..000000000000 --- a/Spigot-Server-Patches/0543-Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mbax -Date: Mon, 17 Aug 2020 12:17:37 -0400 -Subject: [PATCH] Fix regex mistake in CB NBT int deserialization - -The existing regex is too open and allows for the absence of any actual -number data, detecting an NBT entry of just the letter "i" in upper or -lower case. This causes a single-character NBT entry to be processed as -an integer ending in "i", passing an empty String to to Integer.parseInt, -triggering an exception in loading the item. - -This commit forces numbers to be present prior to the ending "i" -letter. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -index 1c5d62abcb968c2a60034e717aeb6d0df6548b92..83985a5aed4db54880c16228990abb3e495b079a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -@@ -19,7 +19,7 @@ import net.minecraft.nbt.NBTTagString; - public class CraftNBTTagConfigSerializer { - - private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); -- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); -+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex - private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); - private static final MojangsonParser MOJANGSON_PARSER = new MojangsonParser(new StringReader("")); - diff --git a/Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch b/Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch deleted file mode 100644 index 1848cd99d4dc..000000000000 --- a/Spigot-Server-Patches/0544-Do-not-let-the-server-load-chunks-from-newer-version.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 23 Jul 2019 20:44:47 -0500 -Subject: [PATCH] Do not let the server load chunks from newer versions - -If the server attempts to load a chunk generated by a newer version of -the game, immediately stop the server to prevent data corruption. - -You can override this functionality at your own peril. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 8e4924cd649c350520cba54a0e1497d5acf089ff..2e5221bc1b9e260e33f2cef2653dc59d05e2680d 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -95,10 +95,24 @@ public class ChunkRegionLoader { - return holder.protoChunk; - } - -+ // Paper start -+ private static final int CURRENT_DATA_VERSION = SharedConstants.getGameVersion().getWorldVersion(); -+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); -+ // Paper end -+ - public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); -+ // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.hasKeyOfType("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); -+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { -+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); -+ System.exit(1); -+ } -+ } -+ // Paper end - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/Spigot-Server-Patches/0545-Brand-support.patch b/Spigot-Server-Patches/0545-Brand-support.patch deleted file mode 100644 index 561373dfe0a6..000000000000 --- a/Spigot-Server-Patches/0545-Brand-support.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Sat, 11 Apr 2020 13:10:58 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 92d5a58f7d18aebf06e3cb868abf3f41825f2f84..1d154ef60fd979340cf925748251669e860d4094 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -5,6 +5,7 @@ import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; - import com.mojang.brigadier.ParseResults; - import com.mojang.brigadier.StringReader; -+import io.netty.buffer.Unpooled; - import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; - import it.unimi.dsi.fastutil.ints.Int2ShortMap; -@@ -37,6 +38,7 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.NetworkManager; -+import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.ChatMessageType; -@@ -260,6 +262,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - -+ private String clientBrandName = null; // Paper - Brand name -+ - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; - this.networkManager = networkmanager; -@@ -2999,6 +3003,8 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); - private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); - -+ private static final MinecraftKey MINECRAFT_BRAND = new MinecraftKey("brand"); // Paper - Brand support -+ - @Override - public void a(PacketPlayInCustomPayload packetplayincustompayload) { - PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.getWorldServer()); -@@ -3026,6 +3032,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - try { - byte[] data = new byte[packetplayincustompayload.data.readableBytes()]; - packetplayincustompayload.data.readBytes(data); -+ -+ // Paper start - Brand support -+ if (packetplayincustompayload.tag.equals(MINECRAFT_BRAND)) { -+ try { -+ this.clientBrandName = new PacketDataSerializer(Unpooled.copiedBuffer(data)).readUTF(256); -+ } catch (StringIndexOutOfBoundsException ex) { -+ this.clientBrandName = "illegal"; -+ } -+ } -+ // Paper end - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -3035,6 +3051,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - - } - -+ // Paper start - brand support -+ public String getClientBrandName() { -+ return clientBrandName; -+ } -+ // Paper end -+ - public final boolean isDisconnected() { - return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0f8d10c2bc7728b58528096fc0686c3aeee623a7..18d7cf6e783843d44715210b7c8db7bf0a5c89ae 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2388,6 +2388,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper end - }; - -+ // Paper start - brand support -+ @Override -+ public String getClientBrandName() { -+ return getHandle().playerConnection != null ? getHandle().playerConnection.getClientBrandName() : null; -+ } -+ // Paper end -+ - public Player.Spigot spigot() - { - return spigot; diff --git a/Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch deleted file mode 100644 index 61129f1906ad..000000000000 --- a/Spigot-Server-Patches/0546-Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 19:24:13 -0700 -Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until - invulnerability period is over - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 174eb12722872182b2d9b54841e5bb57893695a1..30290c0208a4725b2eb0e7764465c354e592e4ee 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -393,8 +393,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit - } - -- this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); -+ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down - } -+ this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) - } - - public static boolean c(IBlockData iblockdata) { diff --git a/Spigot-Server-Patches/0547-Fix-MC-197271.patch b/Spigot-Server-Patches/0547-Fix-MC-197271.patch deleted file mode 100644 index 5c61d89c86db..000000000000 --- a/Spigot-Server-Patches/0547-Fix-MC-197271.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ishland -Date: Sun, 23 Aug 2020 10:57:44 +0200 -Subject: [PATCH] Fix MC-197271 - -This patch only fixes an issue for servers running OpenJ9. - -diff --git a/src/main/java/net/minecraft/data/RegistryGeneration.java b/src/main/java/net/minecraft/data/RegistryGeneration.java -index 25762daca063ff5a422975d7fe64752a2deae163..2c06e3ab167443ac54c27cfe09e279f18a9f7300 100644 ---- a/src/main/java/net/minecraft/data/RegistryGeneration.java -+++ b/src/main/java/net/minecraft/data/RegistryGeneration.java -@@ -48,11 +48,11 @@ public class RegistryGeneration { - public static final IRegistry g = a(IRegistry.aw, () -> { - return ProcessorLists.b; - }); -- public static final IRegistry h = a(IRegistry.ax, WorldGenFeaturePieces::a); -+ public static final IRegistry h = a(IRegistry.ax, () -> WorldGenFeaturePieces.a()); // Paper - MC-197271 - public static final IRegistry WORLDGEN_BIOME = a(IRegistry.ay, () -> { - return BiomeRegistry.a; - }); -- public static final IRegistry j = a(IRegistry.ar, GeneratorSettingBase::i); -+ public static final IRegistry j = a(IRegistry.ar, () -> GeneratorSettingBase.i()); // Paper - MC-197271 - - private static IRegistry a(ResourceKey> resourcekey, Supplier supplier) { - return a(resourcekey, Lifecycle.stable(), supplier); -@@ -66,9 +66,9 @@ public class RegistryGeneration { - MinecraftKey minecraftkey = resourcekey.a(); - - RegistryGeneration.k.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = RegistryGeneration.l; -+ IRegistryWritable iregistrywritable = (IRegistryWritable) RegistryGeneration.l; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a((ResourceKey) resourcekey, r0, lifecycle); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, String s, T t0) { -@@ -76,11 +76,11 @@ public class RegistryGeneration { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, ResourceKey resourcekey, T t0) { -- return ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static void a() {} diff --git a/Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch b/Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch deleted file mode 100644 index fd35ea34e419..000000000000 --- a/Spigot-Server-Patches/0548-MC-197883-Bandaid-decode-issue.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 21 Aug 2020 21:05:28 -0400 -Subject: [PATCH] MC-197883: Bandaid decode issue - -Mojang has a mix of type and name in the data sets, but you can only -use one. - -This will retry as name if type is asked for and not found. - -diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644 ---- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -+++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -@@ -48,7 +48,12 @@ public class KeyDispatchCodec extends MapCodec { - - @Override - public DataResult decode(final DynamicOps ops, final MapLike input) { -- final T elementName = input.get(typeKey); -+ // Paper start - bandaid MC-197883 -+ T elementName = input.get(typeKey); -+ if (elementName == null && "type".equals(typeKey)) { -+ elementName = input.get("name"); -+ } -+ // Paper end - if (elementName == null) { - return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); - } diff --git a/Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch b/Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch deleted file mode 100644 index 2ee36075a08e..000000000000 --- a/Spigot-Server-Patches/0549-Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:30 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index d3f3dc4ad2c758482b7a8d5c07caa526ce1e3424..8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -145,7 +145,7 @@ public abstract class PlayerList { - public final WorldNBTStorage playerFileData; - private boolean hasWhitelist; - private final IRegistryCustom.Dimension s; -- protected final int maxPlayers; -+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter - private int viewDistance; - private EnumGamemode u; - private boolean v; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1e0546a14506a41d1a7b74d306b992cfbdf6e0cf..53254ad9e775e9e78da238a54be7d3fc4b8a6ced 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -618,6 +618,13 @@ public final class CraftServer implements Server { - return playerList.getMaxPlayers(); - } - -+ // Paper start -+ @Override -+ public void setMaxPlayers(int maxPlayers) { -+ this.playerList.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - // NOTE: These are dependent on the corresponding call in MinecraftServer - // so if that changes this will need to as well - @Override diff --git a/Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch b/Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index 22fffc954ce5..000000000000 --- a/Spigot-Server-Patches/0550-Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:22 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 5563e7c1ecc9e607ba0be21ae16a544b24d6f030..090e0931df410526cb7b0aab196a01f57ffbb285 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -814,5 +814,9 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - } - } - -+ @Override -+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { -+ getHandle().receive(((CraftItem) item).getHandle(), quantity); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch b/Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch deleted file mode 100644 index 00f9b23e6f25..000000000000 --- a/Spigot-Server-Patches/0551-Don-t-require-FACING-data.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 23 Aug 2020 19:01:04 +0200 -Subject: [PATCH] Don't require FACING data - - -diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -index 979b862284ecd0dc504ee8a7018b27ff569b7b85..3d14ec72bb9babdf6b24aca3bde06d8b54815f9d 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -+++ b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -@@ -15,20 +15,22 @@ import org.bukkit.event.block.BlockDispenseEvent; - // CraftBukkit end - - public class DispenseBehaviorItem implements IDispenseBehavior { -+ private EnumDirection enumdirection; // Paper - - public DispenseBehaviorItem() {} - - @Override - public final ItemStack dispense(ISourceBlock isourceblock, ItemStack itemstack) { -+ enumdirection = isourceblock.getBlockData().get(BlockDispenser.FACING); // Paper - cache facing direction - ItemStack itemstack1 = this.a(isourceblock, itemstack); - - this.a(isourceblock); -- this.a(isourceblock, (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING)); -+ this.a(isourceblock, enumdirection); // Paper - cache facing direction - return itemstack1; - } - - protected ItemStack a(ISourceBlock isourceblock, ItemStack itemstack) { -- EnumDirection enumdirection = (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING); -+ // Paper - cached enum direction - IPosition iposition = BlockDispenser.a(isourceblock); - ItemStack itemstack1 = itemstack.cloneAndSubtract(1); - diff --git a/Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch deleted file mode 100644 index 427d7d68c1a3..000000000000 --- a/Spigot-Server-Patches/0552-Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 22 Aug 2020 23:36:21 +0200 -Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 5401db70b4516ab960cffae0aae9b3ea297288b5..68a2fef79eae006ea7a8de1fc903e7000b6aab85 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1987,12 +1987,14 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ public final void setSpawn(BlockPosition blockposition, float f) { this.a(blockposition, f); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, float f) { - // Paper - configurable spawn radius - BlockPosition prevSpawn = this.getSpawn(); - //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -+ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper - if (this.keepSpawnInMemory) { - // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add - this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 74ee2013a47855cdd1d56a06a2e209776513fd14..d3f5a3d4872665b4c52a6cfad1518016919557d0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -389,11 +389,13 @@ public class CraftWorld implements World { - public boolean setSpawnLocation(int x, int y, int z, float angle) { - try { - Location previousLocation = getSpawnLocation(); -- world.worldData.setSpawn(new BlockPosition(x, y, z), angle); -+ world.setSpawn(new BlockPosition(x, y, z), angle); // Paper - use WorldServer#setSpawn - -+ // Paper start - move to nms.World - // Notify anyone who's listening. -- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -- server.getPluginManager().callEvent(event); -+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -+ // server.getPluginManager().callEvent(event); -+ // Paper end - - return true; - } catch (Exception e) { diff --git a/Spigot-Server-Patches/0553-Add-moon-phase-API.patch b/Spigot-Server-Patches/0553-Add-moon-phase-API.patch deleted file mode 100644 index c49db870414c..000000000000 --- a/Spigot-Server-Patches/0553-Add-moon-phase-API.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:11 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d3f5a3d4872665b4c52a6cfad1518016919557d0..76a7889b49a16ddeb8f310d3a79cfee80ad9a1db 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -328,6 +328,11 @@ public class CraftWorld implements World { - public int getPlayerCount() { - return world.players.size(); - } -+ -+ @Override -+ public io.papermc.paper.world.MoonPhase getMoonPhase() { -+ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); -+ } - // Paper end - - private static final Random rand = new Random(); diff --git a/Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch b/Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch deleted file mode 100644 index f6e166986f32..000000000000 --- a/Spigot-Server-Patches/0554-Prevent-headless-pistons-from-being-created.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: commandblockguy -Date: Fri, 14 Aug 2020 14:44:14 -0500 -Subject: [PATCH] Prevent headless pistons from being created - -Prevent headless pistons from being created by explosions or tree/mushroom growth. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index fdbd8b89bb8bf3b61f60b812b90483c98a3d5ccb..faa1b775e45563b93ac1d5b904938b1f5ad8d80c 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -441,6 +441,12 @@ public class PaperConfig { - set("settings.unsupported-settings.allow-tnt-duplication", null); - } - -+ public static boolean allowHeadlessPistons; -+ private static void allowHeadlessPistons() { -+ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); -+ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); -+ } -+ - public static int playerAutoSaveRate = -1; - public static int maxPlayerAutoSavePerTick = 10; - private static void playerAutoSaveRate() { -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0b3479aae8f7cad7bd0b8b64aa2dead43baf4c56..79008bda42558ea7d28ccf51b66405a3bdb52da7 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -16,6 +16,7 @@ import java.util.Set; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; - import net.minecraft.core.particles.Particles; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -34,6 +35,8 @@ import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.piston.BlockPistonExtension; -+import net.minecraft.world.level.block.piston.TileEntityPiston; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.storage.loot.LootTableInfo; -@@ -163,6 +166,15 @@ public class Explosion { - - if (f > 0.0F && this.l.a(this, this.world, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions - set.add(blockposition); -+ // Paper start - prevent headless pistons from forming -+ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { -+ TileEntity extension = this.world.getTileEntity(blockposition); -+ if (extension instanceof TileEntityPiston && ((TileEntityPiston) extension).isHead()) { -+ EnumDirection direction = iblockdata.get(BlockPistonExtension.FACING); -+ set.add(blockposition.shift(direction.opposite())); -+ } -+ } -+ // Paper end - } - - d4 += d0 * 0.30000001192092896D; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index e70c3a8c9075b6c0bc73e6488d784dfe3b86e58d..58c7a52612fe0f5c1e4ddacc0bf93cd81f1286b8 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -65,6 +65,8 @@ public class TileEntityPiston extends TileEntity implements ITickable { - return this.b; - } - -+ public final boolean isHead() { return this.h(); } // Paper - OBFHELPER -+ - public boolean h() { - return this.g; - } diff --git a/Spigot-Server-Patches/0555-Add-BellRingEvent.patch b/Spigot-Server-Patches/0555-Add-BellRingEvent.patch deleted file mode 100644 index 6352b441280d..000000000000 --- a/Spigot-Server-Patches/0555-Add-BellRingEvent.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Sun, 23 Aug 2020 13:04:02 +0200 -Subject: [PATCH] Add BellRingEvent - -Add a new event, BellRingEvent, to trigger whenever a player rings a -village bell. Passes along the bell block and the player who rang it. - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBell.java b/src/main/java/net/minecraft/world/level/block/BlockBell.java -index 687f7acd8254294b568c9adf3e72d02d12551381..24754057bc83577f4854262bbb82db355591270e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBell.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBell.java -@@ -1,8 +1,11 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.BellRingEvent; -+ - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; -@@ -89,7 +92,7 @@ public class BlockBell extends BlockTileEntity { - boolean flag1 = !flag || this.a(iblockdata, enumdirection, movingobjectpositionblock.getPos().y - (double) blockposition.getY()); - - if (flag1) { -- boolean flag2 = this.a(world, blockposition, enumdirection); -+ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper - - if (flag2 && entityhuman != null) { - entityhuman.a(StatisticList.BELL_RING); -@@ -123,6 +126,11 @@ public class BlockBell extends BlockTileEntity { - } - - public boolean a(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection) { -+ // Paper start - add ringer param -+ return this.handleBellRing(world, blockposition, enumdirection, null); -+ } -+ public boolean handleBellRing(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection, @Nullable Entity ringer) { -+ // Paper end - TileEntity tileentity = world.getTileEntity(blockposition); - - if (!world.isClientSide && tileentity instanceof TileEntityBell) { -@@ -130,6 +138,7 @@ public class BlockBell extends BlockTileEntity { - enumdirection = (EnumDirection) world.getType(blockposition).get(BlockBell.a); - } - -+ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent - ((TileEntityBell) tileentity).a(enumdirection); - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_BELL_USE, SoundCategory.BLOCKS, 2.0F, 1.0F); - return true; diff --git a/Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch b/Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch deleted file mode 100644 index 2d5c7f12aa10..000000000000 --- a/Spigot-Server-Patches/0556-Add-zombie-targets-turtle-egg-config.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:47:34 +0200 -Subject: [PATCH] Add zombie targets turtle egg config - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 978062774c1db286bfb9b0ffdef19d880b1f249b..36ecdfce84141ac731b827e469ac842f5c666259 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -668,4 +668,9 @@ public class PaperWorldConfig { - maxLightningFlashDistance = 512; // Vanilla value - } - } -+ -+ public boolean zombiesTargetTurtleEggs = true; -+ private void zombiesTargetTurtleEggs() { -+ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 3d8d4a43e6cd554b6f1eeafa1c8d43cef877139a..87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -107,7 +107,7 @@ public class EntityZombie extends EntityMonster { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); -+ if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); - this.m(); diff --git a/Spigot-Server-Patches/0557-Buffer-joins-to-world.patch b/Spigot-Server-Patches/0557-Buffer-joins-to-world.patch deleted file mode 100644 index 5237f7efdb3c..000000000000 --- a/Spigot-Server-Patches/0557-Buffer-joins-to-world.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 19 Aug 2020 05:05:54 +0100 -Subject: [PATCH] Buffer joins to world - -This patch buffers the number of logins which will attempt to join -the world per tick, this attempts to reduce the impact that join floods -has on the server - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index faa1b775e45563b93ac1d5b904938b1f5ad8d80c..545948f20efd6c8dd42140b565af94cd6b52b661 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -457,4 +457,9 @@ public class PaperConfig { - maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; - } - } -+ -+ public static int maxJoinsPerTick; -+ private static void maxJoinsPerTick() { -+ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); -+ } - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index ab70eeaeca222de7de7cab1b3db14b2c4761c3c3..878f879f8d410c428ad8a4c49e0c86c559bc47a9 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -33,6 +33,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; - import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; -@@ -382,10 +383,22 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - // Paper end - -+ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper -+ private static int joinAttemptsThisTick; // Paper -+ private static int currTick; // Paper - public void a() { - this.p(); -+ // Paper start -+ if (currTick != MinecraftServer.currentTick) { -+ currTick = MinecraftServer.currentTick; -+ joinAttemptsThisTick = 0; -+ } -+ // Paper end - if (this.packetListener instanceof LoginListener) { -+ if ( ((LoginListener) this.packetListener).getLoginState() != LoginListener.EnumProtocolState.READY_TO_ACCEPT // Paper -+ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick - ((LoginListener) this.packetListener).tick(); -+ } // Paper - } - - if (this.packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 06e2b48ed6d6d52d0eb17301254ed07fb69cb8af..e9fc38f69af815f021a08a94dd41b91171dbf2d6 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -417,7 +417,7 @@ public class LoginListener implements PacketLoginInListener { - return new GameProfile(uuid, gameprofile.getName()); - } - -- static enum EnumProtocolState { -+ public enum EnumProtocolState { // Paper - package private -> public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch b/Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch deleted file mode 100644 index 4e538c9eb352..000000000000 --- a/Spigot-Server-Patches/0558-Optimize-redstone-algorithm.patch +++ /dev/null @@ -1,1158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: theosib -Date: Thu, 27 Sep 2018 01:43:35 -0600 -Subject: [PATCH] Optimize redstone algorithm - -Author: theosib -Co-authored-by: egg82 - -Original license: MIT - -This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. -The new algorithms should be many times faster than current vanilla ones. -From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. - -Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. -A lot of this code is self-contained in a helper class. - -Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. -Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 36ecdfce84141ac731b827e469ac842f5c666259..02bb85364560784adea47c877c13291c3d016b86 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -673,4 +673,14 @@ public class PaperWorldConfig { - private void zombiesTargetTurtleEggs() { - zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); - } -+ -+ public boolean useEigencraftRedstone = false; -+ private void useEigencraftRedstone() { -+ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); -+ if (useEigencraftRedstone) { -+ log("Using Eigencraft redstone algorithm by theosib."); -+ } else { -+ log("Using vanilla redstone algorithm."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..167e0aaec8c2f83856465b7efc9ac9e5f9389d91 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -0,0 +1,914 @@ -+package com.destroystokyo.paper.util; -+ -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ThreadLocalRandom; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockRedstoneWire; -+import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.event.block.BlockRedstoneEvent; -+ -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+ -+/** -+ * Used for the faster redstone algorithm. -+ * Original author: theosib -+ * Original license: MIT -+ * -+ * Ported to Paper and updated to 1.13 by egg82 -+ */ -+public class RedstoneWireTurbo { -+ /* -+ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive -+ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks -+ * in order to more efficiently and deterministically compute new redstone wire power levels -+ * and determine the order in which other blocks should be updated. -+ * -+ * Features: -+ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the -+ * choice between old and new redstone wire update algorithms is switchable on-line. -+ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone -+ * wire blocks to communicate power level changes to each other, generating 36 block -+ * updates per call. This improved implementation propagates power level changes directly -+ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, -+ * and block updates are sent only to non-redstone blocks, many of which may perform an -+ * action when informed of a change in redstone power level. (Note: Block updates are not -+ * the same as state changes to redstone wire. Wire block states are updated as soon -+ * as they are computed.) -+ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, -+ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). -+ * These are eliminated. -+ * - Updates to redstone wire and other connected blocks are propagated in a breath-first -+ * manner, radiating out from the initial trigger (a block update to a redstone wire -+ * from something other than redstone wire). -+ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug -+ * MC-11193. -+ * - All redstone behavior that used to be locational now works the same in all locations. -+ * - All behaviors of redstone wire that used to be orientational now work the same in all -+ * orientations, as long as orientation can be determined; random otherwise. Some other -+ * redstone components still update directionally (e.g. switches), and this code can't -+ * compensate for that. -+ * - Information that is otherwise computed over and over again or which is expensive to -+ * to compute is cached for faster lookup. This includes coordinates of block position -+ * neighbors and block states that won't change behind our backs during the execution of -+ * this search algorithm. -+ * - Redundant block updates (both to redstone wire and to other blocks) are heavily -+ * consolidated. For worst-case scenarios (depowering of redstone wire) this results -+ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, -+ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. -+ * -+ * Extensive testing has been performed to ensure that existing redstone contraptions still -+ * behave as expected. Results of early testing that identified undesirable behavior changes -+ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies -+ * With earlier implementations of this accelerator. Some compatibility adjustments and -+ * performance optimizations resulted in harmless increases in block updates above the -+ * theoretical minimum. -+ * -+ * Only a single redstone machine was found to break: An instant dropper line hack that -+ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The -+ * replacement is to lay redstone wire directly on top of the dropper line, which now works -+ * reliably in any direction. -+ * -+ * There are numerous other optimization that can be made, but those will be provided later in -+ * separate updates. This version is designed to be minimalistic. -+ * -+ * Many thanks to the following individuals for their help in testing this functionality: -+ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, -+ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, -+ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. -+ */ -+ -+ /* Reference to BlockRedstoneWire object, which uses this accelerator */ -+ private final BlockRedstoneWire wire; -+ -+ /* -+ * Implementation: -+ * -+ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the -+ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). -+ * All nodes put in Layer N are those with Manhattan distance N from the trigger -+ * position, reachable through connected redstone wire blocks. -+ * -+ * Layer 0 represents the trigger block position that was input to neighborChanged. -+ * Layer 1 contains the immediate neighbors of that position. -+ * Layer N contains the neighbors of blocks in layer N-1, not including -+ * those in previous layers. -+ * -+ * Layers enforce an update order that is a function of Manhattan distance -+ * from the initial coordinates input to neighborChanged. The same -+ * coordinates may appear in multiple layers, but redundant updates are minimized. -+ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience -+ * redstone wire changes before its layer is processed, then those updates will be merged. -+ * If a block's update has been sent, but its neighboring redstone changes -+ * after that, then another update will be sent. This preserves compatibility with -+ * machines that rely on zero-tick behavior, except that the new functionality is non- -+ * locational. -+ * -+ * Within each layer, updates are ordered left-to-right relative to the direction of -+ * information flow. This makes the implementation non-orientational. Only when -+ * this direction is ambiguous is randomness applied (intentionally). -+ */ -+ private List updateQueue0 = Lists.newArrayList(); -+ private List updateQueue1 = Lists.newArrayList(); -+ private List updateQueue2 = Lists.newArrayList(); -+ -+ public RedstoneWireTurbo(BlockRedstoneWire wire) { -+ this.wire = wire; -+ } -+ -+ /* -+ * Compute neighbors of a block. When a redstone wire value changes, previously it called -+ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in -+ * west, east, down, up, north, south order. For each of those neighbors, their own -+ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are -+ * redundant; for instance the west neighbor of a block's east neighbor. -+ * -+ * Note that this ordering is only used to create the initial list of neighbors. Once -+ * the direction of signal flow is identified, the ordering of updates is completely -+ * reorganized. -+ */ -+ public static BlockPosition[] computeAllNeighbors(final BlockPosition pos) { -+ final int x = pos.getX(); -+ final int y = pos.getY(); -+ final int z = pos.getZ(); -+ final BlockPosition[] n = new BlockPosition[24]; -+ -+ // Immediate neighbors, in the same order as -+ // World.notifyNeighborsOfStateChange, etc.: -+ // west, east, down, up, north, south -+ n[0] = new BlockPosition(x - 1, y, z); -+ n[1] = new BlockPosition(x + 1, y, z); -+ n[2] = new BlockPosition(x, y - 1, z); -+ n[3] = new BlockPosition(x, y + 1, z); -+ n[4] = new BlockPosition(x, y, z - 1); -+ n[5] = new BlockPosition(x, y, z + 1); -+ -+ // Neighbors of neighbors, in the same order, -+ // except that duplicates are not included -+ n[6] = new BlockPosition(x - 2, y, z); -+ n[7] = new BlockPosition(x - 1, y - 1, z); -+ n[8] = new BlockPosition(x - 1, y + 1, z); -+ n[9] = new BlockPosition(x - 1, y, z - 1); -+ n[10] = new BlockPosition(x - 1, y, z + 1); -+ n[11] = new BlockPosition(x + 2, y, z); -+ n[12] = new BlockPosition(x + 1, y - 1, z); -+ n[13] = new BlockPosition(x + 1, y + 1, z); -+ n[14] = new BlockPosition(x + 1, y, z - 1); -+ n[15] = new BlockPosition(x + 1, y, z + 1); -+ n[16] = new BlockPosition(x, y - 2, z); -+ n[17] = new BlockPosition(x, y - 1, z - 1); -+ n[18] = new BlockPosition(x, y - 1, z + 1); -+ n[19] = new BlockPosition(x, y + 2, z); -+ n[20] = new BlockPosition(x, y + 1, z - 1); -+ n[21] = new BlockPosition(x, y + 1, z + 1); -+ n[22] = new BlockPosition(x, y, z - 2); -+ n[23] = new BlockPosition(x, y, z + 2); -+ return n; -+ } -+ -+ /* -+ * We only want redstone wires to update redstone wires that are -+ * immediately adjacent. Some more distant updates can result -+ * in cross-talk that (a) wastes time and (b) can make the update -+ * order unintuitive. Therefore (relative to the neighbor order -+ * computed by computeAllNeighbors), updates are not scheduled -+ * for redstone wire in those non-connecting positions. On the -+ * other hand, updates will always be sent to *other* types of blocks -+ * in any of the 24 neighboring positions. -+ */ -+ private static final boolean[] update_redstone = { -+ true, true, false, false, true, true, // 0 to 5 -+ false, true, true, false, false, false, // 6 to 11 -+ true, true, false, false, false, true, // 12 to 17 -+ true, false, true, true, false, false // 18 to 23 -+ }; -+ -+ // Internal numbering for cardinal directions -+ private static final int North = 0; -+ private static final int East = 1; -+ private static final int South = 2; -+ private static final int West = 3; -+ -+ /* -+ * These lookup tables completely remap neighbor positions into a left-to-right -+ * ordering, based on the cardinal direction that is determined to be forward. -+ * See below for more explanation. -+ */ -+ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; -+ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; -+ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; -+ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; -+ -+ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block -+ * that is itself having an update computed, and this center position is marked with C. -+ * - The update position marked 0 is computed first, and the one marked 23 is last. -+ * - Forward is determined by the local direction of information flow into position C from prior updates. -+ * - The first updates are scheduled for the four positions below and above C. -+ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. -+ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). -+ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly -+ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. -+ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no -+ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C -+ * are ALSO scheduled for layer N+2. -+ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility -+ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular -+ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, -+ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including -+ * NarcolepticFrog, nessie, and Pokechu22. -+ * -+ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated -+ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch -+ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed -+ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, -+ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward -+ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be -+ * concerned about branches meeting up with each other. -+ * -+ * ^ -+ * | -+ * Forward -+ * <-- Left Right --> -+ * -+ * 18 -+ * 10 17 5 19 11 -+ * 2 8 0 12 16 4 C 6 20 9 1 13 3 -+ * 14 21 7 23 15 -+ * Further 22 Further -+ * Down Down Up Up -+ * -+ * Backward -+ * | -+ * V -+ */ -+ -+ // This allows the above remapping tables to be looked up by cardial direction index -+ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; -+ -+ /* -+ * Input: Array of UpdateNode objects in an order corresponding to the positions -+ * computed by computeAllNeighbors above. -+ * Output: Array of UpdateNode objects oriented using the above remapping tables -+ * corresponding to the identified heading (direction of information flow). -+ */ -+ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { -+ final int[] re = reordering[heading]; -+ for (int i = 0; i < 24; i++) { -+ dst[i] = src[re[i]]; -+ } -+ } -+ -+ /* -+ * Structure to keep track of redstone wire blocks and -+ * neighbors that will receive updates. -+ */ -+ private static class UpdateNode { -+ public static enum Type { -+ UNKNOWN, REDSTONE, OTHER -+ } -+ -+ IBlockData currentState; // Keep track of redstone wire value -+ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) -+ BlockPosition self; // UpdateNode's own position -+ BlockPosition parent; // Which block pos spawned/updated this node -+ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block -+ int layer; // Highest layer this node is scheduled in -+ boolean visited; // To keep track of information flow direction, visited restone wire is marked -+ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. -+ } -+ -+ /* -+ * Keep track of all block positions discovered during search and their current states. -+ * We want to remember one entry for each position. -+ */ -+ private final Map nodeCache = Maps.newHashMap(); -+ -+ /* -+ * For a newly created UpdateNode object, determine what type of block it is. -+ */ -+ private void identifyNode(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ final IBlockData oldState = worldIn.getType(pos); -+ upd1.currentState = oldState; -+ -+ // Some neighbors of redstone wire are other kinds of blocks. -+ // These need to receive block updates to inform them that -+ // redstone wire values have changed. -+ final Block block = oldState.getBlock(); -+ if (block != wire) { -+ // Mark this block as not redstone wire and therefore -+ // requiring updates -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Non-redstone blocks may propagate updates, but those updates -+ // are not handled by this accelerator. Therefore, we do not -+ // expand this position's neighbors. -+ return; -+ } -+ -+ // One job of BlockRedstoneWire.neighborChanged is to convert -+ // redstone wires to items if the block beneath was removed. -+ // With this accelerator, BlockRedstoneWire.neighborChanged -+ // is only typically called for a single wire block, while -+ // others are processed internally by the breadth first search -+ // algorithm. To preserve this game behavior, this check must -+ // be replicated here. -+ if (!wire.canPlace(null, worldIn, pos)) { -+ // Pop off the redstone dust -+ Block.a(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO -+ worldIn.setAir(pos); -+ -+ // Mark this position as not being redstone wire -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Note: Sending updates to air blocks leads to an empty method. -+ // Testing shows this to be faster than explicitly avoiding updates to -+ // air blocks. -+ return; -+ } -+ -+ // If the above conditions fail, then this is a redstone wire block. -+ upd1.type = UpdateNode.Type.REDSTONE; -+ } -+ -+ /* -+ * Given which redstone wire blocks have been visited and not visited -+ * around the position currently being updated, compute the cardinal -+ * direction that is "forward." -+ * -+ * rx is the forward direction along the West/East axis -+ * rz is the forward direction along the North/South axis -+ */ -+ static private int computeHeading(final int rx, final int rz) { -+ // rx and rz can only take on values -1, 0, and 1, so we can -+ // compute a code number that allows us to use a single switch -+ // to determine the heading. -+ final int code = (rx + 1) + 3 * (rz + 1); -+ switch (code) { -+ case 0: { -+ // Both rx and rz are -1 (northwest) -+ // Randomly choose one to be forward. -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : West; -+ } -+ case 1: { -+ // rx=0, rz=-1 -+ // Definitively North -+ return North; -+ } -+ case 2: { -+ // rx=1, rz=-1 (northeast) -+ // Choose randomly between north and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : East; -+ } -+ case 3: { -+ // rx=-1, rz=0 -+ // Definitively West -+ return West; -+ } -+ case 4: { -+ // rx=0, rz=0 -+ // Heading is completely ambiguous. Choose -+ // randomly among the four cardinal directions. -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ case 5: { -+ // rx=1, rz=0 -+ // Definitively East -+ return East; -+ } -+ case 6: { -+ // rx=-1, rz=1 (southwest) -+ // Choose randomly between south and west -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : West; -+ } -+ case 7: { -+ // rx=0, rz=1 -+ // Definitively South -+ return South; -+ } -+ case 8: { -+ // rx=1, rz=1 (southeast) -+ // Choose randomly between south and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : East; -+ } -+ } -+ -+ // We should never get here -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ -+ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) -+ // or this helper class (new) -+ private static final boolean old_current_change = false; -+ -+ /* -+ * Process a node whose neighboring redstone wire has experienced value changes. -+ */ -+ private void updateNode(final World worldIn, final UpdateNode upd1, final int layer) { -+ final BlockPosition pos = upd1.self; -+ -+ // Mark this redstone wire as having been visited so that it can be used -+ // to calculate direction of information flow. -+ upd1.visited = true; -+ -+ // Look up the last known state. -+ // Due to the way other redstone components are updated, we do not -+ // have to worry about a state changing behind our backs. The rare -+ // exception is handled by scheduleReentrantNeighborChanged. -+ final IBlockData oldState = upd1.currentState; -+ -+ // Ask the wire block to compute its power level from its neighbors. -+ // This will also update the wire's power level and return a new -+ // state if it has changed. When a wire power level is changed, -+ // calculateCurrentChanges will immediately update the block state in the world -+ // and return the same value here to be cached in the corresponding -+ // UpdateNode object. -+ IBlockData newState; -+ if (old_current_change) { -+ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); -+ } else { -+ // Looking up block state is slow. This accelerator includes a version of -+ // calculateCurrentChanges that uses cahed wire values for a -+ // significant performance boost. -+ newState = this.calculateCurrentChanges(worldIn, upd1); -+ } -+ -+ // Only inform neighbors if the state has changed -+ if (newState != oldState) { -+ // Store the new state -+ upd1.currentState = newState; -+ -+ // Inform neighbors of the change -+ propagateChanges(worldIn, upd1, layer); -+ } -+ } -+ -+ /* -+ * This identifies the neighboring positions of a new UpdateNode object, -+ * determines their types, and links those to into the graph. Then based on -+ * what nodes in the redstone wire graph have been visited, the neighbors -+ * are reordered left-to-right relative to the direction of information flow. -+ */ -+ private void findNeighbors(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ -+ // Get the list of neighbor coordinates -+ final BlockPosition[] neighbors = computeAllNeighbors(pos); -+ -+ // Temporary array of neighbors in cardinal ordering -+ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; -+ -+ // Target array of neighbors sorted left-to-right -+ upd1.neighbor_nodes = new UpdateNode[24]; -+ -+ for (int i=0; i<24; i++) { -+ // Look up each neighbor in the node cache -+ final BlockPosition pos2 = neighbors[i]; -+ UpdateNode upd2 = nodeCache.get(pos2); -+ if (upd2 == null) { -+ // If this is a previously unreached position, create -+ // a new update node, add it to the cache, and identify what it is. -+ upd2 = new UpdateNode(); -+ upd2.self = pos2; -+ upd2.parent = pos; -+ nodeCache.put(pos2, upd2); -+ identifyNode(worldIn, upd2); -+ } -+ -+ // For non-redstone blocks, any of the 24 neighboring positions -+ // should receive a block update. However, some block coordinates -+ // may contain a redstone wire that does not directly connect to the -+ // one being expanded. To avoid redundant calculations and confusing -+ // cross-talk, those neighboring positions are not included. -+ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { -+ neighbor_nodes[i] = upd2; -+ } -+ } -+ -+ // Determine the directions from which the redstone signal may have come from. This -+ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the -+ // block being expanded. -+ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); -+ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); -+ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); -+ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); -+ -+ int cx = 0, cz = 0; -+ if (fromWest) cx += 1; -+ if (fromEast) cx -= 1; -+ if (fromNorth) cz += 1; -+ if (fromSouth) cz -= 1; -+ -+ int heading; -+ if (cx==0 && cz==0) { -+ // If there is no clear direction, try to inherit the heading from ancestor nodes. -+ heading = computeHeading(upd1.xbias, upd1.zbias); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = upd1.xbias; -+ nn.zbias = upd1.zbias; -+ } -+ } -+ } else { -+ if (cx != 0 && cz != 0) { -+ // If the heading is somewhat ambiguous, try to disambiguate based on -+ // ancestor nodes. -+ if (upd1.xbias != 0) cz = 0; -+ if (upd1.zbias != 0) cx = 0; -+ } -+ heading = computeHeading(cx, cz); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = cx; -+ nn.zbias = cz; -+ } -+ } -+ } -+ -+ // Reorder neighboring UpdateNode objects according to the forward direction -+ // determined above. -+ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); -+ } -+ -+ /* -+ * For any redstone wire block in layer N, inform neighbors to recompute their states -+ * in layers N+1 and N+2; -+ */ -+ private void propagateChanges(final World worldIn, final UpdateNode upd1, final int layer) { -+ if (upd1.neighbor_nodes == null) { -+ // If this node has not been expanded yet, find its neighbors -+ findNeighbors(worldIn, upd1); -+ } -+ -+ final BlockPosition pos = upd1.self; -+ -+ // All neighbors may be scheduled for layer N+1 -+ final int layer1 = layer + 1; -+ -+ // If the node being updated (upd1) has already been expanded, then merely -+ // schedule updates to its neighbors. -+ for (int i = 0; i < 24; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ -+ // This test ensures that an UpdateNode is never scheduled to the same layer -+ // more than once. Also, skip non-connecting redstone wire blocks -+ if (upd2 != null && layer1 > upd2.layer) { -+ upd2.layer = layer1; -+ updateQueue1.add(upd2); -+ -+ // Keep track of which block updated this neighbor -+ upd2.parent = pos; -+ } -+ } -+ -+ // Nodes above and below are scheduled ALSO for layer N+2 -+ final int layer2 = layer + 2; -+ -+ // Repeat of the loop above, but only for the first four (above and below) neighbors -+ // and for layer N+2; -+ for (int i = 0; i < 4; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ if (upd2 != null && layer2 > upd2.layer) { -+ upd2.layer = layer2; -+ updateQueue2.add(upd2); -+ upd2.parent = pos; -+ } -+ } -+ } -+ -+ // The breadth-first search below will send block updates to blocks -+ // that are not redstone wire. If one of those updates results in -+ // a distant redstone wire getting an update, then this.neighborChanged -+ // will get called. This would be a reentrant call, and -+ // it is necessary to properly integrate those updates into the -+ // on-going search through redstone wire. Thus, we make the layer -+ // currently being processed visible at the object level. -+ -+ // The current layer being processed by the breadth-first search -+ private int currentWalkLayer = 0; -+ -+ private void shiftQueue() { -+ final List t = updateQueue0; -+ t.clear(); -+ updateQueue0 = updateQueue1; -+ updateQueue1 = updateQueue2; -+ updateQueue2 = t; -+ } -+ -+ /* -+ * Perform a breadth-first (layer by layer) traversal through redstone -+ * wire blocks, propagating value changes to neighbors in an order -+ * that is a function of distance from the initial call to -+ * this.neighborChanged. -+ */ -+ private void breadthFirstWalk(final World worldIn) { -+ shiftQueue(); -+ currentWalkLayer = 1; -+ -+ // Loop over all layers -+ while (updateQueue0.size()>0 || updateQueue1.size()>0) { -+ // Get the set of blocks in this layer -+ final List thisLayer = updateQueue0; -+ -+ // Loop over all blocks in the layer. Recall that -+ // this is a List, preserving the insertion order of -+ // left-to-right based on direction of information flow. -+ for (UpdateNode upd : thisLayer) { -+ if (upd.type == UpdateNode.Type.REDSTONE) { -+ // If the node is is redstone wire, -+ // schedule updates to neighbors if its value -+ // has changed. -+ updateNode(worldIn, upd, currentWalkLayer); -+ } else { -+ // If this block is not redstone wire, send a block update. -+ // Redstone wire blocks get state updates, but they don't -+ // need block updates. Only non-redstone neighbors need updates. -+ -+ // World.neighborChanged is called from -+ // World.notifyNeighborsOfStateChange, and -+ // notifyNeighborsOfStateExcept. We don't use -+ // World.notifyNeighborsOfStateChange here, since we are -+ // already keeping track of all of the neighbor positions -+ // that need to be updated. All on its own, handling neighbors -+ // this way reduces block updates by 1/3 (24 instead of 36). -+ worldIn.neighborChanged(upd.self, wire, upd.parent); -+ } -+ } -+ -+ // Move on to the next layer -+ shiftQueue(); -+ currentWalkLayer++; -+ } -+ -+ currentWalkLayer = 0; -+ } -+ -+ /* -+ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level -+ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), -+ * those updates are queued. Only once all redstone wire updates are complete will any component -+ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, -+ * will process all wire updates for one redstone line, after which the pistons will zero-tick, -+ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its -+ * own discrete wave. -+ * -+ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered -+ * by Rays Works, which works the same in vanilla. The scenario is as follows: -+ * (1) A redstone wire is conducting a signal. -+ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely -+ * separate redstone wire. -+ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of -+ * an already on-going propagation through the first wire. -+ * -+ * The vanilla code, being depth-first, would end up fully processing the second wire before going back -+ * to finish processing the first one. (Although technically, vanilla has no special concept of "being -+ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this -+ * situation special handling, where the updates for the second wire are incorporated into the schedule -+ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in -+ * order to continue processing both the first and second wire in the order of distance from the initial -+ * trigger. -+ */ -+ private IBlockData scheduleReentrantNeighborChanged(final World worldIn, final BlockPosition pos, final IBlockData newState, final BlockPosition source) { -+ if (source != null) { -+ // If the cause of the redstone wire update is known, we can use that to help determine -+ // direction of information flow. -+ UpdateNode src = nodeCache.get(source); -+ if (src == null) { -+ src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ identifyNode(worldIn, src); -+ nodeCache.put(source, src); -+ } -+ } -+ -+ // Find or generate a node for the redstone block position receiving the update -+ UpdateNode upd = nodeCache.get(pos); -+ if (upd == null) { -+ upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = pos; -+ upd.visited = true; -+ identifyNode(worldIn, upd); -+ nodeCache.put(pos, upd); -+ } -+ upd.currentState = newState; -+ -+ // Receiving this block update may mean something in the world changed. -+ // Therefore we clear the cached block info about all neighbors of -+ // the position receiving the update and then re-identify what they are. -+ if (upd.neighbor_nodes != null) { -+ for (int i=0; i<24; i++) { -+ final UpdateNode upd2 = upd.neighbor_nodes[i]; -+ if (upd2 == null) continue; -+ upd2.type = UpdateNode.Type.UNKNOWN; -+ upd2.currentState = null; -+ identifyNode(worldIn, upd2); -+ } -+ } -+ -+ // The block at 'pos' is a redstone wire and has been updated already by calling -+ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need -+ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to -+ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 -+ // and currentWalkLayer+2. -+ propagateChanges(worldIn, upd, currentWalkLayer); -+ -+ // Return here. The call stack will unwind back to the first call to -+ // updateSurroundingRedstone, whereupon the new updates just scheduled will -+ // be propagated. This also facilitates elimination of superfluous and -+ // redundant block updates. -+ return newState; -+ } -+ -+ /* -+ * New version of pre-existing updateSurroundingRedstone, which is called from -+ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a -+ * few other methods in BlockRedstoneWire. This sets off the breadth-first -+ * walk through all redstone dust connected to the initial position triggered. -+ */ -+ public IBlockData updateSurroundingRedstone(final World worldIn, final BlockPosition pos, final IBlockData state, final BlockPosition source) { -+ // Check this block's neighbors and see if its power level needs to change -+ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no -+ // cached block states at this point. -+ final IBlockData newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); -+ -+ // If no change, exit -+ if (newState == state) { -+ return state; -+ } -+ -+ // Check to see if this update was received during an on-going breadth first search -+ if (currentWalkLayer > 0 || nodeCache.size() > 0) { -+ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those -+ // neighbors may affect the world so as to cause yet another redstone wire block to receive -+ // an update. If that happens, we need to integrate those redstone wire updates into the -+ // already on-going graph walk being performed by breadthFirstWalk. -+ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); -+ } -+ // If there are no on-going walks through redstone wire, then start a new walk. -+ -+ // If the source of the block update to the redstone wire at 'pos' is known, we can use -+ // that to help determine the direction of information flow. -+ if (source != null) { -+ final UpdateNode src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ nodeCache.put(source, src); -+ identifyNode(worldIn, src); -+ } -+ -+ // Create a node representing the block at 'pos', and then propagate updates -+ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges -+ // already performs the update to the block at 'pos', so it is not added to the schedule. -+ final UpdateNode upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = source!=null ? source : pos; -+ upd.currentState = newState; -+ upd.type = UpdateNode.Type.REDSTONE; -+ upd.visited = true; -+ nodeCache.put(pos, upd); -+ propagateChanges(worldIn, upd, 0); -+ -+ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value -+ // updates in a breadth first order out from the initial update received for the block at 'pos'. -+ breadthFirstWalk(worldIn); -+ -+ // With the whole search completed, clear the list of all known blocks. -+ // We do not want to keep around state information that may be changed by other code. -+ // In theory, we could cache the neighbor block positions, but that is a separate -+ // optimization. -+ nodeCache.clear(); -+ -+ return newState; -+ } -+ -+ // For any array of neighbors in an UpdateNode object, these are always -+ // the indices of the four immediate neighbors at the same Y coordinate. -+ private static final int[] rs_neighbors = {4, 5, 6, 7}; -+ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; -+ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; -+ -+ /* -+ * Updated calculateCurrentChanges that is optimized for speed and uses -+ * the UpdateNode's neighbor array to find the redstone states of neighbors -+ * that might power it. -+ */ -+ private IBlockData calculateCurrentChanges(final World worldIn, final UpdateNode upd) { -+ IBlockData state = upd.currentState; -+ final int i = state.get(BlockRedstoneWire.POWER).intValue(); -+ int j = 0; -+ j = getMaxCurrentStrength(upd, j); -+ int l = 0; -+ -+ wire.setCanProvidePower(false); -+ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, -+ // and I'm not ready to try to replicate even more functionality from -+ // elsewhere in Minecraft into this accelerator. So sadly, we must -+ // suffer the performance hit of this very expensive call. If there -+ // is consistency to what this call returns, we may be able to cache it. -+ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); -+ wire.setCanProvidePower(true); -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (k < 15) { -+ if (upd.neighbor_nodes == null) { -+ // If this node's neighbors are not known, expand the node -+ findNeighbors(worldIn, upd); -+ } -+ -+ // These remain constant, so pull them out of the loop. -+ // Regardless of which direction is forward, the UpdateNode for the -+ // position directly above the node being calculated is always -+ // at index 1. -+ UpdateNode center_up = upd.neighbor_nodes[1]; -+ boolean center_up_is_cube = center_up.currentState.isOccluding(worldIn, center_up.self); // TODO -+ -+ for (int m = 0; m < 4; m++) { -+ // Get the neighbor array index of each of the four cardinal -+ // neighbors. -+ int n = rs_neighbors[m]; -+ -+ // Get the max redstone power level of each of the cardinal -+ // neighbors -+ UpdateNode neighbor = upd.neighbor_nodes[n]; -+ l = getMaxCurrentStrength(neighbor, l); -+ -+ // Also check the positions above and below the cardinal -+ // neighbors -+ boolean neighbor_is_cube = neighbor.currentState.isOccluding(worldIn, neighbor.self); // TODO -+ if (!neighbor_is_cube) { -+ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; -+ l = getMaxCurrentStrength(neighbor_down, l); -+ } else -+ if (!center_up_is_cube) { -+ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; -+ l = getMaxCurrentStrength(neighbor_up, l); -+ } -+ } -+ } -+ -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ -+ // egg82's amendment -+ // Adding Bukkit's BlockRedstoneEvent - er.. event. -+ if (i != j) { -+ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); -+ worldIn.getServer().getPluginManager().callEvent(event); -+ j = event.getNewCurrent(); -+ } -+ -+ if (i != j) { -+ // If the power level has changed from its previous value, compute a new state -+ // and set it in the world. -+ // Possible optimization: Don't commit state changes to the world until they -+ // need to be known by some nearby non-redstone-wire block. -+ BlockPosition pos = new BlockPosition(upd.self.getX(), upd.self.getY(), upd.self.getZ()); -+ if (wire.canPlace(null, worldIn, pos)) { -+ state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(j)); -+ worldIn.setTypeAndData(upd.self, state, 2); -+ } -+ } -+ -+ return state; -+ } -+ -+ /* -+ * Optimized function to compute a redstone wire's power level based on cached -+ * state. -+ */ -+ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { -+ if (upd.type != UpdateNode.Type.REDSTONE) return strength; -+ final int i = upd.currentState.get(BlockRedstoneWire.POWER).intValue(); -+ return i > strength ? i : strength; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 9369a0c6c0ae2d8518ebfb17f2c93ead2647ab8d..307a89c431739ed15d8869faace7b08927626f60 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -659,6 +659,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - } - -+ public void neighborChanged(BlockPosition pos, Block blockIn, BlockPosition fromPos) { a(pos, blockIn, fromPos); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) { - if (!this.isClientSide) { - IBlockData iblockdata = this.getType(blockposition); -@@ -1287,6 +1288,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 ? true : (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 ? true : (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 ? true : (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 ? true : (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 ? true : this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0)))); - } - -+ public int isBlockIndirectlyGettingPowered(BlockPosition pos) { return this.s(pos); } // Paper - OBFHELPER - public int s(BlockPosition blockposition) { - int i = 0; - EnumDirection[] aenumdirection = World.a; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -index 60f0e582199472f9c5ef26e12ee1da0c3867254e..71ba55d36f5bc8a417930015c31553b30cf3e8dd 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.util.RedstoneWireTurbo; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -50,7 +52,7 @@ public class BlockRedstoneWire extends Block { - private final Map j = Maps.newHashMap(); - private static final Vector3fa[] k = new Vector3fa[16]; - private final IBlockData o; -- private boolean p = true; -+ private boolean p = true; public final boolean canProvidePower() { return this.p; } public final void setCanProvidePower(boolean value) { this.p = value; } // Paper - OBFHELPER - - public BlockRedstoneWire(BlockBase.Info blockbase_info) { - super(blockbase_info); -@@ -237,6 +239,121 @@ public class BlockRedstoneWire extends Block { - return iblockdata.d(iblockaccess, blockposition, EnumDirection.UP) || iblockdata.a(Blocks.HOPPER); - } - -+ // Paper start - Optimize redstone -+ // The bulk of the new functionality is found in RedstoneWireTurbo.java -+ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); -+ -+ /* -+ * Modified version of pre-existing updateSurroundingRedstone, which is called from -+ * this.neighborChanged and a few other methods in this class. -+ * Note: Added 'source' argument so as to help determine direction of information flow -+ */ -+ private void updateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, BlockPosition source) { -+ if (worldIn.paperConfig.useEigencraftRedstone) { -+ turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ return; -+ } -+ a(worldIn, pos, state); -+ } -+ -+ /* -+ * Slightly modified method to compute redstone wire power levels from neighboring blocks. -+ * Modifications cut the number of power level changes by about 45% from vanilla, and this -+ * optimization synergizes well with the breadth-first search implemented in -+ * RedstoneWireTurbo. -+ * Note: RedstoneWireTurbo contains a faster version of this code. -+ * Note: Made this public so that RedstoneWireTurbo can access it. -+ */ -+ public IBlockData calculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state) { -+ IBlockData iblockstate = state; -+ int i = state.get(POWER); -+ int j = 0; -+ j = this.getPower(j, worldIn.getType(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // This code is totally redundant to if statements just below the loop. -+ if (k > 0 && k > j - 1) { -+ j = k; -+ } -+ } -+ -+ int l = 0; -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { -+ for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { -+ BlockPosition blockpos = pos1.shift(enumfacing); -+ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); -+ -+ if (flag) { -+ l = this.getPower(l, worldIn.getType(blockpos)); -+ } -+ -+ if (worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && !worldIn.getType(pos1.up()).isOccluding(worldIn, pos1)) { -+ if (flag && pos1.getY() >= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.up())); -+ } -+ } else if (!worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.down())); -+ } -+ } -+ } -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // The old code would decrement the wire value only by 1 at a time. -+ if (l > j) { -+ j = l - 1; -+ } else if (j > 0) { -+ --j; -+ } else { -+ j = 0; -+ } -+ -+ if (k > j - 1) { -+ j = k; -+ } -+ } else { -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ } -+ -+ if (i != j) { -+ state = state.set(POWER, j); -+ -+ if (worldIn.getType(pos1) == iblockstate) { -+ worldIn.setTypeAndData(pos1, state, 2); -+ } -+ -+ // 1.16(.1?) dropped the need for blocks needing updates. -+ // Whether this is necessary after all is to be seen. -+// if (!worldIn.paperConfig.useEigencraftRedstone) { -+// // The new search algorithm keeps track of blocks needing updates in its own data structures, -+// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. -+// this.getBlocksNeedingUpdate().add(pos1); -+// -+// for (EnumDirection enumfacing1 : EnumDirection.values()) { -+// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); -+// } -+// } -+ } -+ -+ return state; -+ } -+ // Paper end -+ - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - int i = this.a(world, blockposition); - -@@ -306,6 +423,8 @@ public class BlockRedstoneWire extends Block { - return Math.max(i, j - 1); - } - -+ private int getPower(int min, IBlockData iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone -+ private int getPower(IBlockData iblockdata) { return this.o(iblockdata); } // Paper - OBFHELPER - private int o(IBlockData iblockdata) { - return iblockdata.a((Block) this) ? (Integer) iblockdata.get(BlockRedstoneWire.POWER) : 0; - } -@@ -328,7 +447,7 @@ public class BlockRedstoneWire extends Block { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock()) && !world.isClientSide) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - Iterator iterator = EnumDirection.EnumDirectionLimit.VERTICAL.iterator(); - - while (iterator.hasNext()) { -@@ -355,7 +474,7 @@ public class BlockRedstoneWire extends Block { - world.applyPhysics(blockposition.shift(enumdirection), this); - } - -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - this.d(world, blockposition); - } - } -@@ -390,7 +509,7 @@ public class BlockRedstoneWire extends Block { - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (!world.isClientSide) { - if (iblockdata.canPlace(world, blockposition)) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, blockposition1); // Paper - Optimize redstone - } else { - c(iblockdata, world, blockposition); - world.a(blockposition, false); diff --git a/Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch b/Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch deleted file mode 100644 index e159b43cdc15..000000000000 --- a/Spigot-Server-Patches/0559-Fix-hex-colors-not-working-in-some-kick-messages.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 16:57:25 -0400 -Subject: [PATCH] Fix hex colors not working in some kick messages - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 3d5381a6737876d3d7de40cacef900ab7ad27e27..97c7914e9826defc3e7167879e387fe697c10f3e 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -50,7 +50,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; -@@ -76,12 +76,12 @@ public class HandshakeListener implements PacketHandshakingInListener { - } - // CraftBukkit end - if (packethandshakinginsetprotocol.c() != SharedConstants.getGameVersion().getProtocolVersion()) { -- ChatMessage chatmessage; -+ IChatBaseComponent chatmessage; // Paper - Fix hex colors not working in some kick messages - - if (packethandshakinginsetprotocol.c() < 754) { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } else { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } - - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -@@ -98,7 +98,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - if (event.callEvent()) { - // If we've failed somehow, let the client know so and go no further. - if (event.isFailed()) { -- chatmessage = new ChatMessage(event.getFailMessage()); -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages - this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.getNetworkManager().close(chatmessage); - return; -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index e9fc38f69af815f021a08a94dd41b91171dbf2d6..c67b94840e4c967baebf6eb351df15f0e4ead4be 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -106,14 +106,7 @@ public class LoginListener implements PacketLoginInListener { - // CraftBukkit start - @Deprecated - public void disconnect(String s) { -- try { -- IChatBaseComponent ichatbasecomponent = new ChatComponentText(s); -- LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), s); -- this.networkManager.sendPacket(new PacketLoginOutDisconnect(ichatbasecomponent)); -- this.networkManager.close(ichatbasecomponent); -- } catch (Exception exception) { -- LoginListener.LOGGER.error("Error whilst disconnecting player", exception); -- } -+ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch b/Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch deleted file mode 100644 index 66018f4db8d6..000000000000 --- a/Spigot-Server-Patches/0560-PortalCreateEvent-needs-to-know-its-entity.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 21 Aug 2020 20:57:54 +0200 -Subject: [PATCH] PortalCreateEvent needs to know its entity - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 800d10db92a956d3ca8a3d569d12862f36044ee9..366ceb65d40c685117d1c79a933864ab91d8aa11 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -368,7 +368,7 @@ public final class ItemStack { - IBlockData block = world.getType(newblockposition); - - if (!(block.getBlock() instanceof BlockTileEntity)) { // Containers get placed automatically -- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); -+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext - } - - world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getType(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index e6ea1d29c7f3f4cb6039df0e35c8db94b6f38c3e..70c32b7a53a1107cced3491ebac19b0eaf4fec2e 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -15,6 +15,7 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -364,8 +365,10 @@ public class BlockFire extends BlockFireAbstract { - } - - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -- super.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ // Paper start - ItemActionContext param -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); -+ // Paper end - world.getBlockTickList().a(blockposition, this, a(world.random)); - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -index b86513497b7ca8bde84176f5228ef9c479a73abb..02047bf07c2008c7de8daf3d76b660e25b77bce8 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -@@ -7,6 +7,7 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.World; -@@ -66,14 +67,17 @@ public abstract class BlockFireAbstract extends Block { - super.a(iblockdata, world, blockposition, entity); - } - -+ // Paper start - ItemActionContext param -+ @Override public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { this.onPlace(iblockdata, world, blockposition, iblockdata1, flag, null); } - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ // Paper end - if (!iblockdata1.a(iblockdata.getBlock())) { - if (a(world)) { - Optional optional = BlockPortalShape.a((GeneratorAccess) world, blockposition, EnumDirection.EnumAxis.X); - - if (optional.isPresent()) { -- ((BlockPortalShape) optional.get()).createPortal(); -+ ((BlockPortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param - return; - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 2a785ea58a7bdc80c703a60bc6ed602dc8040aa0..9af91784544dbb0555824a91088257659bdf2c3d 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -32,6 +32,7 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.BlockAccessAir; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -120,6 +121,12 @@ public abstract class BlockBase { - PacketDebug.a(world, blockposition); - } - -+ // Paper start - add ItemActionContext param -+ @Deprecated -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ } -+ // Paper end - @Deprecated - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot -diff --git a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -index 9f7ff56e43a3dc0cc57ed3a2c6dbc729afafa1f8..3f8a674345bcad8289a48d2daa5e2a283528e952 100644 ---- a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -+++ b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -@@ -11,6 +11,7 @@ import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntitySize; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.block.BlockPortal; - import net.minecraft.world.level.block.Blocks; -@@ -177,7 +178,10 @@ public class BlockPortalShape { - } - - // CraftBukkit start - return boolean -- public boolean createPortal() { -+ // Paper start - ItemActionContext param -+ @Deprecated public boolean createPortal() { return this.createPortal(null); } -+ public boolean createPortal(ItemActionContext itemActionContext) { -+ // Paper end - org.bukkit.World bworld = this.b.getMinecraftWorld().getWorld(); - - // Copy below for loop -@@ -189,7 +193,7 @@ public class BlockPortalShape { - blocks.add(state); - }); - -- PortalCreateEvent event = new PortalCreateEvent(blocks, bworld, null, PortalCreateEvent.CreateReason.FIRE); -+ PortalCreateEvent event = new PortalCreateEvent(blocks, bworld, itemActionContext == null || itemActionContext.getEntity() == null ? null : itemActionContext.getEntity().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param - this.b.getMinecraftWorld().getMinecraftServer().server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch b/Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch deleted file mode 100644 index 52281e313544..000000000000 --- a/Spigot-Server-Patches/0561-Fix-CraftTeam-null-check.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: foss-mc <69294560+foss-mc@users.noreply.github.com> -Date: Sun, 30 Aug 2020 15:30:29 +0800 -Subject: [PATCH] Fix CraftTeam null check - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index c631934fe9d205a06956c900d5b58a1d8a781c19..d637c2941ad0680299378b58ba0db7f7a6be07dc 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -254,7 +254,7 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - @Override - public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { -- Validate.notNull("Entry cannot be null"); -+ Validate.notNull(entry, "Entry cannot be null"); // Paper - - CraftScoreboard scoreboard = checkState(); - diff --git a/Spigot-Server-Patches/0562-Add-more-Evoker-API.patch b/Spigot-Server-Patches/0562-Add-more-Evoker-API.patch deleted file mode 100644 index ccde2ad0c91b..000000000000 --- a/Spigot-Server-Patches/0562-Add-more-Evoker-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:28:35 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -index 64bfd84e8a5a0c2b1fec7044b688c7cc1083f18a..2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -@@ -40,7 +40,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class EntityEvoker extends EntityIllagerWizard { - -- private EntitySheep bo; -+ private EntitySheep bo; public final EntitySheep getWololoTarget() { return this.bo; } public final void setWololoTarget(EntitySheep sheep) { this.bo = sheep; } // Paper - OBFHELPER - - public EntityEvoker(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -59,7 +59,7 @@ public class EntityEvoker extends EntityIllagerWizard { - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); - this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 5e8e9d95068342661a962aae9878a7eafaa06207..75a7832e9841921497a9a2d1cfd1b05807fe6ede 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.animal.EntitySheep; - import net.minecraft.world.entity.monster.EntityEvoker; - import net.minecraft.world.entity.monster.EntityIllagerWizard; - import org.bukkit.craftbukkit.CraftServer; -@@ -36,4 +37,17 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { - public void setCurrentSpell(Evoker.Spell spell) { - getHandle().setSpell(spell == null ? EntityIllagerWizard.Spell.NONE : EntityIllagerWizard.Spell.a(spell.ordinal())); - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.entity.Sheep getWololoTarget() { -+ EntitySheep sheep = getHandle().getWololoTarget(); -+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); -+ } -+ -+ @Override -+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { -+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index c34765c878ce..000000000000 --- a/Spigot-Server-Patches/0563-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:16:09 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 9d2955f05aadd4bbc6dcfec068a55d7fe6950ba0..f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -278,6 +278,7 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getKey(entitytypes); - } - -+ public static Optional> getByName(String name) { return a(name); } // Paper - OBFHELPER - public static Optional> a(String s) { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } -@@ -431,6 +432,7 @@ public class EntityTypes { - return this.bg; - } - -+ public String getDescriptionId() { return f(); } // Paper - OBFHELPER - public String f() { - if (this.bo == null) { - this.bo = SystemUtils.a("entity", IRegistry.ENTITY_TYPE.getKey(this)); -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index ca513e7b0a416860aba89e41de6a7c5ff42baa69..467121839b94e09f59c64300de9f26d3c6caf1e5 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -56,7 +56,7 @@ public class Item implements IMaterial { - private final FoodInfo foodInfo; - - public static int getId(Item item) { -- return item == null ? 0 : IRegistry.ITEM.a((Object) item); -+ return item == null ? 0 : IRegistry.ITEM.a(item); // Paper - Fix Decompiler Issue - } - - public static Item getById(int i) { -@@ -152,6 +152,7 @@ public class Item implements IMaterial { - return IRegistry.ITEM.getKey(this).getKey(); - } - -+ public String getOrCreateDescriptionId() { return m(); } // Paper - OBFHELPER - protected String m() { - if (this.name == null) { - this.name = SystemUtils.a("item", IRegistry.ITEM.getKey(this)); -@@ -164,6 +165,7 @@ public class Item implements IMaterial { - return this.m(); - } - -+ public String getDescriptionId(ItemStack itemStack) { return f(itemStack); } // Paper - OBFHELPER - public String f(ItemStack itemstack) { - return this.getName(); - } -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index cc512bd2e89382e7fdbc59b41640e95ccafbbfe9..d4903842aebeff3e32dbf7d3f4b670af4ebad174 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -318,6 +318,7 @@ public class Block extends BlockBase implements IMaterial { - return !this.material.isBuildable() && !this.material.isLiquid(); - } - -+ public String getOrCreateDescriptionId() { return i(); } // Paper - OBFHELPER - public String i() { - if (this.name == null) { - this.name = SystemUtils.a("block", IRegistry.BLOCK.getKey(this)); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index e3ab0b76e5003553b29215a43bc5a762f2663648..ee8977a1e4a83598ba7873c4c482fea828c6b26c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -764,5 +764,10 @@ public class CraftBlock implements Block { - public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { - return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); - } -+ -+ @Override -+ public String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 2519dbce9717ff647d50c31aed6aca68b9f4e3af..8049063ea37f3e0eac3f3a26703adc80fc99341a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -45,6 +45,7 @@ import org.bukkit.Registry; - import org.bukkit.UnsafeValues; - import org.bukkit.advancement.Advancement; - import org.bukkit.block.data.BlockData; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.legacy.CraftLegacy; -@@ -420,6 +421,30 @@ public final class CraftMagicNumbers implements UnsafeValues { - throw new RuntimeException(); - } - } -+ -+ @Override -+ public String getTranslationKey(Material mat) { -+ if (mat.isBlock()) { -+ return getBlock(mat).getOrCreateDescriptionId(); -+ } -+ return getItem(mat).getName(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.block.Block block) { -+ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.entity.EntityType type) { -+ return net.minecraft.world.entity.EntityTypes.getByName(type.getName()).map(net.minecraft.world.entity.EntityTypes::getDescriptionId).orElse(null); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { -+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch b/Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index 1e4c77c2c5a2..000000000000 --- a/Spigot-Server-Patches/0564-Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:18:04 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 910c6109783dfef86e127a0a5b7d7d3865150d89..347c23d4b7d47198f214c3f95354e8abb660b191 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -365,5 +365,40 @@ public final class CraftItemFactory implements ItemFactory { - - return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; - } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { -+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); -+ return new net.md_5.bungee.api.chat.hover.content.Item( -+ itemStack.getType().getKey().toString(), -+ itemStack.getAmount(), -+ itemTag); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ customName); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0565-Cache-block-data-strings.patch b/Spigot-Server-Patches/0565-Cache-block-data-strings.patch deleted file mode 100644 index f09196d5d68b..000000000000 --- a/Spigot-Server-Patches/0565-Cache-block-data-strings.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 6 Dec 2018 19:52:50 -0500 -Subject: [PATCH] Cache block data strings - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index bd6b9c7be8951393e7ba731f4d6a9486f0743be7..040933a25f1fa88e86b19ea20f519488af6a2740 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1954,6 +1954,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant%s", nms, bukkit); - } - -+ // Paper start - cache block data strings -+ private static Map stringDataCache = new HashMap<>(); -+ -+ static { -+ // cache all of the default states at startup, will not cache ones with the custom states inside of the -+ // brackets in a different order, though -+ reloadCache(); -+ } -+ -+ public static void reloadCache() { -+ stringDataCache.clear(); -+ Block.REGISTRY_ID.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); -+ } -+ // Paper end -+ - public static CraftBlockData newData(Material material, String data) { - Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); - -+ // Paper start - cache block data strings -+ if (material != null) { -+ Block block = CraftMagicNumbers.getBlock(material); -+ if (block != null) { -+ MinecraftKey key = IRegistry.BLOCK.getKey(block); -+ data = data == null ? key.toString() : key + data; -+ } -+ } -+ -+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); -+ return (CraftBlockData) cached.clone(); -+ } -+ -+ private static CraftBlockData createNewData(Material material, String data) { -+ // Paper end - cache block data strings - IBlockData blockData; - Block block = CraftMagicNumbers.getBlock(material); - Map, Comparable> parsed = null; diff --git a/Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch deleted file mode 100644 index b9cb472b5af1..000000000000 --- a/Spigot-Server-Patches/0566-Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 25 Aug 2020 20:45:36 -0400 -Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported - -Uses correct setPositionRotation for Entity teleporting instead of setLocation -as this is how Vanilla teleports entities. - -Cancel any pending motion when teleported. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 1d154ef60fd979340cf925748251669e860d4094..68f8a7f227c4d683d4c13d634ccfbabe759e82b3 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -693,7 +693,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) { - PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer()); - if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit -- this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); -+ this.player.setPositionRotation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); // Paper - use proper setPositionRotation for teleportation - this.o = this.teleportPos.x; - this.p = this.teleportPos.y; - this.q = this.teleportPos.z; -@@ -1537,7 +1537,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - this.A = this.e; -- this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.setPositionRotation(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation - this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 743d4725c0a26a8abd0a98eed2ec45ffba6211ad..344862c3f479ae7b6d4f929c9ef7882aba983ffb 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -145,6 +145,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -+ boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation - static boolean isLevelAtLeast(NBTTagCompound tag, int level) { - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } -@@ -1408,6 +1409,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRotation(double d0, double d1, double d2, float f, float f1) { -+ // Paper - cancel entity velocity if teleported -+ if (!preserveMotion) { -+ this.mot = Vec3D.ORIGIN; -+ } else { -+ this.preserveMotion = false; -+ } -+ // Paper end - this.g(d0, d1, d2); - this.yaw = f; - this.pitch = f1; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 387f6f6fa9bbb1cce544cfb907f68c7993752dd7..fb52a60437d48282f3e99e7eccb0e76b446155f9 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -558,7 +558,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - } - - // entity.setLocation() throws no event, and so cannot be cancelled -- entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); -+ entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting - // SPIGOT-619: Force sync head rotation also - entity.setHeadRotation(location.getYaw()); - ((net.minecraft.server.level.WorldServer) entity.world).chunkCheck(entity); // Spigot - register to new chunk diff --git a/Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch b/Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index 775318f266fa..000000000000 --- a/Spigot-Server-Patches/0567-Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 26 Aug 2020 02:12:31 -0400 -Subject: [PATCH] Add additional open container api to HumanEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 92501a415813b3b0f2be492a4711962320264a76..b99423b3b413fc6364c6530a99e3c74dd406e1b4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -458,6 +458,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return this.getHandle().activeContainer.getBukkitView(); - } - -+ // Paper start - Add additional containers -+ @Override -+ public InventoryView openAnvil(Location location, boolean force) { -+ return openInventory(location, force, Material.ANVIL); -+ } -+ -+ @Override -+ public InventoryView openCartographyTable(Location location, boolean force) { -+ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); -+ } -+ -+ @Override -+ public InventoryView openGrindstone(Location location, boolean force) { -+ return openInventory(location, force, Material.GRINDSTONE); -+ } -+ -+ @Override -+ public InventoryView openLoom(Location location, boolean force) { -+ return openInventory(location, force, Material.LOOM); -+ } -+ -+ @Override -+ public InventoryView openSmithingTable(Location location, boolean force) { -+ return openInventory(location, force, Material.SMITHING_TABLE); -+ } -+ -+ @Override -+ public InventoryView openStonecutter(Location location, boolean force) { -+ return openInventory(location, force, Material.STONECUTTER); -+ } -+ -+ private InventoryView openInventory(Location location, boolean force, Material material) { -+ org.spigotmc.AsyncCatcher.catchOp("open" + material); -+ if (location == null) { -+ location = getLocation(); -+ } -+ if (!force) { -+ Block block = location.getBlock(); -+ if (block.getType() != material) { -+ return null; -+ } -+ } -+ net.minecraft.world.level.block.Block block; -+ if (material == Material.ANVIL) { -+ block = Blocks.ANVIL; -+ } else if (material == Material.CARTOGRAPHY_TABLE) { -+ block = Blocks.CARTOGRAPHY_TABLE; -+ } else if (material == Material.GRINDSTONE) { -+ block = Blocks.GRINDSTONE; -+ } else if (material == Material.LOOM) { -+ block = Blocks.LOOM; -+ } else if (material == Material.SMITHING_TABLE) { -+ block = Blocks.SMITHING_TABLE; -+ } else if (material == Material.STONECUTTER) { -+ block = Blocks.STONECUTTER; -+ } else { -+ throw new IllegalArgumentException("Unsupported inventory type: " + material); -+ } -+ getHandle().openContainer(block.getInventory(null, getHandle().world, new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); -+ getHandle().activeContainer.checkReachable = !force; -+ return getHandle().activeContainer.getBukkitView(); -+ } -+ // Paper end -+ - @Override - public void closeInventory() { - // Paper start diff --git a/Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch deleted file mode 100644 index a02addc375bf..000000000000 --- a/Spigot-Server-Patches/0568-Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 12 Sep 2020 17:21:38 -0400 -Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand - -Mojang precaches every single potential rewrite rule that could ever -exist on server startup. This includes rules from all the way back to versions from 6+ years ago. - -This is the source of why the server hogs every CPU core at 100% every start. - -For anyone who hard resets for updates or has force upgraded their entire world, this -results in completely wasted cpu cycles. - -This massive CPU usage also delays server startup time. - -We improve this by making "min version to precache" that defaults to a future version -so that no rewrite rules are precached. - -someone who expects to be converting a lot chunks could theoretically set --DPaper.minPrecachedDatafixVersion= as a startup -parameter and only build from that point on. - -However this will likely never be needed as the server will still run -the same cache logic on demand when it's actually needed. The only -cost would be some delay on the FIRST chunk conversion, but paper already -runs chunk conversions on another thread so this will likely never be -a concern for TPS. - -This patch will significantly reduce CPU use on startup, reduce memory usage, -and improve server startup time. - -diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -index edb77982d273e9492ab1a669ca1ad89da2ec3c3e..abc265b00044b14abb55c2628d454ee01fef467b 100644 ---- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -+++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -@@ -26,8 +26,10 @@ public class DataFixerBuilder { - private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); - private final List globalList = Lists.newArrayList(); - private final IntSortedSet fixerVersions = new IntAVLTreeSet(); -+ private final int minDataFixPrecacheVersion; // Paper - - public DataFixerBuilder(final int dataVersion) { -+ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' - this.dataVersion = dataVersion; - } - -@@ -65,6 +67,7 @@ public class DataFixerBuilder { - final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); - while (iterator.hasNext()) { - final int versionKey = iterator.nextInt(); -+ if (versionKey < minDataFixPrecacheVersion) continue; // Paper - final Schema schema = schemas.get(versionKey); - for (final String typeName : schema.types()) { - CompletableFuture.runAsync(() -> { diff --git a/Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch b/Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch deleted file mode 100644 index 8353773dbd8f..000000000000 --- a/Spigot-Server-Patches/0569-Extend-block-drop-capture-to-capture-all-items-added.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 17 Sep 2020 00:36:05 +0100 -Subject: [PATCH] Extend block drop capture to capture all items added to the - world - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 984209e4f66ad23d85d2c5d02318caab1aff7324..31012963815a5c7355753b8cd2749976282ef0d2 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -12,6 +12,7 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.ItemActionContext; -@@ -419,10 +420,12 @@ public class PlayerInteractManager { - // return true; // CraftBukkit - } - // CraftBukkit start -+ java.util.List itemsToDrop = world.captureDrops; // Paper - store current list -+ world.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff - if (event.isDropItems()) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, world.captureDrops); -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref - } -- world.captureDrops = null; -+ //world.captureDrops = null; // Paper - move up - - // Drop event experience - if (flag && event != null) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 68a2fef79eae006ea7a8de1fc903e7000b6aab85..7942f492f7688fab52acbefbe5703221b0435752 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -99,6 +99,7 @@ import net.minecraft.world.entity.animal.EntityWaterAnimal; - import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.npc.NPC; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.raid.PersistentRaid; -@@ -1290,6 +1291,13 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } else if (this.isUUIDTaken(entity)) { - return false; - } else { -+ // Paper start - capture all item additions to the world -+ if (captureDrops != null && entity instanceof EntityItem) { -+ captureDrops.add((EntityItem) entity); -+ return true; -+ } -+ // Paper end -+ - if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { - return false; - } diff --git a/Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch deleted file mode 100644 index 974a34ff2f13..000000000000 --- a/Spigot-Server-Patches/0570-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 27 Sep 2020 16:25:24 +0200 -Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 00cebd33101916f29bbc192d531ac0fba31e037b..a323b76f68c273a73cb3f20167a668b2100f4944 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -389,6 +389,7 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -+ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks - Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { diff --git a/Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index 6c4cca6613bf..000000000000 --- a/Spigot-Server-Patches/0571-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:26 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 344862c3f479ae7b6d4f929c9ef7882aba983ffb..e2301dbeb3d76684b2a0ab4262bb76cab3557789 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3473,4 +3473,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - void accept(Entity entity, double d0, double d1, double d2); - } -+ -+ // Paper start -+ public static int nextEntityId() { -+ return entityCount.incrementAndGet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8049063ea37f3e0eac3f3a26703adc80fc99341a..5b03187f4d76e3052ee9abe0ee2774218d41b864 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -445,6 +445,10 @@ public final class CraftMagicNumbers implements UnsafeValues { - net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); - return nmsItemStack.getItem().getDescriptionId(nmsItemStack); - } -+ -+ public int nextEntityId() { -+ return net.minecraft.world.entity.Entity.nextEntityId(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch b/Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch deleted file mode 100644 index 974e02ca682e..000000000000 --- a/Spigot-Server-Patches/0572-Lazily-track-plugin-scoreboards-by-default.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sat, 3 Oct 2020 04:15:09 -0400 -Subject: [PATCH] Lazily track plugin scoreboards by default - -On servers with plugins that constantly churn through scoreboards, there is a risk of -degraded GC performance due to the number of scoreboards held on by weak references. -Most plugins don't even need the (vanilla) functionality that requires all plugin -scoreboards to be tracked by the server. Instead, only track scoreboards when an -objective is added with a non-dummy criteria. - -This is a breaking change, however the change is a much more sensible default. In case -this breaks your workflow you can always force all scoreboards to be tracked with -settings.track-plugin-scoreboards in paper.yml. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 545948f20efd6c8dd42140b565af94cd6b52b661..7d50aded88f5b7dfebaea1aebc86231f7b5c4e25 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -462,4 +462,9 @@ public class PaperConfig { - private static void maxJoinsPerTick() { - maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); - } -+ -+ public static boolean trackPluginScoreboards; -+ private static void trackPluginScoreboards() { -+ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 6ea491f6308317059c4bc6735abbdce370df0f34..3dfb6ad1ed5fae773b88cbe9ad540fd2520b8b50 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -19,6 +19,7 @@ import org.bukkit.scoreboard.Team; - - public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - final Scoreboard board; -+ boolean registeredGlobally = false; // Paper - - CraftScoreboard(Scoreboard board) { - this.board = board; -@@ -45,6 +46,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective -+ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); - } -@@ -66,6 +73,12 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start -+ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective);*/ // Paper - return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 73663bcea163cda26f531902141a9ad3ad7eba57..9c30a79cc55c6455aa18e3798728deaacc3434ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -30,6 +30,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { - - public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); -+ mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); - } -@@ -43,10 +44,22 @@ public final class CraftScoreboardManager implements ScoreboardManager { - public CraftScoreboard getNewScoreboard() { - org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot - CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server)); -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { -+ scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); -+ } -+ // Paper end - return scoreboard; - } - -+ // Paper start -+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { -+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); -+ scoreboards.add(scoreboard); -+ } -+ // Paper end -+ - // CraftBukkit method - public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); diff --git a/Spigot-Server-Patches/0573-Entity-isTicking.patch b/Spigot-Server-Patches/0573-Entity-isTicking.patch deleted file mode 100644 index 2842cb3c9f02..000000000000 --- a/Spigot-Server-Patches/0573-Entity-isTicking.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:16 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index e2301dbeb3d76684b2a0ab4262bb76cab3557789..f1fa11217ab09133f4f19f5c73dfdab2f2b434e2 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -48,6 +48,7 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; -@@ -3478,5 +3479,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public static int nextEntityId() { - return entityCount.incrementAndGet(); - } -+ -+ public boolean isTicking() { -+ return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index fb52a60437d48282f3e99e7eccb0e76b446155f9..295ffab08672d77d88aca368cb5b56f80bc4f1b5 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1161,5 +1161,9 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean isInLava() { - return getHandle().isInLava(); - } -+ -+ public boolean isTicking() { -+ return getHandle().isTicking(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch deleted file mode 100644 index c87a1962f6e4..000000000000 --- a/Spigot-Server-Patches/0574-Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 22:00:27 -0500 -Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is - not enabled - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 040933a25f1fa88e86b19ea20f519488af6a2740..2834af3e0ff2ae8466fde191a64bf719242f67f3 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2019,6 +2019,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = Lists.newArrayList(playerlist.getPlayers()); - Iterator iterator = list.iterator(); - diff --git a/Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch b/Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch deleted file mode 100644 index 26697d6feba2..000000000000 --- a/Spigot-Server-Patches/0575-Fix-Not-a-string-Map-Conversion-spam.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Oct 2020 00:00:25 -0400 -Subject: [PATCH] Fix "Not a string" Map Conversion spam - -The maps did convert successfully, but had noisy logs due to Spigot -implementing this logic incorrectly. - -This stops the spam by converting the old format to new before -requesting the world. - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index d470af1814af332595c1c0beb1cdc552e186a6bb..1f9b710f2af3c5067b3c2b73bebb11f8e22c403e 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -11,8 +11,10 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTNumber; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutMap; -@@ -94,7 +96,26 @@ public class WorldMap extends PersistentBase { - - @Override - public void a(NBTTagCompound nbttagcompound) { -- DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("dimension"))); // CraftBukkit - decompile error -+ // Paper start - fix "Not a string" spam -+ NBTBase dimension = nbttagcompound.get("dimension"); -+ if (dimension instanceof NBTNumber && ((NBTNumber) dimension).asInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { -+ long least = nbttagcompound.getLong("UUIDLeast"); -+ long most = nbttagcompound.getLong("UUIDMost"); -+ -+ if (least != 0L && most != 0L) { -+ this.uniqueId = new UUID(most, least); -+ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); -+ if (world != null) { -+ dimension = NBTTagString.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } -+ DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, dimension)); // CraftBukkit - decompile error -+ // Paper end - fix "Not a string" spam - Logger logger = WorldMap.LOGGER; - - logger.getClass(); diff --git a/Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch deleted file mode 100644 index 48e233764b2c..000000000000 --- a/Spigot-Server-Patches/0576-Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sun, 4 Oct 2020 19:55:25 -0700 -Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f1fa11217ab09133f4f19f5c73dfdab2f2b434e2..2a3025793db52a18e58f832c9da78c6c3b39d33c 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3177,7 +3177,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public Stream recursiveStream() { -- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::recursiveStream)); -+ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::recursiveStream)); // Paper - } - - public boolean hasSinglePlayerPassenger() { diff --git a/Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch deleted file mode 100644 index 42d7399da75e..000000000000 --- a/Spigot-Server-Patches/0577-MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Wed, 18 Mar 2020 00:07:46 -0500 -Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe - - -diff --git a/src/main/java/net/minecraft/recipebook/AutoRecipe.java b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -index 897f7270bae601b39d74d6a56a60f0ac7f1f6090..3bcd2c5a5352b8fb92d09b0a6914a1013569c8d6 100644 ---- a/src/main/java/net/minecraft/recipebook/AutoRecipe.java -+++ b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -@@ -71,7 +71,12 @@ public class AutoRecipe implements AutoRecipeAbstract -Date: Wed, 1 Jun 2016 23:29:17 -0400 -Subject: [PATCH] Reset Ender Crystals on Dragon Spawn - -Crystals can end up in a bad state in certain conditions which causes -an exception on the expected number of crystals going negative. - -This ensures the crystals/pillars are in expected state when the dragon spawns. - -See #3522 - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0869af4670f040344f5b6c2c10bff5e5226f707c..c6283489dcb6e13f0d618971614aeadaee2e3007 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -445,6 +445,7 @@ public class EnderDragonBattle { - entityenderdragon.setPositionRotation(0.0D, 128.0D, 0.0D, this.world.random.nextFloat() * 360.0F, 0.0F); - this.world.addEntity(entityenderdragon); - this.dragonUUID = entityenderdragon.getUniqueID(); -+ this.resetCrystals(); // Paper - return entityenderdragon; - } - diff --git a/Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch b/Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch deleted file mode 100644 index 03994e2ff1a7..000000000000 --- a/Spigot-Server-Patches/0579-Fix-for-large-move-vectors-crashing-server.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 17 May 2020 23:47:33 -0700 -Subject: [PATCH] Fix for large move vectors crashing server - -Check movement distance also based on current position. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 68f8a7f227c4d683d4c13d634ccfbabe759e82b3..8ffc98faecca616005fc56031718a7a10de40102 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -518,19 +518,24 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (entity != this.player && entity.getRidingPassenger() == this.player && entity == this.r) { - WorldServer worldserver = this.player.getWorldServer(); -- double d0 = entity.locX(); -- double d1 = entity.locY(); -- double d2 = entity.locZ(); -- double d3 = packetplayinvehiclemove.getX(); -- double d4 = packetplayinvehiclemove.getY(); -- double d5 = packetplayinvehiclemove.getZ(); -+ double d0 = entity.locX();double fromX = d0; // Paper - OBFHELPER -+ double d1 = entity.locY();double fromY = d1; // Paper - OBFHELPER -+ double d2 = entity.locZ();double fromZ = d2; // Paper - OBFHELPER -+ double d3 = packetplayinvehiclemove.getX();double toX = d3; // Paper - OBFHELPER -+ double d4 = packetplayinvehiclemove.getY();double toY = d4; // Paper - OBFHELPER -+ double d5 = packetplayinvehiclemove.getZ();double toZ = d5; // Paper - OBFHELPER - float f = packetplayinvehiclemove.getYaw(); - float f1 = packetplayinvehiclemove.getPitch(); - double d6 = d3 - this.s; - double d7 = d4 - this.t; - double d8 = d5 - this.u; - double d9 = entity.getMot().g(); -- double d10 = d6 * d6 + d7 * d7 + d8 * d8; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - fromX; -+ double currDeltaY = toY - fromY; -+ double currDeltaZ = toZ - fromZ; -+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - - // CraftBukkit start - handle custom speeds and skipped ticks -@@ -1232,7 +1237,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d2 = this.player.locZ(); - double d3 = this.player.locY(); - double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER -- double d5 = packetplayinflying.b(this.player.locY()); -+ double d5 = packetplayinflying.b(this.player.locY());double toY = d5; // Paper - OBFHELPER - double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); -@@ -1240,7 +1245,12 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d8 = d5 - this.m; - double d9 = d6 - this.n; - double d10 = this.player.getMot().g(); -- double d11 = d7 * d7 + d8 * d8 + d9 * d9; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - prevX; -+ double currDeltaY = toY - prevY; -+ double currDeltaZ = toZ - prevZ; -+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - if (this.player.isSleeping()) { - if (d11 > 1.0D) { diff --git a/Spigot-Server-Patches/0580-Optimise-getType-calls.patch b/Spigot-Server-Patches/0580-Optimise-getType-calls.patch deleted file mode 100644 index 16993ab18dd1..000000000000 --- a/Spigot-Server-Patches/0580-Optimise-getType-calls.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 3 Jun 2020 11:37:13 -0700 -Subject: [PATCH] Optimise getType calls - -Remove the map lookup for converting from Block->Bukkit Material - -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -index 9e1ebfd7befe9e2fc3396b4dcd5e8fc7c23ee305..ed28710fefee4fad96290b2d166ac9dfe3d1fa6e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -@@ -11,6 +11,19 @@ public class IBlockData extends BlockBase.BlockData { - - public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); - -+ -+ // Paper start - optimise getType calls -+ org.bukkit.Material cachedMaterial; -+ -+ public final org.bukkit.Material getBukkitMaterial() { -+ if (this.cachedMaterial == null) { -+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); -+ } -+ -+ return this.cachedMaterial; -+ } -+ // Paper end - optimise getType calls -+ - public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(block, immutablemap, mapcodec); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -index aa20cecc93ac53ce7f1b956ea5065ae80b55cff5..fc65c138bab242d5b533381ea496a2a48fcd91ea 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -@@ -79,7 +79,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot { - public Material getBlockType(int x, int y, int z) { - CraftChunk.validateChunkCoordinates(x, y, z); - -- return CraftMagicNumbers.getMaterial(blockids[y >> 4].a(x, y & 0xF, z).getBlock()); -+ return blockids[y >> 4].a(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ee8977a1e4a83598ba7873c4c482fea828c6b26c..f1f03bd0162a158761f300cbd96aa32101542abb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -214,7 +214,7 @@ public class CraftBlock implements Block { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); -+ return world.getType(position).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index b7ce677572f1f5ed01f3a8caf9368222e03bb69c..1960f01b5e4d7bff96d466e9a48f1d5300f261d1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -135,7 +135,7 @@ public class CraftBlockState implements BlockState { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls - } - - public void setFlag(int flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 58f892478de74b853cd35ef2fec8c462e3a9ecee..1fe9b32c2a3717652be70786090a61c5fa7430cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -45,7 +45,7 @@ public class CraftBlockData implements BlockData { - - @Override - public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls - } - - public IBlockData getState() { -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index d02281f954aac8d8b65f5d36ec70f0352e4c7cdd..2194232200e90fa894b45eb265b5ed08ce1e35a3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -73,7 +73,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - - @Override - public Material getType(int x, int y, int z) { -- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); -+ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override diff --git a/Spigot-Server-Patches/0581-Villager-resetOffers.patch b/Spigot-Server-Patches/0581-Villager-resetOffers.patch deleted file mode 100644 index 5c18995906b6..000000000000 --- a/Spigot-Server-Patches/0581-Villager-resetOffers.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 7 Oct 2019 00:15:37 -0500 -Subject: [PATCH] Villager#resetOffers - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 3dd80fcf9237f15bb3bf38d1529340e178f09388..a614f5d5817bf999aca0f0b50f343031c8168392 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -113,6 +113,13 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.tradingPlayer != null; - } - -+ // Paper start -+ public void resetOffers() { -+ this.trades = new MerchantRecipeList(); -+ this.updateTrades(); -+ } -+ // Paper end -+ - @Override - public MerchantRecipeList getOffers() { - if (this.trades == null) { -@@ -235,6 +242,7 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.world; - } - -+ protected final void updateTrades() { eW(); } // Paper - OBFHELPER - protected abstract void eW(); - - protected void a(MerchantRecipeList merchantrecipelist, VillagerTrades.IMerchantRecipeOption[] avillagertrades_imerchantrecipeoption, int i) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 01285d555ed084fa2e818e1f02955f8aa28002b3..ee751ed4f9f386bf9926347fe2f0958015aecffa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -@@ -71,4 +71,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla - public HumanEntity getTrader() { - return getMerchant().getTrader(); - } -+ -+ // Paper start -+ @Override -+ public void resetOffers() { -+ getHandle().resetOffers(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch deleted file mode 100644 index 124a856cdf9f..000000000000 --- a/Spigot-Server-Patches/0582-Improve-inlinig-for-some-hot-IBlockData-methods.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Jul 2020 20:46:50 -0700 -Subject: [PATCH] Improve inlinig for some hot IBlockData methods - - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 9af91784544dbb0555824a91088257659bdf2c3d..3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -391,7 +391,14 @@ public abstract class BlockBase { - } - // Paper end - -+ // Paper start -+ protected boolean isTicking; -+ protected Fluid fluid; -+ // Paper end -+ - public void a() { -+ this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() -+ this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() - if (!this.getBlock().o()) { - this.a = new BlockBase.BlockData.Cache(this.p()); - } -@@ -430,19 +437,19 @@ public abstract class BlockBase { - return this.getBlock().d(this.p(), iblockaccess, blockposition); - } - -- public boolean d() { -+ public final boolean d() { // Paper - return this.a == null || this.a.c; - } - -- public boolean e() { -+ public final boolean e() { // Paper - return this.e; - } - -- public int f() { -+ public final int f() { // Paper - return this.b; - } - -- public boolean isAir() { -+ public final boolean isAir() { // Paper - return this.f; - } - -@@ -508,7 +515,7 @@ public abstract class BlockBase { - } - } - -- public boolean l() { -+ public final boolean l() { // Paper - return this.k; - } - -@@ -680,12 +687,12 @@ public abstract class BlockBase { - return this.getBlock().a(block); - } - -- public Fluid getFluid() { -- return this.getBlock().d(this.p()); -+ public final Fluid getFluid() { // Paper -+ return this.fluid; // Paper - moved into init - } - -- public boolean isTicking() { -- return this.getBlock().isTicking(this.p()); -+ public final boolean isTicking() { // Paper -+ return this.isTicking; // Paper - moved into init - } - - public SoundEffectType getStepSound() { -diff --git a/src/main/java/net/minecraft/world/level/material/Fluid.java b/src/main/java/net/minecraft/world/level/material/Fluid.java -index 9a93b204973eef4c02a52f33fd9578a43603ed98..147e628bd562da4cf6f07218724a9d6c79d26e38 100644 ---- a/src/main/java/net/minecraft/world/level/material/Fluid.java -+++ b/src/main/java/net/minecraft/world/level/material/Fluid.java -@@ -20,8 +20,12 @@ public final class Fluid extends IBlockDataHolder { - - public static final Codec a = a((Codec) IRegistry.FLUID, FluidType::h).stable(); - -+ // Paper start -+ protected final boolean isEmpty; -+ // Paper end - public Fluid(FluidType fluidtype, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(fluidtype, immutablemap, mapcodec); -+ this.isEmpty = fluidtype.b(); // Paper - moved from isEmpty() - } - - public FluidType getType() { -@@ -33,7 +37,7 @@ public final class Fluid extends IBlockDataHolder { - } - - public boolean isEmpty() { -- return this.getType().b(); -+ return this.isEmpty; // Paper - moved into constructor - } - - public float getHeight(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch b/Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch deleted file mode 100644 index 418df8075617..000000000000 --- a/Spigot-Server-Patches/0583-Retain-block-place-order-when-capturing-blockstates.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 7 Aug 2020 04:27:56 -0700 -Subject: [PATCH] Retain block place order when capturing blockstates - -Fixes twisted vines not connecting properly when grown via -bonemeal by a player. - -In general, look at making this logic more robust (i.e properly handling -cases where a captured entry is overriden) - but for now this will do. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 307a89c431739ed15d8869faace7b08927626f60..ae5f9a6af810b524f6dcbed64bc943122f0536cc 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -135,7 +135,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; - public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper -- public Map capturedTileEntities = new HashMap<>(); -+ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - public List captureDrops; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; diff --git a/Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch b/Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch deleted file mode 100644 index 26401893244d..000000000000 --- a/Spigot-Server-Patches/0584-Reduce-blockpos-allocation-from-pathfinding.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Apr 2020 17:10:55 -0700 -Subject: [PATCH] Reduce blockpos allocation from pathfinding - - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index d14f2800237c2a80912bf6f2d418a9ba9031070d..a0c7d3ab747ba1a3cf07e716f3591663a8a9e14b 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -498,7 +498,7 @@ public class PathfinderNormal extends PathfinderAbstract { - return PathType.DANGER_FIRE; - } - -- if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { -+ if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call - return PathType.WATER_BORDER; - } - } // Paper -@@ -528,7 +528,7 @@ public class PathfinderNormal extends PathfinderAbstract { - } else if (iblockdata.a(Blocks.COCOA)) { - return PathType.COCOA; - } else { -- Fluid fluid = iblockaccess.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - remove another get type call - - return fluid.a((Tag) TagsFluid.WATER) ? PathType.WATER : (fluid.a((Tag) TagsFluid.LAVA) ? PathType.LAVA : (a(iblockdata) ? PathType.DAMAGE_FIRE : (BlockDoor.l(iblockdata) && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_WOOD_CLOSED : (block instanceof BlockDoor && material == Material.ORE && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_IRON_CLOSED : (block instanceof BlockDoor && (Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_OPEN : (block instanceof BlockMinecartTrackAbstract ? PathType.RAIL : (block instanceof BlockLeaves ? PathType.LEAVES : (!block.a((Tag) TagsBlock.FENCES) && !block.a((Tag) TagsBlock.WALLS) && (!(block instanceof BlockFenceGate) || (Boolean) iblockdata.get(BlockFenceGate.OPEN)) ? (!iblockdata.a(iblockaccess, blockposition, PathMode.LAND) ? PathType.BLOCKED : PathType.OPEN) : PathType.FENCE)))))))); - } diff --git a/Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch b/Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch deleted file mode 100644 index 764f6d797905..000000000000 --- a/Spigot-Server-Patches/0585-Fix-item-locations-dropped-from-campfires.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 20:32:25 -0500 -Subject: [PATCH] Fix item locations dropped from campfires - -Fixes #4259 by not flooring the blockposition among other weirdness - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index df010dc740f2dd647a418ba4e425ce3a3b1d79e2..62a19f39405cff27f34a3b98fb9310b1c9c27563 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -14,6 +14,7 @@ import net.minecraft.world.Clearable; - import net.minecraft.world.ContainerUtil; - import net.minecraft.world.InventorySubcontainer; - import net.minecraft.world.InventoryUtils; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeCampfire; - import net.minecraft.world.item.crafting.Recipes; -@@ -92,7 +93,11 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - // CraftBukkit end -- InventoryUtils.dropItem(this.world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); -+ // Paper start -+ EntityItem droppedItem = new EntityItem(this.world, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.cloneAndSubtract(this.world.random.nextInt(21) + 10)); -+ droppedItem.setMot(this.world.random.nextGaussian() * 0.05D, this.world.random.nextGaussian() * 0.05D + 0.2D, this.world.random.nextGaussian() * 0.05D); -+ this.world.addEntity(droppedItem); -+ // Paper end - this.items.set(i, ItemStack.b); - this.k(); - } diff --git a/Spigot-Server-Patches/0586-Player-elytra-boost-API.patch b/Spigot-Server-Patches/0586-Player-elytra-boost-API.patch deleted file mode 100644 index aed9bb22475c..000000000000 --- a/Spigot-Server-Patches/0586-Player-elytra-boost-API.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:05:22 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 18d7cf6e783843d44715210b7c8db7bf0a5c89ae..8337ed8bb20b8d887bcd71ddc5f29bce346c7cff 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -69,12 +69,14 @@ import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -2284,6 +2286,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - throw new RuntimeException("Unknown settings type"); - } -+ -+ @Override -+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { -+ Validate.isTrue(isGliding(), "Player must be gliding"); -+ Validate.isTrue(firework != null, "firework == null"); -+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); -+ -+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); -+ World world = ((CraftWorld) getWorld()).getHandle(); -+ EntityFireworks entity = new EntityFireworks(world, item, getHandle()); -+ return world.addEntity(entity) -+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() -+ : null; -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch b/Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch deleted file mode 100644 index 879f75271604..000000000000 --- a/Spigot-Server-Patches/0587-Fixed-TileEntityBell-memory-leak.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: giacomo <32515303+giacomozama@users.noreply.github.com> -Date: Sat, 10 Oct 2020 12:15:33 +0200 -Subject: [PATCH] Fixed TileEntityBell memory leak - -TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -index e97d229da3cf7631555f418a73bc74255494cc01..84f9f52c5b632621b509448ac1c760f64de6b062 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -@@ -27,8 +27,8 @@ public class TileEntityBell extends TileEntity implements ITickable { - public int a; - public boolean b; - public EnumDirection c; -- private List h; -- private boolean i; -+ private List h; private List getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER -+ private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER - private int j; - - public TileEntityBell() { -@@ -57,6 +57,11 @@ public class TileEntityBell extends TileEntity implements ITickable { - - if (this.a >= 50) { - this.b = false; -+ // Paper start -+ if (!this.getShouldReveal()) { -+ this.getEntitiesAtRing().clear(); -+ } -+ // Paper end - this.a = 0; - } - -@@ -71,6 +76,7 @@ public class TileEntityBell extends TileEntity implements ITickable { - } else { - this.a(this.world); - this.b(this.world); -+ this.getEntitiesAtRing().clear(); // Paper - this.i = false; - } - } -@@ -111,11 +117,12 @@ public class TileEntityBell extends TileEntity implements ITickable { - EntityLiving entityliving = (EntityLiving) iterator.next(); - - if (entityliving.isAlive() && !entityliving.dead && blockposition.a((IPosition) entityliving.getPositionVector(), 32.0D)) { -- entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.world.getTime()); -+ entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.world.getTime()); // Paper - decompile fix - } - } - } - -+ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper - } - - private boolean h() { diff --git a/Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch deleted file mode 100644 index 183a7c372f3e..000000000000 --- a/Spigot-Server-Patches/0588-Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Toon Schoenmakers -Date: Fri, 23 Oct 2020 15:01:44 +0200 -Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing - loot - -This can realistically only happen if there's custom loot active on fishing -which can return 0 items. This would disconnect the player who's fishing. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 38bcc5a4435c4018b3233cc5e4c9142259e4396d..45f0f004e97b20e5c6c5b1f205b088bf8aa86017 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -484,9 +484,15 @@ public class EntityFishingHook extends IProjectile { - - while (iterator.hasNext()) { - ItemStack itemstack1 = (ItemStack) iterator.next(); -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty -+ // if the item stack is empty we instead just have our entityitem as null -+ EntityItem entityitem = null; -+ if (!itemstack1.isEmpty()) { -+ entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ } -+ // Paper end - // CraftBukkit start -- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); -+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null - playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); - this.world.getServer().getPluginManager().callEvent(playerFishEvent); - -@@ -499,8 +505,12 @@ public class EntityFishingHook extends IProjectile { - double d2 = entityhuman.locZ() - this.locZ(); - double d3 = 0.1D; - -- entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -- this.world.addEntity(entityitem); -+ // Paper start, entity item can be null, so we need to check against this -+ if (entityitem != null) { -+ entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -+ this.world.addEntity(entityitem); -+ } -+ // Paper end - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { - entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper diff --git a/Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch b/Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index daefd94b8e67..000000000000 --- a/Spigot-Server-Patches/0589-Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:34:50 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 53254ad9e775e9e78da238a54be7d3fc4b8a6ced..49d989545aa1a02ecc811a74f0283e779d2543a0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1614,6 +1614,28 @@ public final class CraftServer implements Server { - return result; - } - -+ // Paper start -+ @Override -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(String name) { -+ Validate.notNull(name, "Name cannot be null"); -+ Validate.notEmpty(name, "Name cannot be empty"); -+ -+ OfflinePlayer result = getPlayerExact(name); -+ if (result == null) { -+ GameProfile profile = console.getUserCache().getProfileIfCached(name); -+ -+ if (profile != null) { -+ result = getOfflinePlayer(profile); -+ } -+ } else { -+ offlinePlayers.remove(result.getUniqueId()); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOfflinePlayer(UUID id) { - Validate.notNull(id, "UUID cannot be null"); diff --git a/Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch b/Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch deleted file mode 100644 index 6a4454312bfa..000000000000 --- a/Spigot-Server-Patches/0590-Add-ignore-discounts-API.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:44:51 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index b7c16dfa4ed7d68596c5b5d5037ce0ac3810ecfa..e24c598c9d662144b91075ac80a193db2e0cb111 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -460,6 +460,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator.hasNext()) { - MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); -+ if (merchantrecipe.ignoreDiscounts) continue; // Paper - - // CraftBukkit start - int bonus = -MathHelper.d((float) i * merchantrecipe.getPriceMultiplier()); -@@ -479,6 +480,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator1.hasNext()) { - MerchantRecipe merchantrecipe1 = (MerchantRecipe) iterator1.next(); -+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper - double d0 = 0.3D + 0.0625D * (double) j; - int k = (int) Math.floor(d0 * (double) merchantrecipe1.a().getCount()); - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index 9e2fe0d5e6d4ea1f4c9cea96b755ddcd1e3c9009..605d1b2514c272c0fcf3cb9d7575ad8066dad31b 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -19,6 +19,7 @@ public class MerchantRecipe { - private int demand; - public float priceMultiplier; - public int xp; -+ public boolean ignoreDiscounts; // Paper - // CraftBukkit start - private CraftMerchantRecipe bukkitHandle; - -@@ -27,7 +28,12 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { -- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.bukkitHandle = bukkit; - } - // CraftBukkit end -@@ -59,6 +65,7 @@ public class MerchantRecipe { - - this.specialPrice = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { -@@ -70,10 +77,19 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f) { -- this(itemstack, itemstack1, itemstack2, i, j, k, f, 0); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.rewardExp = true; - this.xp = 1; - this.buyingItem1 = itemstack; -@@ -189,6 +205,7 @@ public class MerchantRecipe { - nbttagcompound.setFloat("priceMultiplier", this.priceMultiplier); - nbttagcompound.setInt("specialPrice", this.specialPrice); - nbttagcompound.setInt("demand", this.demand); -+ nbttagcompound.setBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper - return nbttagcompound; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -index e3b9a0ebe5cec5b47d9d225887656e00e999960b..0c8728bd8272e36d70cf8f05fcd7656ea5a48702 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -@@ -17,7 +17,12 @@ public class CraftMerchantRecipe extends MerchantRecipe { - } - - public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { -- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); -+ } -+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { -+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.handle = new net.minecraft.world.item.trading.MerchantRecipe( - net.minecraft.world.item.ItemStack.b, - net.minecraft.world.item.ItemStack.b, -@@ -26,6 +31,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - maxUses, - experience, - priceMultiplier, -+ ignoreDiscounts, // Paper - add ignoreDiscounts param - this - ); - this.setExperienceReward(experienceReward); -@@ -81,6 +87,18 @@ public class CraftMerchantRecipe extends MerchantRecipe { - handle.priceMultiplier = priceMultiplier; - } - -+ // Paper start -+ @Override -+ public boolean shouldIgnoreDiscounts() { -+ return this.handle.ignoreDiscounts; -+ } -+ -+ @Override -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.handle.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end -+ - public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() { - List ingredients = getIngredients(); - Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); -@@ -95,7 +113,7 @@ public class CraftMerchantRecipe extends MerchantRecipe { - if (recipe instanceof CraftMerchantRecipe) { - return (CraftMerchantRecipe) recipe; - } else { -- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); -+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts - craft.setIngredients(recipe.getIngredients()); - - return craft; diff --git a/Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch b/Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch deleted file mode 100644 index 724d1c211144..000000000000 --- a/Spigot-Server-Patches/0591-Toggle-for-removing-existing-dragon.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 30 Sep 2020 22:49:14 +0200 -Subject: [PATCH] Toggle for removing existing dragon - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 02bb85364560784adea47c877c13291c3d016b86..424754a0183b071d20c86f0420cec784a8992e2b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -683,4 +683,12 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); - } - } -+ -+ public boolean shouldRemoveDragon = false; -+ private void shouldRemoveDragon() { -+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); -+ if (shouldRemoveDragon) { -+ log("The Ender Dragon will be removed if she already exists without a portal."); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index c6283489dcb6e13f0d618971614aeadaee2e3007..c0a6b340810b8ea4f454290b1ac22316ff0e6e22 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -214,7 +214,7 @@ public class EnderDragonBattle { - this.dragonUUID = entityenderdragon.getUniqueID(); - EnderDragonBattle.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); - this.dragonKilled = false; -- if (!flag) { -+ if (!flag && this.world.paperConfig.shouldRemoveDragon) { // Paper - EnderDragonBattle.LOGGER.info("But we didn't have a portal, let's remove it."); - entityenderdragon.die(); - this.dragonUUID = null; diff --git a/Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch b/Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch deleted file mode 100644 index c2ef60d3c738..000000000000 --- a/Spigot-Server-Patches/0592-Fix-client-lag-on-advancement-loading.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 31 Oct 2020 11:49:01 -0700 -Subject: [PATCH] Fix client lag on advancement loading - -When new advancements are added via the UnsafeValues#loadAdvancement -API, it triggers a full datapack reload when this is not necessary. The -advancement is already loaded directly into the advancement registry, -and the point of saving the advancement to the Bukkit datapack seems to -be for persistence. By removing the call to reload datapacks when an -advancement is loaded, the client no longer completely freezes up when -adding a new advancement. -To ensure the client still receives the updated advancement data, we -manually reload the advancement data for all players, which -normally takes place as a part of the datapack reloading. - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 8e760445885f6ab92f60db0ee2a02d098b5e5f03..7a8a1960882e291c46301d07da3e1c5415516893 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -97,6 +97,7 @@ public class AdvancementDataPlayer { - - } - -+ public final void reload(AdvancementDataWorld advancementDataWorld) { this.a(advancementDataWorld); } // Paper - OBFHELPER - public void a(AdvancementDataWorld advancementdataworld) { - this.a(); - this.data.clear(); -@@ -393,6 +394,7 @@ public class AdvancementDataPlayer { - - } - -+ public final void sendUpdateIfNeeded(EntityPlayer entityPlayer) { this.b(entityPlayer); } // Paper - OBFHELPER - public void b(EntityPlayer entityplayer) { - if (this.m || !this.i.isEmpty() || !this.j.isEmpty()) { - Map map = Maps.newHashMap(); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 5b03187f4d76e3052ee9abe0ee2774218d41b864..36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -309,7 +309,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); - } - -- MinecraftServer.getServer().getPlayerList().reload(); -+ // Paper start -+ //MinecraftServer.getServer().getPlayerList().reload(); -+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { -+ player.getAdvancementData().reload(MinecraftServer.getServer().getAdvancementData()); -+ player.getAdvancementData().sendUpdateIfNeeded(player); -+ }); -+ // Paper end - - return bukkit; - } diff --git a/Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch b/Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch deleted file mode 100644 index 84124da98a54..000000000000 --- a/Spigot-Server-Patches/0593-Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:33 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 5988cdd18b7e4bfca0075fd2356cfe9c4e673954..7a78ef2f6f673568c0528fa46168c69d21f51a66 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -10,6 +10,12 @@ import org.bukkit.entity.Item; - import org.bukkit.inventory.ItemStack; - - public class CraftItem extends CraftEntity implements Item { -+ -+ // Paper start -+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; -+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; -+ // Paper end -+ - private final EntityItem item; - - public CraftItem(CraftServer server, Entity entity, EntityItem item) { -@@ -57,6 +63,26 @@ public class CraftItem extends CraftEntity implements Item { - public void setCanMobPickup(boolean canMobPickup) { - item.canMobPickup = canMobPickup; - } -+ -+ @Override -+ public boolean canPlayerPickup() { -+ return item.pickupDelay != NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public void setCanPlayerPickup(boolean canPlayerPickup) { -+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public boolean willAge() { -+ return item.age != NO_AGE_TIME; -+ } -+ -+ @Override -+ public void setWillAge(boolean willAge) { -+ item.age = willAge ? 0 : NO_AGE_TIME; -+ } - // Paper End - - @Override diff --git a/Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch b/Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index f32bda9f013a..000000000000 --- a/Spigot-Server-Patches/0594-Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:39:08 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index f9b1ab0e19ff398a16b1452e86f1a165a4b54219..8dfb9eb12d07c2d4737ecf3de1ae7f6de31891bf 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -73,6 +73,26 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryEffect, getLevel(), getAmplification(), true, true)) : null; - } - // CraftBukkit end -+ // Paper start - add field/methods for custom range -+ private final String PAPER_RANGE_TAG = "Paper.Range"; -+ private double effectRange = -1; -+ -+ public double getEffectRange() { -+ if (this.effectRange < 0) { -+ return this.levels * 10 + 10; -+ } else { -+ return effectRange; -+ } -+ } -+ -+ public void setEffectRange(double range) { -+ this.effectRange = range; -+ } -+ -+ public void resetEffectRange() { -+ this.effectRange = -1; -+ } -+ // Paper end - - public TileEntityBeacon() { - super(TileEntityTypes.BEACON); -@@ -263,7 +283,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - public List getHumansInRange() { - { -- double d0 = (double) (this.levels * 10 + 10); -+ // Paper - custom beacon ranges -+ double d0 = this.getEffectRange(); - - AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.position)).g(d0).b(0.0D, (double) this.world.getBuildHeight(), 0.0D); - List list = this.world.a(EntityHuman.class, axisalignedbb); -@@ -364,6 +385,9 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - this.secondaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Secondary")); - this.levels = nbttagcompound.getInt("Levels"); // SPIGOT-5053, use where available - // CraftBukkit end -+ // Paper -+ this.effectRange = nbttagcompound.hasKeyOfType(PAPER_RANGE_TAG, 6) ? nbttagcompound.getDouble(PAPER_RANGE_TAG) : -1; -+ - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { - this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); - } -@@ -380,6 +404,8 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - if (this.customName != null) { - nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(this.customName)); - } -+ // Paper -+ nbttagcompound.setDouble(PAPER_RANGE_TAG, this.effectRange); - - this.chestLock.a(nbttagcompound); - return nbttagcompound; -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index d3ae5cadd88f9012203d2c04cbe38af9b215ef0b..c2e054853cba891326d45e9129bbc09e32fa3cc7 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -108,4 +108,19 @@ public class CraftBeacon extends CraftBlockEntityState impleme - public void setLock(String key) { - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } -+ -+ @Override -+ public double getEffectRange() { -+ return this.getSnapshot().getEffectRange(); -+ } -+ -+ @Override -+ public void setEffectRange(double range) { -+ this.getSnapshot().setEffectRange(range); -+ } -+ -+ @Override -+ public void resetEffectRange() { -+ this.getSnapshot().resetEffectRange(); -+ } - } diff --git a/Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch b/Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch deleted file mode 100644 index c540a10b73fc..000000000000 --- a/Spigot-Server-Patches/0595-Add-API-for-quit-reason.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:52 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 878f879f8d410c428ad8a4c49e0c86c559bc47a9..f86f430598026a3a7e27fb8d40cfc5fe7b9b845d 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -137,12 +137,15 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - this.u = true; - if (this.channel.isOpen()) { -+ EntityPlayer player = this.getPlayer(); // Paper - if (throwable instanceof TimeoutException) { - NetworkManager.LOGGER.debug("Timeout", throwable); -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper - this.close(new ChatMessage("disconnect.timeout")); - } else { - ChatMessage chatmessage = new ChatMessage("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); - -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - if (flag) { - NetworkManager.LOGGER.debug("Failed to sent packet", throwable); - this.sendPacket(new PacketPlayOutKickDisconnect(chatmessage), (future) -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3908dc27a5cf127ab3c3630da47318da1bf4e3c9..78fcb90c86700ee6feef0d40753fc8d8a943777f 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -261,6 +261,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - - boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event - - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 8ffc98faecca616005fc56031718a7a10de40102..d00c17210b3c0aff40b37ff11f8e9dc6ae1ba948 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -449,6 +449,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - -+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { - this.networkManager.close(ichatbasecomponent); - }); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8bd55e3d2b5142081a7dfe1dbbd36f2f995e5856..e0bbb7f3ea7ce4902cd14e64357472087ce6912a 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -590,7 +590,7 @@ public abstract class PlayerList { - entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName())), entityplayer.quitReason); // Paper - quit reason - if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - diff --git a/Spigot-Server-Patches/0596-Seed-based-feature-search.patch b/Spigot-Server-Patches/0596-Seed-based-feature-search.patch deleted file mode 100644 index 00261682ebf1..000000000000 --- a/Spigot-Server-Patches/0596-Seed-based-feature-search.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Mon, 13 Jan 2020 15:40:32 +0100 -Subject: [PATCH] Seed based feature search - -This tries to work around the issue where the server will load -surrounding chunks up to a radius of 100 chunks in order to search for -features e.g. when running the /locate command or for treasure maps -(issue #2312). -This is done by backporting Mojang's change in 1.17 which makes it so -that the biome (generated by the seed) is checked first if the feature -can be generated before actually to load the chunk. - -The only downside of this is that it breaks once the seed or generator -changes but this should usually not happen. A config option to disable -this improvement is added though in case that should ever be necessary. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 424754a0183b071d20c86f0420cec784a8992e2b..a98e25917193043633e2120beb4fe2d49d0e4500 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -337,6 +337,12 @@ public class PaperWorldConfig { - } - } - -+ public boolean seedBasedFeatureSearch = true; -+ private void seedBasedFeatureSearch() { -+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); -+ log("Feature search is based on seed: " + seedBasedFeatureSearch); -+ } -+ - public int maxCollisionsPerEntity; - private void maxEntityCollision() { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index e41d63596c32eee5f0c04a6f043d576d8021ff1a..53eb5b65683a2ab208edfc3f3bbf78ffee61bc85 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -68,10 +68,12 @@ public class ChunkCoordIntPair { - } - } - -+ public int getBlockX() { return d(); } // Paper - OBFHELPER - public int d() { - return this.x << 4; - } - -+ public int getBlockZ() { return e(); } // Paper - OBFHELPER - public int e() { - return this.z << 4; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index ae5f9a6af810b524f6dcbed64bc943122f0536cc..f40be366ebc5f98b417b677565fa89d3f817f3fb 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -1511,8 +1511,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.methodProfiler; - } - -- @Override -- public BiomeManager d() { -+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER -+ @Override public BiomeManager d() { - return this.biomeManager; - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -index 340508e0ba8b8883a3037ecaa2d4e09e61e709d3..3b1d9b26ba3249b1df0c15a22428e4211ae0e024 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -@@ -23,6 +23,7 @@ public class BiomeManager { - return new BiomeManager(worldchunkmanager, this.b, this.c); - } - -+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER - public BiomeBase a(BlockPosition blockposition) { - return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index ea7e3e15fa778c573d24f956f72f60579ea0b1a1..6df42ff26ff6e65ec2885122fe53dde857a3d1d2 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -176,6 +176,14 @@ public abstract class StructureGenerator - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); - if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper -+ // Paper start - seed based feature search -+ if (structuremanager.getWorld().paperConfig.seedBasedFeatureSearch) { -+ BiomeBase biomeBase = structuremanager.getWorld().getBiomeManager().getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); -+ if (!biomeBase.e().a(this)) { -+ continue; -+ } -+ } -+ // Paper end - IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - diff --git a/Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch b/Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch deleted file mode 100644 index 7ec0e046eae0..000000000000 --- a/Spigot-Server-Patches/0597-Add-Wandering-Trader-spawn-rate-config-options.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 20 Aug 2020 11:20:12 -0700 -Subject: [PATCH] Add Wandering Trader spawn rate config options - -Adds config options for modifying the spawn rates of Wandering Traders. -These values are all easy to understand and configure after a quick read of this -page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning -Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values -in IWorldServerData are removed as they were only used in certain places, with hardcoded -values used in other places. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a98e25917193043633e2120beb4fe2d49d0e4500..b4d76494851601d61a69e2f060727a68f4461267 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -697,4 +697,17 @@ public class PaperWorldConfig { - log("The Ender Dragon will be removed if she already exists without a portal."); - } - } -+ -+ public int wanderingTraderSpawnMinuteTicks = 1200; -+ public int wanderingTraderSpawnDayTicks = 24000; -+ public int wanderingTraderSpawnChanceFailureIncrement = 25; -+ public int wanderingTraderSpawnChanceMin = 25; -+ public int wanderingTraderSpawnChanceMax = 75; -+ private void wanderingTraderSettings() { -+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); -+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); -+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); -+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); -+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index b74a262a62642f63fdbd17579d58d5eae68ed169..e57938b4591bb103b9dd0d0145a62b5a901f2c63 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -30,49 +30,59 @@ public class MobSpawnerTrader implements MobSpawner { - - private final Random a = new Random(); - private final IWorldDataServer b; -- private int c; -- private int d; -- private int e; -+ private int c; public final int getMinuteTimer() { return this.c; } public final void setMinuteTimer(int x) { this.c = x; } // Paper - OBFHELPER -+ private int d; public final int getDayTimer() { return this.d; } public final void setDayTimer(int x) { this.d = x; } // Paper - OBFHELPER -+ private int e; public final int getSpawnChance() { return this.e; } public final void setSpawnChance(int x) { this.e = x; } // Paper - OBFHELPER - - public MobSpawnerTrader(IWorldDataServer iworlddataserver) { - this.b = iworlddataserver; -- this.c = 1200; -- this.d = iworlddataserver.v(); -- this.e = iworlddataserver.w(); -- if (this.d == 0 && this.e == 0) { -- this.d = 24000; -- iworlddataserver.g(this.d); -- this.e = 25; -- iworlddataserver.h(this.e); -- } -+ // Paper start -+ this.setMinuteTimer(Integer.MIN_VALUE); -+ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //if (this.d == 0 && this.e == 0) { -+ // this.d = 24000; -+ // iworlddataserver.g(this.d); -+ // this.e = 25; -+ // iworlddataserver.h(this.e); -+ //} -+ // Paper end - - } - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ // Paper start -+ if (this.getMinuteTimer() == Integer.MIN_VALUE) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ } - if (!worldserver.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING)) { - return 0; -- } else if (--this.c > 0) { -+ } else if (this.getMinuteTimer() - 1 > 0) { -+ this.setMinuteTimer(this.getMinuteTimer() - 1); - return 0; - } else { -- this.c = 1200; -- this.d -= 1200; -- this.b.g(this.d); -- if (this.d > 0) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(getDayTimer() - worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways -+ if (this.getDayTimer() > 0) { - return 0; - } else { -- this.d = 24000; -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); - if (!worldserver.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING)) { - return 0; - } else { -- int i = this.e; -+ int i = this.getSpawnChance(); - -- this.e = MathHelper.clamp(this.e + 25, 25, 75); -- this.b.h(this.e); -+ this.setSpawnChance(MathHelper.clamp(i + worldserver.paperConfig.wanderingTraderSpawnChanceFailureIncrement, worldserver.paperConfig.wanderingTraderSpawnChanceMin, worldserver.paperConfig.wanderingTraderSpawnChanceMax)); -+ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways - if (this.a.nextInt(100) > i) { - return 0; - } else if (this.a(worldserver)) { -- this.e = 25; -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ // Paper end - return 1; - } else { - return 0; diff --git a/Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch b/Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch deleted file mode 100644 index b205a133b363..000000000000 --- a/Spigot-Server-Patches/0598-Significantly-improve-performance-of-the-end-generat.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> -Date: Tue, 3 Nov 2020 23:48:05 -0600 -Subject: [PATCH] Significantly improve performance of the end generation - -This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. - -Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) - -Co-authored-by: Gegy -Co-authored-by: Dylan Xaldin -Co-authored-by: pop4959 - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 1077972d694d604c3ec97d333d34a9ab81819c33..62fe4cc00a24e330443d2f006a88dbab3798fb28 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -3,10 +3,12 @@ package net.minecraft.world.level.biome; - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; -+import it.unimi.dsi.fastutil.HashCommon; // Paper - import java.util.List; - import net.minecraft.core.IRegistry; - import net.minecraft.resources.RegistryLookupCodec; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3Handler; - -@@ -27,6 +29,16 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - private final BiomeBase k; - private final BiomeBase l; - private final BiomeBase m; -+ // Paper start -+ private static final class NoiseCache { -+ public long[] keys = new long[8192]; -+ public float[] values = new float[8192]; -+ public NoiseCache() { -+ java.util.Arrays.fill(keys, Long.MIN_VALUE); -+ } -+ } -+ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); -+ // Paper end - - public WorldChunkManagerTheEnd(IRegistry iregistry, long i) { - this(iregistry, i, (BiomeBase) iregistry.d(Biomes.THE_END), (BiomeBase) iregistry.d(Biomes.END_HIGHLANDS), (BiomeBase) iregistry.d(Biomes.END_MIDLANDS), (BiomeBase) iregistry.d(Biomes.SMALL_END_ISLANDS), (BiomeBase) iregistry.d(Biomes.END_BARRENS)); -@@ -81,13 +93,27 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - - f = MathHelper.a(f, -100.0F, 80.0F); - -+ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper - for (int k1 = -12; k1 <= 12; ++k1) { - for (int l1 = -12; l1 <= 12; ++l1) { - long i2 = (long) (k + k1); - long j2 = (long) (l + l1); - -- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -- float f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = ChunkCoordIntPair.pair((int) i2, (int) j2); -+ int index = (int) HashCommon.mix(key) & 8191; -+ float f1 = Float.MIN_VALUE; -+ if (cache.keys[index] == key) { -+ f1 = cache.values[index]; -+ } else { -+ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -+ f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ } -+ cache.keys[index] = key; -+ cache.values[index] = f1; -+ } -+ if (f1 != Float.MIN_VALUE) { -+ // Paper end - float f2 = (float) (i1 - k1 * 2); - float f3 = (float) (j1 - l1 * 2); - float f4 = 100.0F - MathHelper.c(f2 * f2 + f3 * f3) * f1; diff --git a/Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch b/Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch deleted file mode 100644 index 881cbed4050a..000000000000 --- a/Spigot-Server-Patches/0599-Expose-world-spawn-angle.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Tue, 17 Nov 2020 19:13:09 +0200 -Subject: [PATCH] Expose world spawn angle - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e0bbb7f3ea7ce4902cd14e64357472087ce6912a..66fbbc4c91e16a3dfb4bb756972e667121693501 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -894,7 +894,7 @@ public abstract class PlayerList { - if (location == null) { - worldserver1 = this.server.getWorldServer(World.OVERWORLD); - blockposition = entityplayer1.getSpawnPoint(worldserver1); -- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); -+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.worldData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldData.java b/src/main/java/net/minecraft/world/level/storage/WorldData.java -index 81ad90ba93481decdfaa38fc9fa81bca0e402781..7599488f7d4b168c92078c2d2987cb38f0dee8a9 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldData.java -@@ -12,6 +12,7 @@ public interface WorldData { - - int c(); - -+ default float getSpawnAngle() { return d(); } // Paper - OBFHELPER - float d(); - - long getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 76a7889b49a16ddeb8f310d3a79cfee80ad9a1db..776733a4a913d232126b48f2d0eadbe27aa84e59 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -380,7 +380,7 @@ public class CraftWorld implements World { - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); -- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); -+ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.worldData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle - } - - @Override diff --git a/Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch b/Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch deleted file mode 100644 index bdeb073a8514..000000000000 --- a/Spigot-Server-Patches/0600-Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:48:06 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index f1f03bd0162a158761f300cbd96aa32101542abb..fab9e1e5d63c22faceae093dc88769d203d359c6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -769,5 +769,23 @@ public class CraftBlock implements Block { - public String getTranslationKey() { - return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ @Override -+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { -+ net.minecraft.world.item.ItemStack nmsItemStack; -+ if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); -+ } else { -+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ } -+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().getBlockData()); -+ if (speed > 1.0F && considerEnchants) { -+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentManager.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.DIG_SPEED, nmsItemStack); -+ if (enchantLevel > 0) { -+ speed += enchantLevel * enchantLevel + 1; -+ } -+ } -+ return speed; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch deleted file mode 100644 index 54e629a54c01..000000000000 --- a/Spigot-Server-Patches/0601-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Esophose -Date: Sat, 3 Oct 2020 18:57:47 -0600 -Subject: [PATCH] Fix Player spawnParticle x/y/z precision loss - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8337ed8bb20b8d887bcd71ddc5f29bce346c7cff..41987716afa8ec34214868373df97d0e8f8b27c1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2012,7 +2012,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } -- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); -+ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss - getHandle().playerConnection.sendPacket(packetplayoutworldparticles); - - } diff --git a/Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch b/Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index 7856335fa171..000000000000 --- a/Spigot-Server-Patches/0602-Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:08:49 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 090e0931df410526cb7b0aab196a01f57ffbb285..5d2ed8a0cf8351df1c8b2946f8a614fe13c34673 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -785,6 +785,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().activeItem.asBukkitMirror(); - } - -+ // Paper start -+ @Override -+ public void clearActiveItem() { -+ getHandle().clearActiveItem(); -+ } -+ // Paper end -+ - @Override - public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); diff --git a/Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch b/Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 81581680ce78..000000000000 --- a/Spigot-Server-Patches/0603-Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Tue, 25 Aug 2020 13:48:33 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -index 5f70e39f4da2880a6f734a225be83061b00847c8..ef9ffad211473f1cbcd0b8fd200ff04ec2051f94 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -@@ -3,14 +3,26 @@ package net.minecraft.world.item; - import net.minecraft.network.protocol.game.PacketPlayOutSetCooldown; - import net.minecraft.server.level.EntityPlayer; - -+import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper -+ - public class ItemCooldownPlayer extends ItemCooldown { - -- private final EntityPlayer a; -+ private final EntityPlayer a; public EntityPlayer getEntityPlayer() { return a; } // Paper - OBFHELPER - - public ItemCooldownPlayer(EntityPlayer entityplayer) { - this.a = entityplayer; - } - -+ // Paper start -+ @Override -+ public void setCooldown(Item item, int ticks) { -+ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), ticks); -+ if (event.callEvent()) { -+ super.setCooldown(item, event.getCooldown()); -+ } -+ } -+ // Paper end -+ - @Override - protected void b(Item item, int i) { - super.b(item, i); diff --git a/Spigot-Server-Patches/0604-More-lightning-API.patch b/Spigot-Server-Patches/0604-More-lightning-API.patch deleted file mode 100644 index e08b3251e516..000000000000 --- a/Spigot-Server-Patches/0604-More-lightning-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Sun, 26 Jul 2020 14:44:09 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 834ced9d9b385c8f1d66355244313d62a97d9c98..85f571a791bce63989890f277857bc7bdeec0cb5 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -31,7 +31,7 @@ public class EntityLightning extends Entity { - - private int lifeTicks; - public long b; -- private int d; -+ private int d; public int getFlashCount() { return d; } public void setFlashCount(int flashes) { this.d = flashes; } // Paper - OBFHELPER - public boolean isEffect; - @Nullable - private EntityPlayer f; -@@ -49,6 +49,16 @@ public class EntityLightning extends Entity { - this.isEffect = flag; - } - -+ // Paper start -+ public int getLifeTicks() { -+ return lifeTicks; -+ } -+ -+ public void setLifeTicks(int lifeTicks) { -+ this.lifeTicks = lifeTicks; -+ } -+ // Paper end -+ - @Override - public SoundCategory getSoundCategory() { - return SoundCategory.WEATHER; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index 3e054592cef6526b769d14460a671ea78a5ef58a..395f702b14425d85ff3a7938c32f7bfd5523f3ca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -@@ -45,4 +45,27 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public int getFlashCount() { -+ return getHandle().getFlashCount(); -+ } -+ -+ @Override -+ public void setFlashCount(int flashes) { -+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); -+ getHandle().setFlashCount(flashes); -+ } -+ -+ @Override -+ public int getLifeTicks() { -+ return getHandle().getLifeTicks(); -+ } -+ -+ @Override -+ public void setLifeTicks(int lifeTicks) { -+ getHandle().setLifeTicks(lifeTicks); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch b/Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch deleted file mode 100644 index 4c501b7baa2f..000000000000 --- a/Spigot-Server-Patches/0605-Climbing-should-not-bypass-cramming-gamerule.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 20:59:00 +0200 -Subject: [PATCH] Climbing should not bypass cramming gamerule - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b4d76494851601d61a69e2f060727a68f4461267..6262246c4018c660705fbad028f297fc44e7197f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -710,4 +710,9 @@ public class PaperWorldConfig { - wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); - wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); - } -+ -+ public boolean fixClimbingBypassingCrammingRule = false; -+ private void fixClimbingBypassingCrammingRule() { -+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 2a3025793db52a18e58f832c9da78c6c3b39d33c..d801486565865cf3b56e9d80b7c1643e9b0f4597 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1575,6 +1575,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isCollidable() { -+ // Paper start -+ return isCollidable(false); -+ } -+ -+ public boolean isCollidable(boolean ignoreClimbing) { -+ // Paper end - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index a5b731bab16bf05351fee7e64ab6ae4d830309f7..358bb6244b7b9e785c7dcc3725ee00cfbb917cec 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -137,7 +137,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -2959,7 +2958,7 @@ public abstract class EntityLiving extends Entity { - return; - } - // Paper - end don't run getEntities if we're not going to use its result -- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); -+ List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule - - if (!list.isEmpty()) { - // Paper - move up -@@ -3097,9 +3096,16 @@ public abstract class EntityLiving extends Entity { - return !this.dead && this.collides; // CraftBukkit - } - -+ // Paper start - @Override - public boolean isCollidable() { -- return this.isAlive() && !this.isSpectator() && !this.isClimbing() && this.collides; // CraftBukkit -+ return this.isCollidable(world.paperConfig.fixClimbingBypassingCrammingRule); -+ } -+ -+ @Override -+ public boolean isCollidable(boolean ignoreClimbing) { -+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.isClimbing()) && this.collides; // CraftBukkit -+ // Paper end - } - - // CraftBukkit start - collidable API -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index c8d7ea8cfa4945af4a6675172b931a4cc3ca2801..f5e32faeb6d937cf90b1f3ea251b5cfc91f2338d 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -51,11 +51,17 @@ public final class IEntitySelector { - } - - public static Predicate a(Entity entity) { -+ // Paper start - ignoreClimbing param -+ return pushable(entity, false); -+ } -+ -+ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { -+ // Paper end - ScoreboardTeamBase scoreboardteambase = entity.getScoreboardTeam(); - ScoreboardTeamBase.EnumTeamPush scoreboardteambase_enumteampush = scoreboardteambase == null ? ScoreboardTeamBase.EnumTeamPush.ALWAYS : scoreboardteambase.getCollisionRule(); - - return (Predicate) (scoreboardteambase_enumteampush == ScoreboardTeamBase.EnumTeamPush.NEVER ? Predicates.alwaysFalse() : IEntitySelector.g.and((entity1) -> { -- if (!entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API -+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable - return false; - } else if (entity.world.isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).ez())) { - return false; -diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -index 2167590677c68d261b804a16853bd943f16a76dd..61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -@@ -76,7 +76,7 @@ public class EntityBat extends EntityAmbient { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index e93375171462b95e270230f5f72f7eb5c6b0ff58..699dd0ac1f8d0d340ab1a560106336fc7cc95d5b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -368,8 +368,8 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - - @Override -- public boolean isCollidable() { -- return super.isCollidable(); // CraftBukkit - collidable API -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper -+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index d05391290dc11440aae5f38328a0530c500ac601..d678e3164ecdb7f0c600597bcb39d1054dfbc4b2 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -227,7 +227,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return !this.isVehicle(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 5eb900619951083b9a777b1645cb5495b99968ec..c0e0750adef0ae6aff7635c84f6585f06c5fc38d 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -362,7 +362,7 @@ public class EntityArmorStand extends EntityLiving { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 25a6f53888293994a50128bcbcbb88ff141c5395..add2aef0192a3b3767c1e477145978b9702c0fb4 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -150,7 +150,7 @@ public class EntityBoat extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 7d91e6b75a8a827853b0ca8e53b8ec19e2cf1092..2e3ceab3e34f7756764b3471b13d48d1263ecba9 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -145,7 +145,7 @@ public abstract class EntityMinecartAbstract extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - diff --git a/Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch b/Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch deleted file mode 100644 index 25843d00d1a6..000000000000 --- a/Spigot-Server-Patches/0606-Added-missing-default-perms-for-commands.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 16 Nov 2020 12:01:52 -0800 -Subject: [PATCH] Added missing default perms for commands - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index d5f4ece060b61de9ca5292d1f2411c709de5ece2..f0a57d225b81a505ff12425155ba838d8fad990c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -31,6 +31,59 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); -+ // Paper start -+ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) -+ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); -+ // Paper end - - DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); - diff --git a/Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch b/Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch deleted file mode 100644 index 3404ded8f3e6..000000000000 --- a/Spigot-Server-Patches/0607-Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Thu, 27 Aug 2020 15:02:48 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index d4903842aebeff3e32dbf7d3f4b670af4ebad174..7279893d599351785652279c8827fe0efbd72f12 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -262,7 +262,7 @@ public class Block extends BlockBase implements IMaterial { - - } - -- public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { -+ public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER - if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - float f = 0.5F; - double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -index ff521e64384281fc88b78bb908d19049743cf63b..828d231a963f1962d88fe170ac86590d86e1df40 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -@@ -1,5 +1,7 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - import java.util.Iterator; - import java.util.List; - import java.util.Random; -@@ -10,6 +12,7 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; -@@ -116,8 +119,19 @@ public class BlockBeehive extends BlockTileEntity { - - if (i >= 5) { - if (itemstack.getItem() == Items.SHEARS) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - world.playSound(entityhuman, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.BLOCK_BEEHIVE_SHEAR, SoundCategory.NEUTRAL, 1.0F, 1.0F); -- a(world, blockposition); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ dropItem(world, blockposition, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ } -+ // Paper end - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -index 130b768ac7155c2960694dfa12163e46315f7797..11a9c3e76baaa50317a3cd7d81541a3666028c16 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -@@ -15,6 +16,8 @@ import net.minecraft.world.level.block.state.BlockBase; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPositionBlock; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - public class BlockPumpkin extends BlockStemmed { - - protected BlockPumpkin(BlockBase.Info blockbase_info) { -@@ -27,15 +30,26 @@ public class BlockPumpkin extends BlockStemmed { - - if (itemstack.getItem() == Items.SHEARS) { - if (!world.isClientSide) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - EnumDirection enumdirection1 = enumdirection.n() == EnumDirection.EnumAxis.Y ? entityhuman.getDirection().opposite() : enumdirection; - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PUMPKIN_CARVE, SoundCategory.BLOCKS, 1.0F, 1.0F); - world.setTypeAndData(blockposition, (IBlockData) Blocks.CARVED_PUMPKIN.getBlockData().set(BlockPumpkinCarved.a, enumdirection1), 11); -- EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ // Paper end - - entityitem.setMot(0.05D * (double) enumdirection1.getAdjacentX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getAdjacentZ() + world.random.nextDouble() * 0.02D); - world.addEntity(entityitem); -+ } // Paper - Add PlayerShearBlockEvent - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); diff --git a/Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch b/Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch deleted file mode 100644 index be0092f76106..000000000000 --- a/Spigot-Server-Patches/0608-Add-warning-for-servers-not-running-on-Java-16.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Wed, 2 Dec 2020 21:58:45 -0800 -Subject: [PATCH] Add warning for servers not running on Java 16 - - -diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -@@ -0,0 +1,48 @@ -+package io.papermc.paper.util; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class PaperJvmChecker { -+ -+ private static int getJvmVersion() { -+ String javaVersion = System.getProperty("java.version"); -+ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); -+ if (!matcher.find()) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); -+ return -1; -+ } -+ -+ final String version = matcher.group(1); -+ try { -+ return Integer.parseInt(version); -+ } catch (final NumberFormatException e) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); -+ return -1; -+ } -+ } -+ -+ public static void checkJvm() { -+ if (getJvmVersion() < 16) { -+ final Logger logger = LogManager.getLogger(); -+ logger.warn("************************************************************"); -+ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); -+ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); -+ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); -+ logger.warn("*"); -+ logger.warn("* Please update the version of Java you use to run Paper"); -+ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); -+ logger.warn("* released support for versions of Java before 16 will"); -+ logger.warn("* be dropped."); -+ logger.warn("*"); -+ logger.warn("* Current Java version: {}", System.getProperty("java.version")); -+ logger.warn("*"); -+ logger.warn("* Check this forum post for more information: "); -+ logger.warn("* https://papermc.io/java16"); -+ logger.warn("************************************************************"); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2834af3e0ff2ae8466fde191a64bf719242f67f3..13aac7efac8bfc8ea685621c942c310fdf2496d9 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -182,6 +182,7 @@ import org.bukkit.event.server.ServerLoadEvent; - - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot -+import io.papermc.paper.util.PaperJvmChecker; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -1076,6 +1077,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Wed, 2 Dec 2020 20:17:54 -0800 -Subject: [PATCH] Set spigots verbose world setting to false by def - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 6b015c1f26facb4e82d75b252164dec05731ca6c..094a934c168d232b0550c3efe722f2ebfbdf8e24 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -20,7 +20,7 @@ public class SpigotWorldConfig - - public void init() - { -- this.verbose = getBoolean( "verbose", true ); -+ this.verbose = getBoolean( "verbose", false ); // Paper - - log( "-------- World Settings For [" + worldName + "] --------" ); - SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch b/Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch deleted file mode 100644 index bcd571f1ce58..000000000000 --- a/Spigot-Server-Patches/0610-Fix-curing-zombie-villager-discount-exploit.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:14:20 -0600 -Subject: [PATCH] Fix curing zombie villager discount exploit - -This fixes the exploit used to gain absurd trading discounts with infecting -and curing a villager on repeat by simply resetting the relevant part of -the reputation when it is cured. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6262246c4018c660705fbad028f297fc44e7197f..9ebe8771c2d5e843756868824740ef599ca8455f 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -715,4 +715,9 @@ public class PaperWorldConfig { - private void fixClimbingBypassingCrammingRule() { - fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); - } -+ -+ public boolean fixCuringZombieVillagerDiscountExploit = true; -+ private void fixCuringExploit() { -+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 7d34d1157786227ac210edc1595a024ccb61a3e9..ce8a4cc9f642a740947c4e63d6eb78ad93a0fd44 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -223,6 +223,7 @@ public class Reputation { - - } - -+ public final void removeReputationForType(ReputationType reputationType) { this.b(reputationType); } // Paper - OBFHELPER - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index e24c598c9d662144b91075ac80a193db2e0cb111..3f081177814dc874047e35e294ed18609f082d76 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -1014,6 +1014,15 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void a(ReputationEvent reputationevent, Entity entity) { - if (reputationevent == ReputationEvent.a) { -+ // Paper start - fix MC-181190 -+ if (world.paperConfig.fixCuringZombieVillagerDiscountExploit) { -+ final Reputation.a playerReputation = this.getReputation().getReputations().get(entity.getUniqueID()); -+ if (playerReputation != null) { -+ playerReputation.removeReputationForType(ReputationType.MAJOR_POSITIVE); -+ playerReputation.removeReputationForType(ReputationType.MINOR_POSITIVE); -+ } -+ } -+ // Paper end - this.by.a(entity.getUniqueID(), ReputationType.MAJOR_POSITIVE, 20); - this.by.a(entity.getUniqueID(), ReputationType.MINOR_POSITIVE, 25); - } else if (reputationevent == ReputationEvent.e) { diff --git a/Spigot-Server-Patches/0611-Limit-recipe-packets.patch b/Spigot-Server-Patches/0611-Limit-recipe-packets.patch deleted file mode 100644 index 9964fcfeeb1d..000000000000 --- a/Spigot-Server-Patches/0611-Limit-recipe-packets.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 12 Dec 2020 23:45:28 +0000 -Subject: [PATCH] Limit recipe packets - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 7d50aded88f5b7dfebaea1aebc86231f7b5c4e25..652d87fc5d566dba8018c81676329f0e0bca471b 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -334,6 +334,13 @@ public class PaperConfig { - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } - -+ public static int autoRecipeIncrement = 1; -+ public static int autoRecipeLimit = 20; -+ private static void autoRecipieLimiters() { -+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); -+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); -+ } -+ - public static boolean velocitySupport; - public static boolean velocityOnlineMode; - public static byte[] velocitySecretKey; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index d00c17210b3c0aff40b37ff11f8e9dc6ae1ba948..79c0ef65f3a1d28de73afb3f1891cfc1a0a3dd90 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.PaperConfig; - import com.google.common.collect.Lists; - import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; -@@ -176,6 +177,7 @@ import net.minecraft.world.inventory.InventoryClickType; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; -+import org.bukkit.Bukkit; // Paper - import org.bukkit.Location; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.event.CraftEventFactory; -@@ -234,6 +236,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); - private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits -+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -382,6 +385,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -2787,6 +2791,14 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInAutoRecipe packetplayinautorecipe) { -+ // Paper start -+ if (!Bukkit.isPrimaryThread()) { -+ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ } -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { diff --git a/Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch b/Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch deleted file mode 100644 index 8a131ca40ab3..000000000000 --- a/Spigot-Server-Patches/0612-Fix-CraftSound-backwards-compatibility.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 17 Dec 2020 15:25:49 -0600 -Subject: [PATCH] Fix CraftSound backwards compatibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -index e839d50c7b1cc3c9a6e463c497489ad580aceabd..84fb7d96bea3b47f2f6c6dc8d0086fee13d07ada 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -@@ -27,4 +27,10 @@ public class CraftSound { - public static Sound getBukkit(SoundEffect soundEffect) { - return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(IRegistry.SOUND_EVENT.getKey(soundEffect))); - } -+ -+ // Paper start -+ public static String getSound(Sound sound) { -+ return sound.getKey().getKey(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch b/Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch deleted file mode 100644 index abc309a82050..000000000000 --- a/Spigot-Server-Patches/0613-MC-4-Fix-item-position-desync.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:24:52 -0600 -Subject: [PATCH] MC-4: Fix item position desync - -This fixes item position desync (MC-4) by running the item coordinates -through the encode/decode methods of the packet that causes the precision -loss, which forces the server to lose the same precision as the client -keeping them in sync. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 652d87fc5d566dba8018c81676329f0e0bca471b..c56e7fb18f9a56c8025eb70a524f028b5942da37 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -474,4 +474,9 @@ public class PaperConfig { - private static void trackPluginScoreboards() { - trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); - } -+ -+ public static boolean fixEntityPositionDesync = true; -+ private static void fixEntityPositionDesync() { -+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -index e80429368afced0299d9f41b97251cd6c64b1759..0eed10a6c4e0c7245f219d19ed1e2e5c94364db9 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -@@ -19,11 +19,11 @@ public class PacketPlayOutEntity implements Packet { - protected boolean i; - - public static long a(double d0) { -- return MathHelper.d(d0 * 4096.0D); -+ return MathHelper.d(d0 * 4096.0D); // Paper - check EntityItem#setPositionRaw on update - } - - public static Vec3D a(long i, long j, long k) { -- return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); -+ return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); // Paper - check EntityItem#setPositionRaw on update - } - - public PacketPlayOutEntity() {} -diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java -index caa628417bb9c1c65b037e4f3f762b08272c6d09..cc566784c7dd21cc2c44e0f351347f657e57ddcf 100644 ---- a/src/main/java/net/minecraft/util/MathHelper.java -+++ b/src/main/java/net/minecraft/util/MathHelper.java -@@ -9,7 +9,7 @@ import net.minecraft.core.BaseBlockPosition; - public class MathHelper { - - public static final float a = c(2.0F); -- private static final float[] b = (float[]) SystemUtils.a((Object) (new float[65536]), (afloat) -> { -+ private static final float[] b = (float[]) SystemUtils.a((new float[65536]), (afloat) -> { // Paper - decompile error - for (int i = 0; i < afloat.length; ++i) { - afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); - } -@@ -49,6 +49,7 @@ public class MathHelper { - return d0 < (double) i ? i - 1 : i; - } - -+ public static long floorLong(double d0) { return d(d0); } // Paper - OBFHELPER - public static long d(double d0) { - long i = (long) d0; - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 11e029f6f97f1dd9c32e311d1a3800f2fa54b91f..575833807ff647f30d7c2b7abcd01701c7dec85b 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -550,4 +550,16 @@ public class EntityItem extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - fix MC-4 -+ public void setPositionRaw(double x, double y, double z) { -+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ // encode/decode from PacketPlayOutEntity -+ x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); -+ y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); -+ z = MathHelper.floorLong(z * 4096.0D) * (1 / 4096.0D); -+ } -+ super.setPositionRaw(x, y, z); -+ } -+ // Paper end - fix MC-4 - } diff --git a/Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch b/Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index a1a05e716f68..000000000000 --- a/Spigot-Server-Patches/0614-Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:25:16 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 78fcb90c86700ee6feef0d40753fc8d8a943777f..c0446ed3c7cc24fae2880dfba71228f5edee66d6 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -139,6 +139,8 @@ import net.minecraft.world.scores.ScoreboardScore; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; - import net.minecraft.world.scores.criteria.IScoreboardCriteria; -+import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper -+import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -2098,11 +2100,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void a(ChunkCoordIntPair chunkcoordintpair, Packet packet, Packet packet1) { - this.playerConnection.sendPacket(packet1); - this.playerConnection.sendPacket(packet); -+ // Paper start -+ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (this.isAlive()) { - this.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(chunkcoordintpair.x, chunkcoordintpair.z)); -+ // Paper start -+ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch b/Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch deleted file mode 100644 index 5a4efe035cc0..000000000000 --- a/Spigot-Server-Patches/0615-Optimize-Dynamic-get-Missing-Keys.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 21 Dec 2020 11:01:42 -0500 -Subject: [PATCH] Optimize Dynamic#get Missing Keys - -get was calling toString() on every NBT object that was ever asked for an optional -key from the object to build a string for the error text. - -When done on large NBT objects, this was using a ton of computation time building the -JSON representation of the NBT object. - -Now we will just skip the value when 99.9999% of the time the text is never even printed. - -diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java -index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644 ---- a/src/main/java/com/mojang/serialization/Dynamic.java -+++ b/src/main/java/com/mojang/serialization/Dynamic.java -@@ -17,6 +17,7 @@ import java.util.stream.Stream; - - @SuppressWarnings("unused") - public class Dynamic extends DynamicLike { -+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper - private final T value; - - public Dynamic(final DynamicOps ops) { -@@ -113,7 +114,7 @@ public class Dynamic extends DynamicLike { - return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { - final T value = m.get(key); - if (value == null) { -- return DataResult.error("key missing: " + key + " in " + this.value); -+ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper - } - return DataResult.success(new Dynamic<>(ops, value)); - })); diff --git a/Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch b/Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index 551ec0e06f4c..000000000000 --- a/Spigot-Server-Patches/0616-Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:05 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 358bb6244b7b9e785c7dcc3725ee00cfbb917cec..deffd82dfca1d2eea6e5b8db9228015bf35ad0a3 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -163,7 +163,7 @@ public abstract class EntityLiving extends Entity { - public int am; - public int hurtTicks; - public int hurtDuration; -- public float ap; -+ public float ap; public final float getHurtDirection() { return ap; } public final void setHurtDirection(float hurtDirection) { this.ap = hurtDirection; } // Paper - OBFHELPER - public int deathTicks; - public float ar; - public float as; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 5d2ed8a0cf8351df1c8b2946f8a614fe13c34673..e574e2453c7bc848168ff24372d6772bd423b672 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -825,5 +825,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { - getHandle().receive(((CraftItem) item).getHandle(), quantity); - } -+ -+ @Override -+ public float getHurtDirection() { -+ return getHandle().getHurtDirection(); -+ } -+ -+ @Override -+ public void setHurtDirection(float hurtDirection) { -+ getHandle().setHurtDirection(hurtDirection); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index 91c4ed13f411..000000000000 --- a/Spigot-Server-Patches/0617-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:39 -0800 -Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 703f2648dde7ad1620e83f88ac4184e5803ed9b4..62fcf390e5cf5b76e1f7b34fea856911d9494044 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -268,6 +268,10 @@ public class CraftEventFactory { - return BedEnterResult.TOO_FAR_AWAY; - case NOT_SAFE: - return BedEnterResult.NOT_SAFE; -+ // Paper start -+ case OBSTRUCTED: -+ return BedEnterResult.OBSTRUCTED; -+ // Paper end - default: - return BedEnterResult.OTHER_PROBLEM; - } diff --git a/Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch deleted file mode 100644 index 3addc9816cb9..000000000000 --- a/Spigot-Server-Patches/0618-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 27 Dec 2020 11:31:06 +0000 -Subject: [PATCH] Do not crash from invalid ingredient lists in - VillagerAcquireTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index a614f5d5817bf999aca0f0b50f343031c8168392..10067731e6289211cb11b2b368527a1c45603314 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -273,7 +273,11 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - Bukkit.getPluginManager().callEvent(event); - } - if (!event.isCancelled()) { -- merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); -+ // Paper start -+ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); -+ if (craftMerchantRecipe.getIngredients().isEmpty()) return; -+ merchantrecipelist.add(craftMerchantRecipe.toMinecraft()); -+ // Paper end - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch b/Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch deleted file mode 100644 index b24c22edd8d5..000000000000 --- a/Spigot-Server-Patches/0619-added-PlayerTradeEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:12:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 89d24d7532a256434513a45c901946e28db396bd..ff482e3774f580d8ba7028f6c5141888d3bd907a 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -93,7 +93,7 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; - public abstract class EntityInsentient extends EntityLiving { - - private static final DataWatcherObject b = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a); -- public int e; -+ public int e;public void setAmbientSoundTime(int time) { this.e = time; } // Paper - OBFHELPER - protected int f; - protected ControllerLook lookController; - protected ControllerMove moveController; -@@ -295,6 +295,7 @@ public abstract class EntityInsentient extends EntityLiving { - this.datawatcher.register(EntityInsentient.b, (byte) 0); - } - -+ public int getAmbientSoundInterval() { return D(); } // Paper - OBFHELPER - public int D() { - return 80; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 10067731e6289211cb11b2b368527a1c45603314..49821f0f26864c35be84a4a4288857a04668fbba 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -39,6 +39,9 @@ import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; - import org.bukkit.entity.AbstractVillager; - import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end -+// Paper start -+import io.papermc.paper.event.player.PlayerTradeEvent; -+// Paper end - - public abstract class EntityVillagerAbstract extends EntityAgeable implements NPC, IMerchant { - -@@ -135,16 +138,27 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - - @Override - public void a(MerchantRecipe merchantrecipe) { -- merchantrecipe.increaseUses(); -- this.e = -this.D(); -- this.b(merchantrecipe); -+ // Paper - moved down -+ // Paper start - if (this.tradingPlayer instanceof EntityPlayer) { -- CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, merchantrecipe.getSellingItem()); -+ PlayerTradeEvent event = new PlayerTradeEvent(((EntityPlayer) this.tradingPlayer).getBukkitEntity(), (AbstractVillager) this.getBukkitEntity(), merchantrecipe.asBukkit(), true, true); -+ event.callEvent(); -+ if (!event.isCancelled()) { -+ MerchantRecipe recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); -+ if (event.willIncreaseTradeUses()) recipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ if (event.isRewardingExp()) this.rewardTradeXp(recipe); -+ CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, recipe.getSellingItem()); -+ } -+ } else { -+ merchantrecipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ this.rewardTradeXp(merchantrecipe); - } -- -+ // Paper end - } - -- protected abstract void b(MerchantRecipe merchantrecipe); -+ protected abstract void b(MerchantRecipe merchantrecipe); public void rewardTradeXp(MerchantRecipe merchantrecipe) { this.b(merchantrecipe); } // Paper - OBFHELPER - - @Override - public boolean isRegularVillager() { diff --git a/Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch b/Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch deleted file mode 100644 index eebdc5aa97c0..000000000000 --- a/Spigot-Server-Patches/0620-Implement-TargetHitEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 25 Nov 2020 23:20:44 -0800 -Subject: [PATCH] Implement TargetHitEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTarget.java b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -index c336490815dc17991d3d84d8c6f0fc58571a3e3a..a9316ce8eb3d8a645f4c0e41ac668a90f584c263 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTarget.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms - import java.util.Random; - import net.minecraft.advancements.CriterionTriggers; - import net.minecraft.core.BlockPosition; -@@ -34,6 +35,10 @@ public class BlockTarget extends Block { - @Override - public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { - int i = a((GeneratorAccess) world, iblockdata, movingobjectpositionblock, (Entity) iprojectile); -+ // Paper start -+ } -+ private static void awardTargetHitCriteria(IProjectile iprojectile, MovingObjectPositionBlock movingobjectpositionblock, int i) { -+ // Paper end - Entity entity = iprojectile.getShooter(); - - if (entity instanceof EntityPlayer) { -@@ -49,6 +54,20 @@ public class BlockTarget extends Block { - int i = a(movingobjectpositionblock, movingobjectpositionblock.getPos()); - int j = entity instanceof EntityArrow ? 20 : 8; - -+ // Paper start -+ if (entity instanceof IProjectile) { -+ final IProjectile projectile = (IProjectile) entity; -+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, movingobjectpositionblock.getBlockPosition()); -+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); -+ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); -+ if (targetHitEvent.callEvent()) { -+ i = targetHitEvent.getSignalStrength(); -+ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); -+ } else { -+ return i; -+ } -+ } -+ // Paper end - if (!generatoraccess.getBlockTickList().a(movingobjectpositionblock.getBlockPosition(), iblockdata.getBlock())) { - a(generatoraccess, iblockdata, i, movingobjectpositionblock.getBlockPosition(), j); - } diff --git a/Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch b/Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch deleted file mode 100644 index ba38cd24b020..000000000000 --- a/Spigot-Server-Patches/0621-Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 19:43:01 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index fab9e1e5d63c22faceae093dc88769d203d359c6..ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -621,6 +621,25 @@ public class CraftBlock implements Block { - return getNMS().getMaterial().isLiquid(); - } - -+ // Paper start -+ @Override -+ public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); -+ } -+ @Override -+ public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); -+ } -+ @Override -+ public boolean isReplaceable() { -+ return getNMS().getMaterial().isReplaceable(); -+ } -+ @Override -+ public boolean isSolid() { -+ return getNMS().getMaterial().isSolid(); -+ } -+ // Paper end -+ - @Override - public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPushReaction().ordinal()); diff --git a/Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch b/Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch deleted file mode 100644 index 0e9ad1d647bb..000000000000 --- a/Spigot-Server-Patches/0622-Fix-harming-potion-dupe.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> -Date: Thu, 23 Jul 2020 14:25:07 -0700 -Subject: [PATCH] Fix harming potion dupe - -EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. -Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. -This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. - -diff --git a/src/main/java/net/minecraft/world/item/ItemPotion.java b/src/main/java/net/minecraft/world/item/ItemPotion.java -index b197fe561ab735e80d8bf29ac16eacfaf3fc2d21..ca2f8d522d7f2305f161cb4aa611226355ea5789 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotion.java -@@ -15,6 +15,7 @@ import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.alchemy.PotionRegistry; - import net.minecraft.world.item.alchemy.PotionUtil; - import net.minecraft.world.item.alchemy.Potions; -+import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - - public class ItemPotion extends Item { -@@ -36,6 +37,7 @@ public class ItemPotion extends Item { - CriterionTriggers.z.a((EntityPlayer) entityhuman, itemstack); - } - -+ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe - if (!world.isClientSide) { - List list = PotionUtil.getEffects(itemstack); - Iterator iterator = list.iterator(); -@@ -44,7 +46,7 @@ public class ItemPotion extends Item { - MobEffect mobeffect = (MobEffect) iterator.next(); - - if (mobeffect.getMobEffect().isInstant()) { -- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ instantLater.add(mobeffect); // Paper - Fix harming potion dupe - } else { - entityliving.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit - } -@@ -58,7 +60,20 @@ public class ItemPotion extends Item { - } - } - -+ // Paper start - Fix harming potion dupe -+ for (MobEffect mobeffect : instantLater) { -+ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ } -+ // Paper end -+ - if (entityhuman == null || !entityhuman.abilities.canInstantlyBuild) { -+ // Paper start - Fix harming potion dupe -+ if (entityliving.getHealth() <= 0 && !entityliving.world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { -+ entityliving.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); -+ return ItemStack.NULL_ITEM; -+ } -+ // Paper end -+ - if (itemstack.isEmpty()) { - return new ItemStack(Items.GLASS_BOTTLE); - } diff --git a/Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch deleted file mode 100644 index 02569905c0eb..000000000000 --- a/Spigot-Server-Patches/0623-Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:19 +1000 -Subject: [PATCH] Implement API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index add2aef0192a3b3767c1e477145978b9702c0fb4..2609b83573e0e8532e6c4c36d4f475bf0da6a354 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -260,6 +260,7 @@ public class EntityBoat extends Entity { - - } - -+ public final Item getBoatItem() { return this.g(); } // Paper - OBFHELPER - public Item g() { - switch (this.getType()) { - case OAK: -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index c7a459c0c860724ef1890b8fb9a59a5508b3f6d6..16799dc565c5ca42d1fdb3122594d9dae21c74e0 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -1,8 +1,10 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityBoat; -+import org.bukkit.Material; // Paper - import org.bukkit.TreeSpecies; - import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - import org.bukkit.entity.Boat; - import org.bukkit.entity.EntityType; - -@@ -66,6 +68,13 @@ public class CraftBoat extends CraftVehicle implements Boat { - getHandle().landBoats = workOnLand; - } - -+ // Paper start -+ @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); -+ } -+ // Paper end -+ - @Override - public EntityBoat getHandle() { - return (EntityBoat) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 69415f5a838345826fa5cf1d855e057794520f2c..e5ebb80a44da775df6f3d5a9db5cf58295e2e960 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -1,8 +1,10 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -+import net.minecraft.world.item.Items; // Paper - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.Material; // Paper - import org.bukkit.block.data.BlockData; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.block.data.CraftBlockData; -@@ -68,6 +70,38 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { - getHandle().setDerailedVelocityMod(derailed); - } - -+ // Paper start -+ @Override -+ public Material getMinecartMaterial() { -+ net.minecraft.world.item.Item minecartItem; -+ switch (getHandle().getMinecartType()) { -+ case CHEST: -+ minecartItem = Items.CHEST_MINECART; -+ break; -+ case FURNACE: -+ minecartItem = Items.FURNACE_MINECART; -+ break; -+ case TNT: -+ minecartItem = Items.TNT_MINECART; -+ break; -+ case HOPPER: -+ minecartItem = Items.HOPPER_MINECART; -+ break; -+ case COMMAND_BLOCK: -+ minecartItem = Items.COMMAND_BLOCK_MINECART; -+ break; -+ case RIDEABLE: -+ case SPAWNER: -+ minecartItem = Items.MINECART; -+ break; -+ default: -+ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); -+ } -+ -+ return CraftMagicNumbers.getMaterial(minecartItem); -+ } -+ // Paper end -+ - @Override - public EntityMinecartAbstract getHandle() { - return (EntityMinecartAbstract) entity; diff --git a/Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch b/Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch deleted file mode 100644 index 522f5db77313..000000000000 --- a/Spigot-Server-Patches/0624-Optimized-tick-ready-check.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 17:19:51 +0100 -Subject: [PATCH] Optimized tick ready check - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index f40be366ebc5f98b417b677565fa89d3f817f3fb..78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -854,13 +854,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (!tileentity.isRemoved() && tileentity.hasWorld()) { - BlockPosition blockposition = tileentity.getPosition(); - -- if (this.getChunkProvider().a(blockposition) && this.getWorldBorder().a(blockposition)) { -+ Chunk chunk; PlayerChunk playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity - try { - gameprofilerfiller.a(() -> { - return String.valueOf(TileEntityTypes.a(tileentity.getTileType())); - }); - tileentity.tickTimer.startTiming(); // Spigot -- if (tileentity.getTileType().isValidBlock(this.getType(blockposition).getBlock())) { -+ if (tileentity.getTileType().isValidBlock(chunk.getType(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again - ((ITickable) tileentity).tick(); - } else { - tileentity.w(); -@@ -893,9 +893,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end - //this.tileEntityList.remove(tileentity); // Paper - remove unused list -- if (this.isLoaded(tileentity.getPosition())) { -- this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); -+ // Paper - prevent double chunk lookups -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ chunk.removeTileEntity(tileentity.getPosition()); - } -+ // Paper end - } - } - -@@ -914,8 +916,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // CraftBukkit end */ - -- if (this.isLoaded(tileentity1.getPosition())) { -- Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getPosition())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above - IBlockData iblockdata = chunk.getType(tileentity1.getPosition()); - - chunk.setTileEntity(tileentity1.getPosition(), tileentity1); diff --git a/Spigot-Server-Patches/0625-Cache-burn-durations.patch b/Spigot-Server-Patches/0625-Cache-burn-durations.patch deleted file mode 100644 index 1c9afd635003..000000000000 --- a/Spigot-Server-Patches/0625-Cache-burn-durations.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 16:47:00 +0100 -Subject: [PATCH] Cache burn durations - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index e630e8d3e115d2a0177849ad8258a2304b9d3e9d..54316a8079b4331a48cac3c43f3f8c506a4af091 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.level.block.entity; - -+import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -@@ -113,7 +114,15 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.c = recipes; - } - -+ private static Map cachedBurnDurations = null; // Paper - cache burn durations -+ -+ public static Map getBurnDurations() { return f(); } // Paper - OBFHELPER - public static Map f() { -+ // Paper start - cache burn durations -+ if(cachedBurnDurations != null) { -+ return cachedBurnDurations; -+ } -+ // Paper end - Map map = Maps.newLinkedHashMap(); - - a(map, (IMaterial) Items.LAVA_BUCKET, 20000); -@@ -176,7 +185,10 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - a(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); - a(map, (IMaterial) Blocks.SMITHING_TABLE, 300); - a(map, (IMaterial) Blocks.COMPOSTER, 300); -- return map; -+ // Paper start - cache burn durations -+ cachedBurnDurations = ImmutableMap.copyOf(map); -+ return cachedBurnDurations; -+ // Paper end - } - - // CraftBukkit start - add fields and methods -@@ -430,7 +442,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } else { - Item item = itemstack.getItem(); - -- return (Integer) f().getOrDefault(item, 0); -+ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations - } - } - -@@ -443,7 +455,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - // Paper end - - public static boolean isFuel(ItemStack itemstack) { -- return f().containsKey(itemstack.getItem()); -+ return getBurnDurations().containsKey(itemstack.getItem()); // Paper - cache burn durations - } - - @Override diff --git a/Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch deleted file mode 100644 index 5a7b73fbcac9..000000000000 --- a/Spigot-Server-Patches/0626-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Fri, 9 Oct 2020 20:30:12 -0400 -Subject: [PATCH] Allow disabling mob spawner spawn egg transformation - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9ebe8771c2d5e843756868824740ef599ca8455f..a555d040fdc58f7c89ef78e3e6851916fdd8462a 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -720,4 +720,9 @@ public class PaperWorldConfig { - private void fixCuringExploit() { - fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); - } -+ -+ public boolean disableMobSpawnerSpawnEggTransformation = false; -+ private void disableMobSpawnerSpawnEggTransformation() { -+ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); -+ } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -index c170d2141504d80624e3c1a7f78f7968ea8a80ee..4d965e504a40eb52777575df839856c825a0900a 100644 ---- a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -@@ -60,7 +60,7 @@ public class ItemMonsterEgg extends Item { - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - IBlockData iblockdata = world.getType(blockposition); - -- if (iblockdata.a(Blocks.SPAWNER)) { -+ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.a(Blocks.SPAWNER)) { // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityMobSpawner) { diff --git a/Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch b/Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index 43503c58f0d4..000000000000 --- a/Spigot-Server-Patches/0627-Implement-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:45:06 -0700 -Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -index a61d1ffeebfd00a5fcd5faf95200b0640da8ea82..18fefad056d92a6fa498ab3764cd391446c26b60 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -@@ -21,6 +21,8 @@ import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - -+import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper -+ - public class BlockFlowerPot extends Block { - - private static final Map b = Maps.newHashMap(); -@@ -52,6 +54,27 @@ public class BlockFlowerPot extends Block { - boolean flag1 = this.c == Blocks.AIR; - - if (flag != flag1) { -+ // Paper start -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity(); -+ boolean placing = flag1; -+ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition); -+ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); -+ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(c); -+ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); -+ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; -+ -+ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player, bukkitblock, whichitem, placing); -+ player.getServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ // Update client -+ player.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); -+ player.updateInventory(); -+ -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end -+ - if (flag1) { - world.setTypeAndData(blockposition, block.getBlockData(), 3); - entityhuman.a(StatisticList.POT_FLOWER); diff --git a/Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch b/Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch deleted file mode 100644 index e0ef42968cf1..000000000000 --- a/Spigot-Server-Patches/0628-Fix-interact-event-not-being-called-in-adventure.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheMolkaPL -Date: Sun, 21 Jun 2020 17:21:46 +0200 -Subject: [PATCH] Fix interact event not being called in adventure - -Call PlayerInteractEvent when left-clicking on a block in adventure mode - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 79c0ef65f3a1d28de73afb3f1891cfc1a0a3dd90..358d1095b219fce6b308ec0362f22db7cfc85251 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1702,7 +1702,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - IChatMutableComponent ichatmutablecomponent = (new ChatMessage("build.tooHigh", new Object[]{this.minecraftServer.getMaxBuildHeight()})).a(EnumChatFormat.RED); - - this.player.playerConnection.sendPacket(new PacketPlayOutChat(ichatmutablecomponent, ChatMessageType.GAME_INFO, SystemUtils.b)); -- } else if (enuminteractionresult.b()) { -+ } else if (enuminteractionresult.b() && !this.player.playerInteractManager.interactResult) { - this.player.swingHand(enumhand, true); - } - } -@@ -2203,7 +2203,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - MovingObjectPosition movingobjectposition = this.player.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, player)); - -- if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK || this.player.playerInteractManager.getGameMode() == EnumGamemode.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - } - diff --git a/Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch b/Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch deleted file mode 100644 index da61412550ac..000000000000 --- a/Spigot-Server-Patches/0629-Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:46 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 87acbdee03edf8bc35f4b3bcb9b82855ed4a3c33..5b0c79d752d616e5824393968136f3844ce52c22 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -140,10 +140,12 @@ public class EntityZombie extends EntityMonster { - return (Boolean) this.getDataWatcher().get(EntityZombie.DROWN_CONVERTING); - } - -+ public boolean canBreakDoors() { return this.eU(); } // Paper - OBFHELPER - public boolean eU() { - return this.bs; - } - -+ public void setCanBreakDoors(boolean canBreakDoors) { this.u(canBreakDoors); } // Paper - OBFHELPER - public void u(boolean flag) { - if (this.eK() && PathfinderGoalUtil.a(this)) { - if (this.bs != flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 42d98d798bb8fe2d3c7cc2bfcf2ec38d97d99bd2..e1589ef97222f5e29a3628db354d4406a443a613 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -129,6 +129,16 @@ public class CraftZombie extends CraftMonster implements Zombie { - public void setShouldBurnInDay(boolean shouldBurnInDay) { - getHandle().setShouldBurnInDay(shouldBurnInDay); - } -+ -+ @Override -+ public boolean canBreakDoors() { -+ return getHandle().canBreakDoors(); -+ } -+ -+ @Override -+ public void setCanBreakDoors(boolean canBreakDoors) { -+ getHandle().setCanBreakDoors(canBreakDoors); -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch b/Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch deleted file mode 100644 index 875960eb0b9c..000000000000 --- a/Spigot-Server-Patches/0630-Fix-nerfed-slime-when-splitting.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 24 Aug 2020 08:39:06 -0700 -Subject: [PATCH] Fix nerfed slime when splitting - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 40e39e382092b1a8f831da0cea1557a781c98600..0af0b232ff1b6f1d58cf3fb543d32bd108be0af7 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -246,6 +246,7 @@ public class EntitySlime extends EntityInsentient implements IMonster { - entityslime.setPersistent(); - } - -+ entityslime.aware = this.aware; // Paper - entityslime.setCustomName(ichatbasecomponent); - entityslime.setNoAI(flag); - entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch b/Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index 5e9ae2150b33..000000000000 --- a/Spigot-Server-Patches/0631-Add-EntityLoadCrossbowEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JRoy -Date: Wed, 7 Oct 2020 12:04:01 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index ec6c0836f02e7ac5b72fd224a3022a844dce55cb..4e1e819c8535e8a6b9aa5f76afe568ea171b939f 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -3,6 +3,8 @@ package net.minecraft.world.item; - import com.google.common.collect.Lists; - import com.mojang.math.Quaternion; - import com.mojang.math.Vector3fa; -+import org.bukkit.inventory.EquipmentSlot; // Paper -+import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts - import java.util.List; - import java.util.Random; - import java.util.function.Predicate; -@@ -73,7 +75,11 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - int j = this.e_(itemstack) - i; - float f = a(j, itemstack); - -- if (f >= 1.0F && !d(itemstack) && a(entityliving, itemstack)) { -+ // Paper start - EntityLoadCrossbowEvent -+ if (f >= 1.0F && !d(itemstack) /*&& a(entityliving, itemstack)*/) { -+ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(entityliving.getBukkitLivingEntity(), itemstack.asBukkitMirror(), entityliving.getRaisedHand() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); -+ if (!event.callEvent() || !attemptProjectileLoad(entityliving, itemstack, event.shouldConsumeItem())) return; -+ // Paper end - a(itemstack, true); - SoundCategory soundcategory = entityliving instanceof EntityHuman ? SoundCategory.PLAYERS : SoundCategory.HOSTILE; - -@@ -82,10 +88,13 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - } - -- private static boolean a(EntityLiving entityliving, ItemStack itemstack) { -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow) { return a(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack) { return a(entityliving, itemstack, true); };// Paper - add consume -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume - int i = EnchantmentManager.getEnchantmentLevel(Enchantments.MULTISHOT, itemstack); - int j = i == 0 ? 1 : 3; -- boolean flag = entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; -+ boolean flag = !consume || entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; // Paper - add consme - ItemStack itemstack1 = entityliving.f(itemstack); - ItemStack itemstack2 = itemstack1.cloneItemStack(); - diff --git a/Spigot-Server-Patches/0632-Guardian-beam-workaround.patch b/Spigot-Server-Patches/0632-Guardian-beam-workaround.patch deleted file mode 100644 index 4439204159f5..000000000000 --- a/Spigot-Server-Patches/0632-Guardian-beam-workaround.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Guardian beam workaround - -This patch is a workaround for MC-165595 - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -index a69e60a8934493f6786ce3d425f6dccb6e4befdd..3086ee023685781d94e2fb99fc8dff5264f01165 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -@@ -6,7 +6,7 @@ import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutUpdateTime implements Packet { - -- private long a; -+ private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER - private long b; - - public PacketPlayOutUpdateTime() {} -@@ -21,6 +21,9 @@ public class PacketPlayOutUpdateTime implements Packet { - } - } - -+ // Paper start -+ this.setWorldAge(this.getWorldAge() % 192000); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch b/Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch deleted file mode 100644 index 6eec09567913..000000000000 --- a/Spigot-Server-Patches/0633-Added-WorldGameRuleChangeEvent.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamerule.java b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -index 5b5c5d1299c267f620f5c59873b261a7b7e382a9..feebe4812ff7aec17a50cb5f2789fe88e10a5032 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamerule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -@@ -31,7 +31,7 @@ public class CommandGamerule { - CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) commandcontext.getSource(); - T t0 = commandlistenerwrapper.getWorld().getGameRules().get(gamerules_gamerulekey); // CraftBukkit - -- t0.b(commandcontext, "value"); -+ t0.setValue(commandcontext, "value", gamerules_gamerulekey); // Paper - commandlistenerwrapper.sendMessage(new ChatMessage("commands.gamerule.set", new Object[]{gamerules_gamerulekey.a(), t0.toString()}), true); - return t0.getIntValue(); - } -diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java -index 276c28170b2a177dab6b2a0d5425044cd9f8df22..3783f3a83e3e70d77cf0fa1021f62a89c5950af5 100644 ---- a/src/main/java/net/minecraft/world/level/GameRules.java -+++ b/src/main/java/net/minecraft/world/level/GameRules.java -@@ -25,6 +25,7 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper - - public class GameRules { - -@@ -177,8 +178,11 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = BoolArgumentType.getBool(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Boolean.parseBoolean(event.getValue()); -+ // Paper end - } - - public boolean a() { -@@ -237,8 +241,11 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = IntegerArgumentType.getInteger(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Integer.parseInt(event.getValue()); -+ // Paper end - } - - public int a() { -@@ -291,10 +298,12 @@ public class GameRules { - this.a = gamerules_gameruledefinition; - } - -- protected abstract void a(CommandContext commandcontext, String s); -+ protected void updateValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ protected abstract void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey); // Paper - -- public void b(CommandContext commandcontext, String s) { -- this.a(commandcontext, s); -+ public void setValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ public void b(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper -+ this.updateValue(commandcontext, s, gameRuleKey); // Paper - this.onChange(((CommandListenerWrapper) commandcontext.getSource()).getServer()); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 776733a4a913d232126b48f2d0eadbe27aa84e59..05a7f5f61330bd52705640345524cdedbf105285 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2363,8 +2363,13 @@ public class CraftWorld implements World { - - if (!isGameRule(rule)) return false; - -+ // Paper start -+ GameRule gameRule = GameRule.getByName(rule); -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule)); -- handle.setValue(value); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } -@@ -2399,8 +2404,12 @@ public class CraftWorld implements World { - - if (!isGameRule(rule.getName())) return false; - -+ // Paper start -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule.getName())); -- handle.setValue(newValue.toString()); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } diff --git a/Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch b/Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index 145b3264300c..000000000000 --- a/Spigot-Server-Patches/0634-Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:01 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 13aac7efac8bfc8ea685621c942c310fdf2496d9..1c17db3e9e30d16bc5778bb3220e3e9e8c336258 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2,9 +2,6 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; --import co.aikar.timings.Timings; --import com.destroystokyo.paper.event.server.PaperServerListPingEvent; --import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -183,6 +180,7 @@ import org.bukkit.event.server.ServerLoadEvent; - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - import io.papermc.paper.util.PaperJvmChecker; // Paper -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -1935,7 +1933,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant a(Collection collection) { -+ return this.reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { -+ // Paper end - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { - Stream stream = collection.stream(); // CraftBukkit - decompile error - ResourcePackRepository resourcepackrepository = this.resourcePackRepository; -@@ -1951,6 +1955,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant collection, CommandListenerWrapper commandlistenerwrapper) { -- commandlistenerwrapper.getServer().a(collection).exceptionally((throwable) -> { -+ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper - CommandReload.LOGGER.warn("Failed to execute reload", throwable); - commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); - return null; -@@ -48,7 +49,7 @@ public class CommandReload { - SaveData savedata = minecraftserver.getSaveData(); - Collection collection = resourcepackrepository.d(); - Collection collection1 = a(resourcepackrepository, savedata, collection); -- minecraftserver.a(collection1); -+ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch b/Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch deleted file mode 100644 index 2685a66e7302..000000000000 --- a/Spigot-Server-Patches/0635-Added-world-settings-for-mobs-picking-up-loot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 28 Nov 2020 18:43:52 -0800 -Subject: [PATCH] Added world settings for mobs picking up loot - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a555d040fdc58f7c89ef78e3e6851916fdd8462a..c42e5d9f9c9f67988383c4c25123d8a629ede9e3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -361,6 +361,14 @@ public class PaperWorldConfig { - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } - -+ public boolean zombiesAlwaysCanPickUpLoot; -+ public boolean skeletonsAlwaysCanPickUpLoot; -+ private void setMobsAlwaysCanPickUpLoot() { -+ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); -+ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); -+ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); -+ } -+ - public int expMergeMaxValue; - private void expMergeMaxValue() { - expMergeMaxValue = getInt("experience-merge-max-value", -1); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 4dca5ea9127c15b2739483b2ad74a5296a6b96ad..06d50b22ede102556fdb3e2a6f1424f7ff13f120 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -149,7 +149,7 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - this.a(difficultydamagescaler); - this.b(difficultydamagescaler); - this.eL(); -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); -+ this.setCanPickupLoot(this.world.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); // Paper - if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { - LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 5b0c79d752d616e5824393968136f3844ce52c22..fb98609a38d665659076b8949b59eaf084408a17 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -497,7 +497,7 @@ public class EntityZombie extends EntityMonster { - Object object = super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); - float f = difficultydamagescaler.d(); - -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * f); -+ this.setCanPickupLoot(this.world.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper - if (object == null) { - object = new EntityZombie.GroupDataZombie(a(worldaccess.getRandom()), true); - } diff --git a/Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch b/Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch deleted file mode 100644 index 4921a370de87..000000000000 --- a/Spigot-Server-Patches/0636-Implemented-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:38 +0200 -Subject: [PATCH] Implemented BlockFailedDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 0ab6186ba3cfd7f7115c71b3982f46c5d2c921c0..966051ab3e720e5b3f0fb9ab852c8908c5f23f3b 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -81,6 +81,7 @@ public class BlockDispenser extends BlockTileEntity { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDropper.java b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -index ccab4714bf5a6be8afd92430874fd6f881d4f92f..223cc0ba06cf4b007049880daad881e55ac4e448 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDropper.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -@@ -47,6 +47,7 @@ public class BlockDropper extends BlockDispenser { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 62fcf390e5cf5b76e1f7b34fea856911d9494044..d4b288e127cbd03ded93977fac0c40359525b92d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -4,6 +4,7 @@ import com.google.common.base.Function; - import com.google.common.base.Functions; - import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Either; -+import io.papermc.paper.event.block.BlockFailedDispenseEvent; - import java.net.InetAddress; - import java.util.ArrayList; - import java.util.Collections; -@@ -121,7 +122,6 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; --import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -1787,4 +1787,12 @@ public class CraftEventFactory { - - return event; - } -+ -+ // Paper start -+ public static boolean handleBlockFailedDispenseEvent(WorldServer worldserver, BlockPosition blockposition) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); -+ return event.callEvent(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch b/Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index 8e2dd9cf60d9..000000000000 --- a/Spigot-Server-Patches/0637-Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:51 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index e7c29d194d5c3e3b1b79228758f7a3d8aa060fbd..9c6330da4e026a7753698b5d103c009730154c3e 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -562,6 +562,7 @@ public abstract class Container { - this.getSlot(i).set(itemstack); - } - -+ public void setData(int index, int value) { this.a(index, value); } // Paper - OBFHELPER - public void a(int i, int j) { - ((ContainerProperty) this.d.get(i)).set(j); - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -index 910c3eab0675b84694317427d7317caba89d74c3..10c829efd9ecb7dfa29e92586f99e40a8984f840 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -@@ -13,6 +13,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerTakeLecternBookEvent; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper - - public class ContainerLectern extends Container { - -@@ -60,6 +61,7 @@ public class ContainerLectern extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - int j; -+ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - - if (i >= 100) { - j = i - 100; -@@ -69,11 +71,25 @@ public class ContainerLectern extends Container { - switch (i) { - case 1: - j = this.containerProperties.getProperty(0); -- this.a(0, j - 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 2: - j = this.containerProperties.getProperty(0); -- this.a(0, j + 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 3: - if (!entityhuman.eK()) { diff --git a/Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch b/Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch deleted file mode 100644 index 24dd766968a5..000000000000 --- a/Spigot-Server-Patches/0638-Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:56 +0200 -Subject: [PATCH] Fire event on GS4 query - - -diff --git a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -index 57ff3db0a0199ef03045b880e598407886b0306b..1b6761f75d97c49b1bf1ce3db631b7250c9489bd 100644 ---- a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -+++ b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -@@ -18,15 +18,27 @@ public class RemoteStatusReply { - this.b.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER - public void a(String s) throws IOException { - this.b.writeBytes(s); - this.b.write(0); - } -+ // Paper start - unchecked exception variant to use in Stream API -+ public void writeStringUnchecked(String string) { -+ try { -+ writeString(string); -+ } catch (IOException e) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); -+ } -+ } -+ // Paper end - -+ public void writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(int i) throws IOException { - this.b.write(i); - } - -+ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(short short0) throws IOException { - this.b.writeShort(Short.reverseBytes(short0)); - } -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -index 55b379af2e0c8c3513a76a346d381cd3dbcabe40..59769f7ea808b952cd02192c7121c248756998e9 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -@@ -16,6 +16,7 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.server.IMinecraftServer; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.RemoteStatusReply; - import net.minecraft.server.rcon.StatusChallengeUtils; - import org.apache.logging.log4j.LogManager; -@@ -26,18 +27,18 @@ public class RemoteStatusListener extends RemoteConnectionThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long e; - private final int f; -- private final int g; -- private final int h; -- private final String i; -- private final String j; -+ private final int g; private final int getServerPort() { return this.g; } // Paper - OBFHELPER -+ private final int h; private final int getMaxPlayers() { return this.h; } // Paper - OBFHELPER -+ private final String i; private final String getMotd() { return this.i; } // Paper - OBFHELPER -+ private final String j; private final String getWorldName() { return this.j; } // Paper - OBFHELPER - private DatagramSocket k; - private final byte[] l = new byte[1460]; -- private String m; -+ private String m; public final String getServerHost() { return this.m; } // Paper - OBFHELPER - private String n; - private final Map o; -- private final RemoteStatusReply p; -+ private final RemoteStatusReply p; private final RemoteStatusReply getCachedFullResponse() { return this.p; } // Paper - OBFHELPER - private long q; -- private final IMinecraftServer r; -+ private final IMinecraftServer r; private final IMinecraftServer getServer() { return this.r; } // Paper - OBFHELPER - - private RemoteStatusListener(IMinecraftServer iminecraftserver, int i) { - super("Query Listener"); -@@ -107,6 +108,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { - - remotestatusreply.a((int) 0); - remotestatusreply.a(this.a(datagrampacket.getSocketAddress())); -+ /* Paper start - GS4 Query event - remotestatusreply.a(this.i); - remotestatusreply.a("SMP"); - remotestatusreply.a(this.j); -@@ -114,6 +116,31 @@ public class RemoteStatusListener extends RemoteConnectionThread { - remotestatusreply.a(Integer.toString(this.h)); - remotestatusreply.a((short) this.g); - remotestatusreply.a(this.m); -+ */ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ remotestatusreply.writeString(queryResponse.getMotd()); -+ remotestatusreply.writeString("SMP"); -+ remotestatusreply.writeString(queryResponse.getMap()); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ remotestatusreply.writeShort((short) queryResponse.getPort()); -+ remotestatusreply.writeString(queryResponse.getHostname()); -+ // Paper end - this.a(remotestatusreply.a(), datagrampacket); - RemoteStatusListener.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -150,6 +177,7 @@ public class RemoteStatusListener extends RemoteConnectionThread { - this.p.a("splitnum"); - this.p.a((int) 128); - this.p.a((int) 0); -+ /* Paper start - GS4 Query event - this.p.a("hostname"); - this.p.a(this.i); - this.p.a("gametype"); -@@ -185,6 +213,79 @@ public class RemoteStatusListener extends RemoteConnectionThread { - } - - this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List plugins = java.util.Collections.emptyList(); -+ org.bukkit.plugin.Plugin[] bukkitPlugins; -+ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { -+ plugins = java.util.stream.Stream.of(bukkitPlugins) -+ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayers()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ this.getCachedFullResponse().writeString("hostname"); -+ this.getCachedFullResponse().writeString(queryResponse.getMotd()); -+ this.getCachedFullResponse().writeString("gametype"); -+ this.getCachedFullResponse().writeString("SMP"); -+ this.getCachedFullResponse().writeString("game_id"); -+ this.getCachedFullResponse().writeString("MINECRAFT"); -+ this.getCachedFullResponse().writeString("version"); -+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); -+ this.getCachedFullResponse().writeString("plugins"); -+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); -+ pluginsString.append(queryResponse.getServerVersion()); -+ if (!queryResponse.getPlugins().isEmpty()) { -+ pluginsString.append(": "); -+ java.util.Iterator iter = queryResponse.getPlugins().iterator(); -+ while (iter.hasNext()) { -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); -+ pluginsString.append(info.getName()); -+ if (info.getVersion() != null) { -+ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); -+ } -+ if (iter.hasNext()) { -+ pluginsString.append(';').append(' '); -+ } -+ } -+ } -+ this.getCachedFullResponse().writeString(pluginsString.toString()); -+ this.getCachedFullResponse().writeString("map"); -+ this.getCachedFullResponse().writeString(queryResponse.getMap()); -+ this.getCachedFullResponse().writeString("numplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ this.getCachedFullResponse().writeString("maxplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ this.getCachedFullResponse().writeString("hostport"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); -+ this.getCachedFullResponse().writeString("hostip"); -+ this.getCachedFullResponse().writeString(queryResponse.getHostname()); -+ // The "meaningless data" start, copied from above -+ this.getCachedFullResponse().writeInt(0); -+ this.getCachedFullResponse().writeInt(1); -+ this.getCachedFullResponse().writeString("player_"); -+ this.getCachedFullResponse().writeInt(0); -+ // "Meaningless data" end -+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); -+ this.getCachedFullResponse().writeInt(0); -+ // Paper end - return this.p.a(); - } - } diff --git a/Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch b/Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index c6d4f6121a3b..000000000000 --- a/Spigot-Server-Patches/0639-Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:27 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 7980930cc712e37a788f894bf2d2ee2b1cfc1196..5e5367710d43fc421806bda31cd611a9cb5869f3 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -22,6 +22,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper - - public class ContainerLoom extends Container { - -@@ -41,7 +42,7 @@ public class ContainerLoom extends Container { - } - // CraftBukkit end - private final ContainerAccess containerAccess; -- private final ContainerProperty d; -+ private final ContainerProperty d; public final ContainerProperty getSelectedBannerPattern() { return this.d; }; // Paper - OBFHELPER - private Runnable e; - private final Slot f; - private final Slot g; -@@ -160,7 +161,22 @@ public class ContainerLoom extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (i > 0 && i <= EnumBannerPatternType.R) { -- this.d.set(i); -+ // Paper start -+ int enumBannerPatternTypeOrdinal = i; -+ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) entityhuman.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(EnumBannerPatternType.values()[i].getIdentifier())); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ for (EnumBannerPatternType nms : EnumBannerPatternType.values()) { -+ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { -+ enumBannerPatternTypeOrdinal = nms.ordinal(); -+ break; -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); -+ // Paper end - this.j(); - return true; - } else { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -index 988e52c675dbb5ef368c8dbb5fb6d4229eb30174..9bc27e727d11d4ac9055a0bc02d8a2ef606ff9c4 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -@@ -33,6 +33,7 @@ public enum EnumBannerPatternType { - this.T = flag; - } - -+ public String getIdentifier() { return this.b(); } // Paper - OBFHELPER - public String b() { - return this.V; - } diff --git a/Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch b/Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch deleted file mode 100644 index 5ae39b3398bd..000000000000 --- a/Spigot-Server-Patches/0640-Configurable-door-breaking-difficulty.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 22:27:43 -0800 -Subject: [PATCH] Configurable door breaking difficulty - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c42e5d9f9c9f67988383c4c25123d8a629ede9e3..946c12abc0e25ccfe09ee64a7ac8b045ba5c46a9 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -5,8 +5,12 @@ import java.util.EnumMap; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -+import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; -+import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.configuration.ConfigurationSection; -@@ -73,6 +77,11 @@ public class PaperWorldConfig { - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } - -+ private > List getEnumList(String path, List def, Class type) { -+ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); -+ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); -+ } -+ - public int cactusMaxHeight; - public int reedMaxHeight; - public int bambooMaxHeight; -@@ -733,4 +742,23 @@ public class PaperWorldConfig { - private void disableMobSpawnerSpawnEggTransformation() { - disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); - } -+ -+ public List zombieBreakDoors; -+ public List vindicatorBreakDoors; -+ private void setupEntityBreakingDoors() { -+ zombieBreakDoors = getEnumList( -+ "door-breaking-difficulty.zombie", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityZombie.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ vindicatorBreakDoors = getEnumList( -+ "door-breaking-difficulty.vindicator", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityVindicator.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index c45dcb56af95f3e87e292b92b697a336461f01bc..f0eda0b83bab8e3a8adbb569b5997402b0e08e9a 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.WorldAccess; - - public class EntityVindicator extends EntityIllagerAbstract { - -+ public static final Predicate getDoorBreakingPredicate() { return b; } // Paper - OBFHELPER - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -@@ -204,7 +205,7 @@ public class EntityVindicator extends EntityIllagerAbstract { - static class a extends PathfinderGoalBreakDoor { - - public a(EntityInsentient entityinsentient) { -- super(entityinsentient, 6, EntityVindicator.b); -+ super(entityinsentient, 6, com.google.common.base.Predicates.in(entityinsentient.world.paperConfig.vindicatorBreakDoors)); // Paper - this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index fb98609a38d665659076b8949b59eaf084408a17..634416c354184bc6a2348c27c55e9868009ccd28 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -86,6 +86,7 @@ public class EntityZombie extends EntityMonster { - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -+ public static final Predicate getDoorBreakingPredicate() { return bq; } // Paper - OBFHELPER - private static final Predicate bq = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.HARD; - }; -@@ -98,7 +99,7 @@ public class EntityZombie extends EntityMonster { - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.br = new PathfinderGoalBreakDoor(this, EntityZombie.bq); -+ this.br = new PathfinderGoalBreakDoor(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper - } - - public EntityZombie(World world) { diff --git a/Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch b/Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch deleted file mode 100644 index 5cf58807ca18..000000000000 --- a/Spigot-Server-Patches/0641-Empty-commands-shall-not-be-dispatched.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 6 Jan 2021 23:38:43 +0100 -Subject: [PATCH] Empty commands shall not be dispatched - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 07d3dec9f613013aac72f3f5db17089ebe5ee770..a70e0761aeddee8fafff971b5cbd0422ab560fb5 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -223,6 +223,7 @@ public class CommandDispatcher { - command = event.getCommand(); - - String[] args = command.split(" "); -+ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched - - String cmd = args[0]; - if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch b/Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch deleted file mode 100644 index bd68a6e4e89f..000000000000 --- a/Spigot-Server-Patches/0642-Implement-API-to-expose-exact-interaction-point.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:27 +1000 -Subject: [PATCH] Implement API to expose exact interaction point - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 31012963815a5c7355753b8cd2749976282ef0d2..87722285690d9d3370610e2a2eb809e0d1f497c9 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -496,7 +496,7 @@ public class PlayerInteractManager { - cancelledBlock = true; - } - -- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand); -+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand, movingobjectpositionblock.getPos()); // Paper - firedInteract = true; - interactResult = event.useItemInHand() == Event.Result.DENY; - interactPosition = blockposition.immutableCopy(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d4b288e127cbd03ded93977fac0c40359525b92d..d2f471b8af997cfedaba8e6b5932f8f6079f3392 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -69,7 +69,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.bukkit.Bukkit; -+import org.bukkit.Location; // Paper - import org.bukkit.Material; - import org.bukkit.NamespacedKey; - import org.bukkit.Server; -@@ -484,7 +486,13 @@ public class CraftEventFactory { - return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); - } - -+ // Paper start - Add interactionPoint - public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand) { -+ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); -+ } -+ -+ public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand, Vec3D hitVec) { -+ // Paper end - Player player = (who == null) ? null : (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); - -@@ -510,7 +518,10 @@ public class CraftEventFactory { - itemInHand = null; - } - -- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); -+ // Paper start -+ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); -+ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); -+ // Paper end - if (cancelledBlock) { - event.setUseInteractedBlock(Event.Result.DENY); - } diff --git a/Spigot-Server-Patches/0643-Remove-stale-POIs.patch b/Spigot-Server-Patches/0643-Remove-stale-POIs.patch deleted file mode 100644 index 3063c80e4722..000000000000 --- a/Spigot-Server-Patches/0643-Remove-stale-POIs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jan 2021 14:17:07 +0100 -Subject: [PATCH] Remove stale POIs - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 7942f492f7688fab52acbefbe5703221b0435752..530963c1435985e17d0e3181c2d8affe003f81de 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -2077,6 +2077,11 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - optional1.ifPresent((villageplacetype) -> { - this.getMinecraftServer().execute(() -> { -+ // Paper start -+ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { -+ this.getPoiStorage().remove(blockposition1); -+ } -+ // Paper end - this.y().a(blockposition1, villageplacetype); - PacketDebug.a(this, blockposition1); - }); -@@ -2084,6 +2089,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ public final VillagePlace getPoiStorage() { return this.y(); } // Paper - OBFHELPER - public VillagePlace y() { - return this.getChunkProvider().j(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index 04b01cb841dc4f34ded5aaa4ea7a8e6d4b470183..ce165233739c7b92a76031b949f269bd0a11149c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -54,6 +54,7 @@ public class VillagePlace extends RegionFileSection { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); - } - -+ public void remove(BlockPosition blockposition) { this.a(blockposition); } // Paper - OBFHELPER - public void a(BlockPosition blockposition) { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); - } -@@ -138,6 +139,7 @@ public class VillagePlace extends RegionFileSection { - return ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).c(blockposition); - } - -+ public final boolean test(BlockPosition blockposition, Predicate predicate) { return this.a(blockposition, predicate); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition, Predicate predicate) { - return (Boolean) this.d(SectionPosition.a(blockposition).s()).map((villageplacesection) -> { - return villageplacesection.a(blockposition, predicate); diff --git a/Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch b/Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch deleted file mode 100644 index 06ed0a695a46..000000000000 --- a/Spigot-Server-Patches/0644-Fix-villager-boat-exploit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 11 Jan 2021 12:43:51 -0800 -Subject: [PATCH] Fix villager boat exploit - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 66fbbc4c91e16a3dfb4bb756972e667121693501..cf457f6b6ee2968f68f4eede30bb703a6a4f990b 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -77,6 +77,7 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -@@ -621,6 +622,15 @@ public abstract class PlayerList { - - for (Iterator iterator = entity.getAllPassengers().iterator(); iterator.hasNext(); entity1.dead = true) { - entity1 = (Entity) iterator.next(); -+ // Paper start -+ if (entity1 instanceof EntityVillagerAbstract) { -+ final EntityVillagerAbstract villager = (EntityVillagerAbstract) entity1; -+ final EntityHuman human = villager.getTrader(); -+ if (human != null) { -+ villager.setTradingPlayer(null); -+ } -+ } -+ // Paper end - worldserver.removeEntity(entity1); - } - diff --git a/Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch b/Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch deleted file mode 100644 index a168fe3f5f21..000000000000 --- a/Spigot-Server-Patches/0645-Entity-load-save-limit-per-chunk.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 18 Nov 2020 20:52:25 -0800 -Subject: [PATCH] Entity load/save limit per chunk - -Adds a config option to limit the number of entities saved and loaded -to a chunk. The default values of -1 disable the limit. Although -defaults are only included for certain entites, this allows setting -limits for any entity type. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 946c12abc0e25ccfe09ee64a7ac8b045ba5c46a9..bda4eeb032bea452ea368c679f96b2bd93118730 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -9,6 +9,7 @@ import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.monster.EntityVindicator; - import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; -@@ -761,4 +762,18 @@ public class PaperWorldConfig { - EnumDifficulty.class - ); - } -+ -+ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); -+ private void entityPerChunkSaveLimits() { -+ getInt("entity-per-chunk-save-limit.experience_orb", -1); -+ getInt("entity-per-chunk-save-limit.snowball", -1); -+ getInt("entity-per-chunk-save-limit.ender_pearl", -1); -+ getInt("entity-per-chunk-save-limit.arrow", -1); -+ EntityTypes.getEntityNameList().forEach(name -> { -+ final EntityTypes type = EntityTypes.getByName(name.getKey()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); -+ final String path = ".entity-per-chunk-save-limit." + name.getKey(); -+ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults -+ if (value != -1) entityPerChunkSaveLimits.put(type, value); -+ }); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 2e5221bc1b9e260e33f2cef2653dc59d05e2680d..4eaf497d048324a85ce49fc1c6e9559991c20df7 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -539,11 +539,22 @@ public class ChunkRegionLoader { - - chunk.d(false); - -+ // Paper start -+ final Map, Integer> savedEntityCounts = Maps.newHashMap(); - for (int j = 0; j < chunk.getEntitySlices().length; ++j) { - Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ continue; -+ } -+ savedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start - if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -@@ -674,10 +685,21 @@ public class ChunkRegionLoader { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); - -+ // Paper start -+ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); - - EntityTypes.a(nbttagcompound1, world, (entity) -> { -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return null; -+ } -+ loadedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - chunk.a(entity); - return entity; - }); diff --git a/Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch b/Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch deleted file mode 100644 index 382d08802425..000000000000 --- a/Spigot-Server-Patches/0646-Add-sendOpLevel-API.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:03:03 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index cf457f6b6ee2968f68f4eede30bb703a6a4f990b..1358993217e601e3bab6e0a4e8c55d555865a13e 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1138,6 +1138,11 @@ public abstract class PlayerList { - } - - private void a(EntityPlayer entityplayer, int i) { -+ // Paper start - add recalculatePermissions parameter -+ this.sendPlayerOperatorStatus(entityplayer, i, true); -+ } -+ public void sendPlayerOperatorStatus(EntityPlayer entityplayer, int i, boolean recalculatePermissions) { -+ // Paper end - if (entityplayer.playerConnection != null) { - byte b0; - -@@ -1152,8 +1157,10 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); - } - -+ if (recalculatePermissions) { // Paper - entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit - this.server.getCommandDispatcher().a(entityplayer); -+ } // Paper - } - - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 41987716afa8ec34214868373df97d0e8f8b27c1..e81de526a847c730abf86016354c1dc57780ec8b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2300,6 +2300,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - ? (org.bukkit.entity.Firework) entity.getBukkitEntity() - : null; - } -+ -+ @Override -+ public void sendOpLevel(byte level) { -+ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); -+ -+ this.getHandle().getMinecraftServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch b/Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch deleted file mode 100644 index 3e68e76756be..000000000000 --- a/Spigot-Server-Patches/0647-Add-StructureLocateEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Wed, 16 Sep 2020 01:12:29 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index b1f2c424ef358f79c7fced88a61560d3ce32a2b6..f2621f61cb372ec436fe81e7a93f1aef7d360f3f 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.chunk; - - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; -+import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. - import java.util.BitSet; - import java.util.Iterator; - import java.util.List; -@@ -160,6 +161,22 @@ public abstract class ChunkGenerator { - - @Nullable - public BlockPosition findNearestMapFeature(WorldServer worldserver, StructureGenerator structuregenerator, BlockPosition blockposition, int i, boolean flag) { -+ // Paper start -+ org.bukkit.World world = worldserver.getWorld(); -+ org.bukkit.Location originLocation = new org.bukkit.Location(world, blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ StructureLocateEvent event = new StructureLocateEvent(world, originLocation, org.bukkit.StructureType.getStructureTypes().get(structuregenerator.i()), i, flag); -+ if(!event.callEvent()) return null; -+ // If event call set a final location, skip structure finding and just return set result. -+ if(event.getResult() != null) return new BlockPosition(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); -+ // Get origin location (re)defined by event call. -+ blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); -+ // Get world (re)defined by event call. -+ worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); -+ // Get radius and whether to find unexplored structures (re)defined by event call. -+ i = event.getRadius(); -+ flag = event.shouldFindUnexplored(); -+ structuregenerator = StructureGenerator.a.get(event.getType().getName()); -+ // Paper end - if (!this.b.a(structuregenerator)) { - return null; - } else if (structuregenerator == StructureGenerator.STRONGHOLD) { diff --git a/Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch b/Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch deleted file mode 100644 index 2ffec6957ff0..000000000000 --- a/Spigot-Server-Patches/0648-Collision-option-for-requiring-a-player-participant.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:48:37 +0100 -Subject: [PATCH] Collision option for requiring a player participant - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bda4eeb032bea452ea368c679f96b2bd93118730..5801fe872aff240dc8209069b978d6a4dba30f06 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -716,6 +716,18 @@ public class PaperWorldConfig { - } - } - -+ public boolean onlyPlayersCollide = false; -+ public boolean allowVehicleCollisions = true; -+ private void onlyPlayersCollide() { -+ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); -+ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); -+ if (onlyPlayersCollide && !allowVehicleCollisions) { -+ log("Collisions will only work if a player is one of the two entities colliding."); -+ } else if (onlyPlayersCollide) { -+ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); -+ } -+ } -+ - public int wanderingTraderSpawnMinuteTicks = 1200; - public int wanderingTraderSpawnDayTicks = 24000; - public int wanderingTraderSpawnChanceFailureIncrement = 25; -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d801486565865cf3b56e9d80b7c1643e9b0f4597..f7223f214f911dd25abcf3a52745588ec630241d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -1467,6 +1467,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public void collide(Entity entity) { - if (!this.isSameVehicle(entity)) { - if (!entity.noclip && !this.noclip) { -+ if (this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer || this instanceof EntityPlayer)) return; // Paper - double d0 = entity.locX() - this.locX(); - double d1 = entity.locZ() - this.locZ(); - double d2 = MathHelper.a(d0, d1); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 2609b83573e0e8532e6c4c36d4f475bf0da6a354..069076d3c7165440217a7632b089ab2aa0fbdb1d 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -230,6 +231,7 @@ public class EntityBoat extends Entity { - - @Override - public void collide(Entity entity) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (entity instanceof EntityBoat) { - if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 2e3ceab3e34f7756764b3471b13d48d1263ecba9..57821301ef031995e6044a17b46c70a693322455 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -21,6 +21,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; -@@ -767,6 +768,7 @@ public abstract class EntityMinecartAbstract extends Entity { - public void collide(Entity entity) { - if (!this.world.isClientSide) { - if (!entity.noclip && !this.noclip) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (!this.w(entity)) { - // CraftBukkit start - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); diff --git a/Spigot-Server-Patches/0649-Respect-ProjectileHitEvent-cancel-where-missing.patch b/Spigot-Server-Patches/0649-Respect-ProjectileHitEvent-cancel-where-missing.patch deleted file mode 100644 index cf1af3ddff7b..000000000000 --- a/Spigot-Server-Patches/0649-Respect-ProjectileHitEvent-cancel-where-missing.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Jan 2021 14:30:12 -0500 -Subject: [PATCH] Respect ProjectileHitEvent cancel where missing - -The duplicate ProjectileHitEvent in EntityFireball was not cancelled - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 9660dc2263c48a5818b767843658eeb9ee1748ea..243b24e7c304b379aeb925fe1e2435853f80397d 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -87,7 +87,7 @@ public abstract class EntityFireball extends IProjectile { - - // CraftBukkit start - Fire ProjectileHitEvent - if (this.dead) { -- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); -+ if (CraftEventFactory.callProjectileHitEvent(this, movingobjectposition).isCancelled()) return; // Paper - this is an undesired duplicate event, but make cancellable - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch b/Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index 812ef9c07e3e..000000000000 --- a/Spigot-Server-Patches/0650-Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 9c6330da4e026a7753698b5d103c009730154c3e..bdd00608a72dd81003731ff5fbe774dfdc5220e5 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -11,6 +11,7 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.core.IRegistry; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.IInventory; -@@ -61,7 +62,12 @@ public abstract class Container { - } - private IChatBaseComponent title; - public final IChatBaseComponent getTitle() { -- Preconditions.checkState(this.title != null, "Title not set"); -+ // Paper start - return chat component with empty text instead of throwing error -+ // Preconditions.checkState(this.title != null, "Title not set"); -+ if(this.title == null){ -+ return new ChatComponentText(""); -+ } -+ // Paper end - return this.title; - } - public final void setTitle(IChatBaseComponent title) { diff --git a/Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch b/Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch deleted file mode 100644 index 87d12b619199..000000000000 --- a/Spigot-Server-Patches/0651-Make-schedule-command-per-world.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:52:44 -0800 -Subject: [PATCH] Make schedule command per-world - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandSchedule.java b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -index b88a91072032b75f83d811d63e1b5e3808faa9be..440b25dde0299037032d535c4c751f252775d6ad 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandSchedule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -@@ -32,7 +32,7 @@ public class CommandSchedule { - return new ChatMessage("commands.schedule.cleared.failure", new Object[]{object}); - }); - private static final SuggestionProvider c = (commandcontext, suggestionsbuilder) -> { -- return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getServer().getSaveData().H().u().a(), suggestionsbuilder); -+ return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getWorld().worldDataServer.H().u().a(), suggestionsbuilder); // Paper - }; - - public static void a(CommandDispatcher commanddispatcher) { -@@ -55,7 +55,7 @@ public class CommandSchedule { - } else { - long j = commandlistenerwrapper.getWorld().getTime() + (long) i; - MinecraftKey minecraftkey = (MinecraftKey) pair.getFirst(); -- CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getServer().getSaveData().H().u(); -+ CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getWorld().worldDataServer.H().u(); // Paper - - ((Either) pair.getSecond()).ifLeft((customfunction) -> { - String s = minecraftkey.toString(); -@@ -81,7 +81,7 @@ public class CommandSchedule { - } - - private static int a(CommandListenerWrapper commandlistenerwrapper, String s) throws CommandSyntaxException { -- int i = commandlistenerwrapper.getServer().getSaveData().H().u().a(s); -+ int i = commandlistenerwrapper.getWorld().worldDataServer.H().u().a(s); // Paper - - if (i == 0) { - throw CommandSchedule.b.create(s); diff --git a/Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch b/Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch deleted file mode 100644 index cab50cf8eb4a..000000000000 --- a/Spigot-Server-Patches/0652-Configurable-max-leash-distance.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 21:04:03 -0800 -Subject: [PATCH] Configurable max leash distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5801fe872aff240dc8209069b978d6a4dba30f06..849603de7c918788f1f80d7effb93658a69b0fd6 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -167,6 +167,12 @@ public class PaperWorldConfig { - } - } - -+ public float maxLeashDistance = 10f; -+ private void maxLeashDistance() { -+ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); -+ log("Max leash distance: " + maxLeashDistance); -+ } -+ - public boolean disableEndCredits; - private void disableEndCredits() { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index bbf0f345bfdd8a3a1f7fe902a42b2b18cdcf07a5..20570580367697e37e6c45147168c3beb6c8d31b 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -47,7 +47,7 @@ public abstract class EntityCreature extends EntityInsentient { - float f = this.g(entity); - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - } -@@ -56,7 +56,7 @@ public abstract class EntityCreature extends EntityInsentient { - } - - this.x(f); -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - this.goalSelector.a(PathfinderGoal.Type.MOVE); diff --git a/Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch b/Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch deleted file mode 100644 index 1ae6ad2b2c97..000000000000 --- a/Spigot-Server-Patches/0653-Implement-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:16:09 +1000 -Subject: [PATCH] Implement BlockPreDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 966051ab3e720e5b3f0fb9ab852c8908c5f23f3b..9b92824f1c2797e321ced953d33d2c2fd339374a 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -88,6 +88,7 @@ public class BlockDispenser extends BlockTileEntity { - IDispenseBehavior idispensebehavior = this.a(itemstack); - - if (idispensebehavior != IDispenseBehavior.NONE) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, blockposition, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here - eventFired = false; // CraftBukkit - reset event status - tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d2f471b8af997cfedaba8e6b5932f8f6079f3392..f0ab3d42bc34bf8c1b81642e600360110a88115b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -70,6 +70,7 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; -+import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper - import org.bukkit.Bukkit; - import org.bukkit.Location; // Paper - import org.bukkit.Material; -@@ -1805,5 +1806,11 @@ public class CraftEventFactory { - BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); - return event.callEvent(); - } -+ -+ public static boolean handleBlockPreDispenseEvent(WorldServer worldserver, BlockPosition blockposition, ItemStack itemStack, int slot) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); -+ return event.callEvent(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch b/Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index bab60d5a2ed1..000000000000 --- a/Spigot-Server-Patches/0654-Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:35 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2ca8e1bade5450a14125b77540792e0b18c3e19b ---- /dev/null -+++ b/src/main/java/io/papermc/paper/CraftEntityTag.java -@@ -0,0 +1,29 @@ -+package io.papermc.paper; -+ -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.tags.Tags; -+import net.minecraft.world.entity.EntityTypes; -+import org.bukkit.craftbukkit.tag.CraftTag; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.entity.EntityType; -+ -+import java.util.Collections; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class CraftEntityTag extends CraftTag, EntityType> { -+ -+ public CraftEntityTag(Tags> registry, MinecraftKey tag) { -+ super(registry, tag); -+ } -+ -+ @Override -+ public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); -+ } -+ -+ @Override -+ public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 49d989545aa1a02ecc811a74f0283e779d2543a0..19bd420e6bf625f77bb37755ff8364e5955feb2a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2223,6 +2223,11 @@ public final class CraftServer implements Server { - Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); - - return (org.bukkit.Tag) new CraftFluidTag(console.getTagRegistry().getFluidTags(), key); -+ // Paper start -+ case org.bukkit.Tag.REGISTRY_ENTITIES: -+ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); -+ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTagRegistry().getEntityTags(), key); -+ // Paper end - default: - throw new IllegalArgumentException(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 36ad77a5a3987c1de5d0de7cbcb94cb6fe841d44..848a704fa100c39098a5716bb25b6a9ed85d7a8c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -118,8 +118,17 @@ public final class CraftMagicNumbers implements UnsafeValues { - private static final Map MATERIAL_ITEM = new HashMap<>(); - private static final Map MATERIAL_BLOCK = new HashMap<>(); - private static final Map MATERIAL_FLUID = new HashMap<>(); -+ // Paper start -+ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); -+ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); - - static { -+ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { -+ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; -+ ENTITY_TYPE_ENTITY_TYPES.put(type, IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); -+ ENTITY_TYPES_ENTITY_TYPE.put(IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); -+ } -+ // Paper end - for (Block block : IRegistry.BLOCK) { - BLOCK_MATERIAL.put(block, Material.getMaterial(IRegistry.BLOCK.getKey(block).getKey().toUpperCase(Locale.ROOT))); - } -@@ -185,6 +194,14 @@ public final class CraftMagicNumbers implements UnsafeValues { - public static MinecraftKey key(Material mat) { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } -+ // Paper start -+ public static net.minecraft.world.entity.EntityTypes getEntityTypes(org.bukkit.entity.EntityType type) { -+ return ENTITY_TYPE_ENTITY_TYPES.get(type); -+ } -+ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityTypes entityTypes) { -+ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); -+ } -+ // Paper end - // ======================================================================== - // Paper start - @Override diff --git a/Spigot-Server-Patches/0655-added-Wither-API.patch b/Spigot-Server-Patches/0655-added-Wither-API.patch deleted file mode 100644 index 29bb22ea9dad..000000000000 --- a/Spigot-Server-Patches/0655-added-Wither-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:19 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 30290c0208a4725b2eb0e7764465c354e592e4ee..891905712903bf3ba241187791cfa995375430d5 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -82,6 +82,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); - }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); -+ // Paper start -+ private boolean canPortal = false; -+ -+ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } -+ // Paper end - - public EntityWither(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -580,6 +585,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); - } - -+ public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER - public boolean S_() { - return this.getHealth() <= this.getMaxHealth() / 2.0F; - } -@@ -596,7 +602,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - @Override - public boolean canPortal() { -- return false; -+ return canPortal; // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 1d94aeec37dcb9758d88ef25a5cad1333bbfbf6c..adf4ce8afa3a42ea8a184905969e03b6b756830f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -38,4 +38,31 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok - public BossBar getBossBar() { - return bossBar; - } -+ -+ // Paper start -+ @Override -+ public boolean isCharged() { -+ return getHandle().isPowered(); -+ } -+ -+ @Override -+ public int getInvulnerableTicks() { -+ return getHandle().getInvul(); -+ } -+ -+ @Override -+ public void setInvulnerableTicks(int ticks) { -+ getHandle().setInvul(ticks); -+ } -+ -+ @Override -+ public boolean canTravelThroughPortals() { -+ return getHandle().canPortal(); -+ } -+ -+ @Override -+ public void setCanTravelThroughPortals(boolean value) { -+ getHandle().setCanTravelThroughPortals(value); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index 8300eca18e42..000000000000 --- a/Spigot-Server-Patches/0656-Added-firing-of-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:14:51 -0600 -Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -index 7e5a0bad616d9477e01426ab1604184ef3fab1c1..085298a9c3837dfa48dfbbf02d6261db12c79036 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -@@ -13,6 +13,10 @@ import net.minecraft.world.entity.player.PlayerInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - // CraftBukkit end - -+// Paper start -+import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; -+// Paper end -+ - public class ContainerBeacon extends Container { - - private final IInventory beacon; -@@ -139,9 +143,15 @@ public class ContainerBeacon extends Container { - - public void c(int i, int j) { - if (this.d.hasItem()) { -- this.containerProperties.setProperty(1, i); -- this.containerProperties.setProperty(2, j); -+ // Paper start -+ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(i), org.bukkit.potion.PotionEffectType.getById(j), this.containerAccess.getLocation().getBlock()); -+ if (event.callEvent()) { -+ this.containerProperties.setProperty(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); -+ this.containerProperties.setProperty(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); -+ if (!event.willConsumeItem()) return; - this.d.a(1); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch b/Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch deleted file mode 100644 index d05dbe7aff22..000000000000 --- a/Spigot-Server-Patches/0657-Fix-console-spam-when-removing-chests-in-water.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 19 Nov 2020 02:07:10 +0000 -Subject: [PATCH] Fix console spam when removing chests in water - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index b2c29cff5883868cb56a4e376ab946ac929abc94..a45ee959f41e7f349ff2c309f21fa44ec671cb87 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -239,7 +239,7 @@ public class BlockChest extends BlockChestAbstract implements I - @Override - public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata.a(iblockdata1.getBlock())) { -- TileEntity tileentity = world.getTileEntity(blockposition); -+ TileEntity tileentity = world.getTileEntity(blockposition, false); // Paper - Don't validate TE - Fix console spam when removing chests in water - - if (tileentity instanceof IInventory) { - InventoryUtils.dropInventory(world, blockposition, (IInventory) tileentity); diff --git a/Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch b/Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch deleted file mode 100644 index a722e61d8245..000000000000 --- a/Spigot-Server-Patches/0658-Add-toggle-for-always-placing-the-dragon-egg.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 26 Nov 2020 11:47:24 +0000 -Subject: [PATCH] Add toggle for always placing the dragon egg - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 849603de7c918788f1f80d7effb93658a69b0fd6..1ceacb6bbfe99069763845a8aef48a3fb4841e32 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -794,4 +794,9 @@ public class PaperWorldConfig { - if (value != -1) entityPerChunkSaveLimits.put(type, value); - }); - } -+ -+ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; -+ private void enderDragonsDeathAlwaysPlacesDragonEgg() { -+ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index c0a6b340810b8ea4f454290b1ac22316ff0e6e22..80fcceec519ef59d057d27a81fcd0649a20447da 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -400,7 +400,7 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -- if (!this.previouslyKilled) { -+ if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg - this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); - } - diff --git a/Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch b/Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index 6444ee5cbef8..000000000000 --- a/Spigot-Server-Patches/0659-Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:14:27 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - -Co-Authored-By: MiniDigger - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index bdd00608a72dd81003731ff5fbe774dfdc5220e5..b58ec4abff2840556eb06e08b241a2eaa85c2c7f 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -118,7 +118,7 @@ public abstract class Container { - return slot; - } - -- protected ContainerProperty a(ContainerProperty containerproperty) { -+ protected ContainerProperty addDataSlot(ContainerProperty containerproperty) { return a(containerproperty); } protected ContainerProperty a(ContainerProperty containerproperty) { // Paper - OBFHELPER - this.d.add(containerproperty); - return containerproperty; - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -index 67c3b7ddb0b0f10c82577cbea7506c9d80d41368..b9c82e68a811c2ef6bf2d5ce3ae9f858bcb263d5 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -@@ -20,7 +20,7 @@ public abstract class ContainerProperty { - }; - } - -- public static ContainerProperty a(final int[] aint, final int i) { -+ public static ContainerProperty shared(final int[] aint, final int i) { return a(aint, i); } public static ContainerProperty a(final int[] aint, final int i) { // Paper - OBFHELPER - return new ContainerProperty() { - @Override - public int get() { -@@ -54,7 +54,7 @@ public abstract class ContainerProperty { - - public abstract void set(int i); - -- public boolean c() { -+ public boolean checkAndClearUpdateFlag() { return c(); } public boolean c() { // Paper - OBFHELPER - int i = this.get(); - boolean flag = i != this.a; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index 1589d9ca201d386d11d9fd57fa8ba6848bae215c..dc667dd5d8514ae4c8a2087cb913f44320ebfc48 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -22,13 +22,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper - - public class ContainerStonecutter extends Container { - - private final ContainerAccess containerAccess; - private final ContainerProperty containerProperty; - private final World world; -- private List i; -+ private List i; public final List getRecipes() { return this.i; } // Paper - OBFHELPER - private ItemStack j; - private long k; - final Slot c; -@@ -58,7 +59,7 @@ public class ContainerStonecutter extends Container { - - public ContainerStonecutter(int i, PlayerInventory playerinventory, final ContainerAccess containeraccess) { - super(Containers.STONECUTTER, i); -- this.containerProperty = ContainerProperty.a(); -+ this.containerProperty = addDataSlot(ContainerProperty.shared(new int[1], 0)); // Paper - allow replication - this.i = Lists.newArrayList(); - this.j = ItemStack.b; - this.l = () -> { -@@ -136,13 +137,36 @@ public class ContainerStonecutter extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (this.d(i)) { -- this.containerProperty.set(i); -+ // Paper start -+ int recipeIndex = i; -+ this.containerProperty.set(recipeIndex); -+ this.containerProperty.checkAndClearUpdateFlag(); // mark as changed -+ if (this.isValidRecipeIndex(i)) { -+ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(i).toBukkitRecipe()); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ int newRecipeIndex; -+ if (!this.getRecipes().get(recipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same -+ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { -+ if (this.getRecipes().get(newRecipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.containerProperty.set(recipeIndex); // set new index, so that listeners can read it -+ // Paper end - this.i(); - } - - return true; - } - -+ private boolean isValidRecipeIndex(int index) { return this.d(index); } // Paper - OBFHELPER - private boolean d(int i) { - return i >= 0 && i < this.i.size(); - } diff --git a/Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index 543c76cfddf6..000000000000 --- a/Spigot-Server-Patches/0660-Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 29 Jan 2021 15:13:11 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index 20570580367697e37e6c45147168c3beb6c8d31b..831414980d40f4382cf7370db28dd8fae534384b 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -48,8 +48,11 @@ public abstract class EntityCreature extends EntityInsentient { - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return; -@@ -57,8 +60,11 @@ public abstract class EntityCreature extends EntityInsentient { - - this.x(f); - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - this.goalSelector.a(PathfinderGoal.Type.MOVE); - } else if (f > 6.0F) { - double d0 = (entity.locX() - this.locX()) / (double) f; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index ff482e3774f580d8ba7028f6c5141888d3bd907a..a246edd09854dabf095da75c9d200f5cf26e7138 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -88,6 +88,7 @@ import org.bukkit.event.entity.EntityTargetEvent; - import org.bukkit.event.entity.EntityTransformEvent; - import org.bukkit.event.entity.EntityUnleashEvent; - import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper - // CraftBukkit end - - public abstract class EntityInsentient extends EntityLiving { -@@ -1207,12 +1208,15 @@ public abstract class EntityInsentient extends EntityLiving { - return EnumInteractionResult.PASS; - } else if (this.getLeashHolder() == entityhuman) { - // CraftBukkit start - fire PlayerUnleashEntityEvent -- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); - return EnumInteractionResult.PASS; - } - // CraftBukkit end -- this.unleash(true, !entityhuman.abilities.canInstantlyBuild); -+ this.unleash(true, event.isDropLeash()); // Paper - drop leash variable - return EnumInteractionResult.a(this.world.isClientSide); - } else { - EnumInteractionResult enuminteractionresult = this.c(entityhuman, enumhand); -@@ -1366,8 +1370,11 @@ public abstract class EntityInsentient extends EntityLiving { - - if (this.leashHolder != null) { - if (!this.isAlive() || !this.leashHolder.isAlive()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - } -@@ -1435,8 +1442,11 @@ public abstract class EntityInsentient extends EntityLiving { - boolean flag1 = super.a(entity, flag); - - if (flag1 && this.isLeashed()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return flag1; -@@ -1638,7 +1648,10 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected void bN() { - super.bN(); -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, false); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -index 8f6d2a6a388021f437ac5554e9ece8eca89e1f46..519f0cabadcf97a44a112fd963a8d3ab194650c4 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -@@ -30,6 +30,8 @@ import net.minecraft.server.level.WorldServer; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end - -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper -+ - public class EntityLeash extends EntityHanging { - - public EntityLeash(EntityTypes entitytypes, World world) { -@@ -125,11 +127,14 @@ public class EntityLeash extends EntityHanging { - entityinsentient = (EntityInsentient) iterator.next(); - if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { - // CraftBukkit start -- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - die = false; - continue; - } -- entityinsentient.unleash(true, !entityhuman.abilities.canInstantlyBuild); // false -> survival mode boolean -+ entityinsentient.unleash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable - // CraftBukkit end - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index f0ab3d42bc34bf8c1b81642e600360110a88115b..bbc7f97748f5b61047a9b01a2ecb8c2d0a7b677c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1469,8 +1469,10 @@ public class CraftEventFactory { - return itemInHand; - } - -- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player) { -- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); -+ // Paper start - drop leash variable -+ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player, boolean dropLeash) { -+ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); -+ // Paper end - entity.world.getServer().getPluginManager().callEvent(event); - return event; - } diff --git a/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch b/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch deleted file mode 100644 index dc18792789d9..000000000000 --- a/Spigot-Server-Patches/0661-Skip-distance-map-update-when-spawning-disabled.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Beech Horn -Date: Fri, 14 Feb 2020 19:39:59 +0000 -Subject: [PATCH] Skip distance map update when spawning disabled. - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 326c52f9f2cc729fd52162aeae18ec9dae3a4eaf..c5e54c519e1f686761faa53b5e9579c514a65332 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -825,7 +825,7 @@ public class ChunkProviderServer extends IChunkProvider { - int l = this.chunkMapDistance.b(); - // Paper start - per player mob spawning - SpawnerCreature.d spawnercreature_d; // moved down -- if (this.playerChunkMap.playerMobDistanceMap != null) { -+ if ((this.allowAnimals || this.allowMonsters) && this.playerChunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled - // update distance map - this.world.timings.playerMobDistanceMapUpdate.startTiming(); - this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); diff --git a/Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch b/Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch deleted file mode 100644 index 93084291cf23..000000000000 --- a/Spigot-Server-Patches/0662-Reset-shield-blocking-on-dimension-change.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Sun, 24 Jan 2021 08:55:19 -0800 -Subject: [PATCH] Reset shield blocking on dimension change - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index c0446ed3c7cc24fae2880dfba71228f5edee66d6..3f44d5b8e3bc4f897a5dda473532004078fe0ebe 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1118,6 +1118,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.world.getServer().getPluginManager().callEvent(changeEvent); - // CraftBukkit end - } -+ // Paper start -+ if (this.isBlocking()) { -+ this.clearActiveItem(); -+ } -+ // Paper end - - return this; - } diff --git a/Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch b/Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch deleted file mode 100644 index 609439176dcb..000000000000 --- a/Spigot-Server-Patches/0663-add-DragonEggFormEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:57 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 80fcceec519ef59d057d27a81fcd0649a20447da..0ab6319aa3e4e1f5679f37be36999ca56ca2484c 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -57,6 +57,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - import net.minecraft.world.phys.AxisAlignedBB; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent - - public class EnderDragonBattle { - -@@ -400,9 +401,24 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -+ // Paper start - DragonEggFormEvent -+ BlockPosition eggPosition = this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.getPosition()); -+ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.world, eggPosition); -+ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); -+ eggState.setData(Blocks.DRAGON_EGG.getBlockData()); -+ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, -+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); -+ // Paper end - DragonEggFormEvent - if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg -- this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ // Paper start - DragonEggFormEvent -+ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ } else { -+ eggEvent.setCancelled(true); -+ } -+ if (eggEvent.callEvent()) { -+ eggEvent.getNewState().update(true); - } -+ // Paper end - DragonEggFormEvent - - this.previouslyKilled = true; - this.dragonKilled = true; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -index 18395a3b4a7df1c99e952b9c8e738f165648eba5..851b8c2a86d7155278b49c44c6db8b1cbd2065f2 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -@@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - - public class WorldGenEndTrophy extends WorldGenerator { - -- public static final BlockPosition a = BlockPosition.ZERO; -+ public static final BlockPosition a = BlockPosition.ZERO; public static BlockPosition getPosition() { return a; } // Paper - OBFHELPER - private final boolean ab; - - public WorldGenEndTrophy(boolean flag) { -@@ -22,7 +22,7 @@ public class WorldGenEndTrophy extends WorldGenerator -Date: Tue, 11 Feb 2020 21:56:48 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 1c17db3e9e30d16bc5778bb3220e3e9e8c336258..952d5c7c3324377e0036b9d7e524484cb581e5b2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -13,6 +13,7 @@ import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import io.papermc.paper.event.entity.EntityMoveEvent; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -1459,6 +1460,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 530963c1435985e17d0e3181c2d8affe003f81de..c7a661d4f43fad04ebada1bbebf4e4274fc9c452 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -213,6 +213,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ public boolean hasEntityMoveEvent = false; // Paper - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index deffd82dfca1d2eea6e5b8db9228015bf35ad0a3..21341eeb8148be119fbc1dd370c1beaf70a319e0 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Pair; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; -+import io.papermc.paper.event.entity.EntityMoveEvent; - import java.util.Collection; - import java.util.ConcurrentModificationException; - import java.util.Iterator; -@@ -2912,6 +2913,20 @@ public abstract class EntityLiving extends Entity { - - this.collideNearby(); - this.world.getMethodProfiler().exit(); -+ // Paper start -+ if (((WorldServer) world).hasEntityMoveEvent) { -+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); -+ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); -+ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); -+ } -+ } -+ } -+ // Paper end - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); - } diff --git a/Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch b/Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch deleted file mode 100644 index 8b4e9bfbd573..000000000000 --- a/Spigot-Server-Patches/0665-added-option-to-disable-pathfinding-updates-on-block.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Mon, 25 Jan 2021 14:37:57 +0100 -Subject: [PATCH] added option to disable pathfinding updates on block changes - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1ceacb6bbfe99069763845a8aef48a3fb4841e32..d2f6e1308a4dfec663770e2c7f4de0cf22402a97 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -799,4 +799,9 @@ public class PaperWorldConfig { - private void enderDragonsDeathAlwaysPlacesDragonEgg() { - enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); - } -+ -+ public boolean updatePathfindingOnBlockUpdate = true; -+ private void setUpdatePathfindingOnBlockUpdate() { -+ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index c7a661d4f43fad04ebada1bbebf4e4274fc9c452..325eba4e30ddcdfd038a215fbfde3bdc3e7c9b2a 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1684,6 +1684,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - @Override - public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { - this.getChunkProvider().flagDirty(blockposition); -+ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates - VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition); - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - -@@ -1712,6 +1713,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.tickingEntities = wasTicking; // Paper - } -+ } // Paper - } - - @Override diff --git a/Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch b/Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch deleted file mode 100644 index e044ac5972f1..000000000000 --- a/Spigot-Server-Patches/0666-Inline-shift-direction-fields.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 18 Jan 2021 20:45:25 -0500 -Subject: [PATCH] Inline shift direction fields - -Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the -critical section for much of the server, including the lighting engine. - -diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java -index a699005582293326076eaa80655c5343e6c22ff0..703bdefeb615ef8d15b428a893b5e4939d726f13 100644 ---- a/src/main/java/net/minecraft/core/EnumDirection.java -+++ b/src/main/java/net/minecraft/core/EnumDirection.java -@@ -53,6 +53,11 @@ public enum EnumDirection implements INamable { - }, (enumdirection, enumdirection1) -> { - throw new IllegalArgumentException("Duplicate keys"); - }, Long2ObjectOpenHashMap::new)); -+ // Paper start -+ private final int adjX; -+ private final int adjY; -+ private final int adjZ; -+ // Paper end - - private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) { - this.g = i; -@@ -62,6 +67,11 @@ public enum EnumDirection implements INamable { - this.k = enumdirection_enumaxis; - this.l = enumdirection_enumaxisdirection; - this.m = baseblockposition; -+ // Paper start -+ this.adjX = baseblockposition.getX(); -+ this.adjY = baseblockposition.getY(); -+ this.adjZ = baseblockposition.getZ(); -+ // Paper end - } - - public static EnumDirection[] a(Entity entity) { -@@ -137,15 +147,15 @@ public enum EnumDirection implements INamable { - } - - public int getAdjacentX() { -- return this.m.getX(); -+ return this.adjX; // Paper - } - - public int getAdjacentY() { -- return this.m.getY(); -+ return this.adjY; // Paper - } - - public int getAdjacentZ() { -- return this.m.getZ(); -+ return this.adjZ; // Paper - } - - public String m() { diff --git a/Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch b/Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index d544c54e865e..000000000000 --- a/Spigot-Server-Patches/0667-Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:23:37 -0600 -Subject: [PATCH] Allow adding items to BlockDropItemEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index bbc7f97748f5b61047a9b01a2ecb8c2d0a7b677c..b14cec316b16e46d54d389650372c5c9ce1e5a4d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -398,13 +398,30 @@ public class CraftEventFactory { - } - - public static void handleBlockDropItemEvent(Block block, BlockState state, EntityPlayer player, List items) { -- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); -+ // Paper start -+ List list = new ArrayList<>(); -+ for (EntityItem item : items) { -+ list.add((Item) item.getBukkitEntity()); -+ } -+ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); -+ // Paper end - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- for (EntityItem item : items) { -- item.world.addEntity(item); -+ // Paper start -+ for (Item bukkit : list) { -+ if (!bukkit.isValid()) { -+ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); -+ item.world.addEntity(item); -+ } -+ } -+ } else { -+ for (Item bukkit : list) { -+ if (bukkit.isValid()) { -+ bukkit.remove(); -+ } - } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index f2acd9e21200..000000000000 --- a/Spigot-Server-Patches/0668-Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:54 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 13e461ffb2ee2e7d0440c0f60809ea99629b843c..0be39dac4b9dd69d7d73d86d64cf1e33e4086e81 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -635,4 +635,15 @@ public class CraftScheduler implements BukkitScheduler { - public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { - throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); - } -+ -+ // Paper start - add getMainThreadExecutor -+ @Override -+ public Executor getMainThreadExecutor(Plugin plugin) { -+ Validate.notNull(plugin, "Plugin cannot be null"); -+ return command -> { -+ Validate.notNull(command, "Command cannot be null"); -+ this.runTask(plugin, command); -+ }; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch b/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch deleted file mode 100644 index 73c28af9be98..000000000000 --- a/Spigot-Server-Patches/0669-living-entity-allow-attribute-registration.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Sat, 24 Oct 2020 16:37:44 +0200 -Subject: [PATCH] living entity allow attribute registration - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -index 8f6b78c68da555f96033df567da581af52195e6c..e4cd1848e8700de4ab64f3037bb0c41d99e7c97d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Logger; - public class AttributeMapBase { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final Map b = Maps.newHashMap(); -+ private final Map b = Maps.newHashMap(); private final Map attributeMap = b; // Paper - OBFHELPER - private final Set c = Sets.newHashSet(); - private final AttributeProvider d; - -@@ -135,4 +135,12 @@ public class AttributeMapBase { - } - - } -+ -+ // Paper - start -+ public void registerAttribute(AttributeBase attributeBase) { -+ AttributeModifiable attributeModifiable = new AttributeModifiable(attributeBase, AttributeModifiable::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); -+ } -+ // Paper - end -+ - } -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 673948947bd918c1dbb6c4c99486b4200e3c09fe..2e83b8855070077e90e5ab2c4beae819c620e480 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -40,6 +40,14 @@ public class CraftAttributeMap implements Attributable { - return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ Preconditions.checkArgument(attribute != null, "attribute"); -+ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); -+ } -+ // Paper end -+ - public static AttributeBase toMinecraft(Attribute attribute) { - return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index e574e2453c7bc848168ff24372d6772bd423b672..3d497f69f89455b88fba423de8effb3db83e7af4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -675,6 +675,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().craftAttributes.getAttribute(attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ getHandle().craftAttributes.registerAttribute(attribute); -+ } -+ // Paper end -+ - @Override - public void setAI(boolean ai) { - if (this.getHandle() instanceof EntityInsentient) { diff --git a/Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch b/Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch deleted file mode 100644 index 33f5d175815f..000000000000 --- a/Spigot-Server-Patches/0670-fix-dead-slime-setSize-invincibility.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 5 Feb 2021 22:12:13 +0100 -Subject: [PATCH] fix dead slime setSize invincibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index cf5c6030105e56813f526e710e5db0c59d88c99e..13ab1a430f9ad2ece73ab50455bfcddbc9b236e2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -18,7 +18,7 @@ public class CraftSlime extends CraftMob implements Slime { - - @Override - public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility - } - - @Override diff --git a/Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch b/Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch deleted file mode 100644 index f368eba1569d..000000000000 --- a/Spigot-Server-Patches/0671-Merchant-getRecipes-should-return-an-immutable-list.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Wed, 10 Feb 2021 14:53:36 -0800 -Subject: [PATCH] Merchant#getRecipes should return an immutable list - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -index 00d43e4a77ed03bc9672cbaccad50b48aed0fb93..3c66d9217eb0b60595a59e2f296de332095d4a4c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -@@ -25,7 +25,7 @@ public class CraftMerchant implements Merchant { - - @Override - public List getRecipes() { -- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { -+ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) - @Override - public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantRecipe recipe) { - return recipe.asBukkit(); diff --git a/Spigot-Server-Patches/0672-misc-debugging-dumps.patch b/Spigot-Server-Patches/0672-misc-debugging-dumps.patch deleted file mode 100644 index 5a0eca09e5cb..000000000000 --- a/Spigot-Server-Patches/0672-misc-debugging-dumps.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 18 Feb 2021 20:23:28 +0000 -Subject: [PATCH] misc debugging dumps - - -diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..2d5494d2813b773e60ddba6790b750a9a08f21f8 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TraceUtil.java -@@ -0,0 +1,18 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Bukkit; -+ -+public final class TraceUtil { -+ -+ public static void dumpTraceForThread(Thread thread, String reason) { -+ Bukkit.getLogger().warning(thread.getName() + ": " + reason); -+ StackTraceElement[] trace = thread.getStackTrace(); -+ for (StackTraceElement traceElement : trace) { -+ Bukkit.getLogger().warning("\tat " + traceElement); -+ } -+ } -+ -+ public static void dumpTraceForThread(String reason) { -+ new Throwable(reason).printStackTrace(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 952d5c7c3324377e0036b9d7e524484cb581e5b2..a116156236caa22d3ee13b5a56f4ed3c8d013f37 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper - import io.papermc.paper.event.entity.EntityMoveEvent; -+import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -856,6 +857,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sat, 20 Feb 2021 13:09:59 -0500 -Subject: [PATCH] Add support for hex color codes in console - -Converts upstream's hex color code legacy format into actual hex color codes in the console. - -diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -@@ -0,0 +1,178 @@ -+package io.papermc.paper.console; -+ -+import net.minecrell.terminalconsole.TerminalConsoleAppender; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.config.Configuration; -+import org.apache.logging.log4j.core.config.plugins.Plugin; -+import org.apache.logging.log4j.core.layout.PatternLayout; -+import org.apache.logging.log4j.core.pattern.*; -+import org.apache.logging.log4j.util.PerformanceSensitive; -+import org.apache.logging.log4j.util.PropertiesUtil; -+ -+import java.util.List; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; -+ -+/** -+ * Modified version of -+ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. -+ */ -+@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) -+@ConverterKeys({ "paperMinecraftFormatting" }) -+@PerformanceSensitive("allocation") -+public final class HexFormattingConverter extends LogEventPatternConverter { -+ -+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); -+ -+ private static final String ANSI_RESET = "\u001B[m"; -+ -+ private static final char COLOR_CHAR = '§'; -+ private static final String LOOKUP = "0123456789abcdefklmnor"; -+ -+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; -+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); -+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); -+ -+ private static final String[] ansiCodes = new String[] { -+ "\u001B[0;30m", // Black §0 -+ "\u001B[0;34m", // Dark Blue §1 -+ "\u001B[0;32m", // Dark Green §2 -+ "\u001B[0;36m", // Dark Aqua §3 -+ "\u001B[0;31m", // Dark Red §4 -+ "\u001B[0;35m", // Dark Purple §5 -+ "\u001B[0;33m", // Gold §6 -+ "\u001B[0;37m", // Gray §7 -+ "\u001B[0;30;1m", // Dark Gray §8 -+ "\u001B[0;34;1m", // Blue §9 -+ "\u001B[0;32;1m", // Green §a -+ "\u001B[0;36;1m", // Aqua §b -+ "\u001B[0;31;1m", // Red §c -+ "\u001B[0;35;1m", // Light Purple §d -+ "\u001B[0;33;1m", // Yellow §e -+ "\u001B[0;37;1m", // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[21m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ -+ private final boolean ansi; -+ private final List formatters; -+ -+ /** -+ * Construct the converter. -+ * -+ * @param formatters The pattern formatters to generate the text to manipulate -+ * @param strip If true, the converter will strip all formatting codes -+ */ -+ protected HexFormattingConverter(List formatters, boolean strip) { -+ super("paperMinecraftFormatting", null); -+ this.formatters = formatters; -+ this.ansi = !strip; -+ } -+ -+ @Override -+ public void format(LogEvent event, StringBuilder toAppendTo) { -+ int start = toAppendTo.length(); -+ //noinspection ForLoopReplaceableByForEach -+ for (int i = 0, size = formatters.size(); i < size; i++) { -+ formatters.get(i).format(event, toAppendTo); -+ } -+ -+ if (KEEP_FORMATTING || toAppendTo.length() == start) { -+ // Skip replacement if disabled or if the content is empty -+ return; -+ } -+ -+ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); -+ String content = toAppendTo.substring(start); -+ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); -+ format(content, toAppendTo, start, useAnsi); -+ } -+ -+ private static String convertRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); -+ int hex = Integer.decode(s); -+ int red = (hex >> 16) & 0xFF; -+ int green = (hex >> 8) & 0xFF; -+ int blue = hex & 0xFF; -+ String replacement = String.format(RGB_ANSI, red, green, blue); -+ matcher.appendReplacement(buffer, replacement); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ private static String stripRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ matcher.appendReplacement(buffer, ""); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ static void format(String content, StringBuilder result, int start, boolean ansi) { -+ int next = content.indexOf(COLOR_CHAR); -+ int last = content.length() - 1; -+ if (next == -1 || next == last) { -+ result.setLength(start); -+ result.append(content); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ return; -+ } -+ -+ Matcher matcher = NAMED_PATTERN.matcher(content); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); -+ if (format != -1) { -+ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); -+ } -+ } -+ matcher.appendTail(buffer); -+ -+ result.setLength(start); -+ result.append(buffer.toString()); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ } -+ -+ /** -+ * Gets a new instance of the {@link HexFormattingConverter} with the -+ * specified options. -+ * -+ * @param config The current configuration -+ * @param options The pattern options -+ * @return The new instance -+ * -+ * @see HexFormattingConverter -+ */ -+ public static HexFormattingConverter newInstance(Configuration config, String[] options) { -+ if (options.length < 1 || options.length > 2) { -+ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); -+ return null; -+ } -+ if (options[0] == null) { -+ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); -+ return null; -+ } -+ -+ PatternParser parser = PatternLayout.createPatternParser(config); -+ List formatters = parser.parse(options[0]); -+ boolean strip = options.length > 1 && "strip".equals(options[1]); -+ return new HexFormattingConverter(formatters, strip); -+ } -+ -+} -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 8af159abd3d0cc94cf155fec5b384c42f69551bf..67da1aa7a21622fb231d19dede3775a282a4a12e 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -6,21 +6,21 @@ - - - -- -+ - - - -+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> - - - - - -- -+ - - - -+ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> - - - diff --git a/Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch b/Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch deleted file mode 100644 index 5f1ef784b97c..000000000000 --- a/Spigot-Server-Patches/0674-Clear-SyncLoadInfo.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:10:53 -0600 -Subject: [PATCH] Clear SyncLoadInfo - -This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 4b3efe01750d79bcc27a42b5a145d9aa6b124d18..12313a37ceeb6a0b6a539c38fdba67e5e43d7413 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -295,6 +295,13 @@ public class PaperCommand extends Command { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); - return; - } -+ -+ if (args.length > 1 && args[1].equals("clear")) { -+ SyncLoadFinder.clear(); -+ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); -+ return; -+ } -+ - File file = new File(new File(new File("."), "debug"), - "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); - file.getParentFile().mkdirs(); -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -index d381f91cf105bfc01846ada90da8971a3618e784..c51401bcfac0a1e45099af1dd355073c19790476 100644 ---- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -26,6 +26,10 @@ public class SyncLoadFinder { - public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); - } - -+ public static void clear() { -+ SYNC_LOADS.clear(); -+ } -+ - public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { - if (!ENABLED) { - return; diff --git a/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch b/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch deleted file mode 100644 index 5bb7b3c9efa4..000000000000 --- a/Spigot-Server-Patches/0675-Expose-Tracked-Players.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f7223f214f911dd25abcf3a52745588ec630241d..7abeeefeb579a43bc9ee85fd4150afacfb11c802 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -172,7 +172,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -- PlayerChunkMap.EntityTracker tracker; // Paper -+ public PlayerChunkMap.EntityTracker tracker; // Paper package private -> public - public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e81de526a847c730abf86016354c1dc57780ec8b..05248f560d643080a3eac581c01aa89fb3709e6c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -16,6 +16,7 @@ import java.net.InetSocketAddress; - import java.net.SocketAddress; - import java.util.ArrayList; - import java.util.Collection; -+import java.util.Collections; // Paper - import java.util.HashMap; - import java.util.HashSet; - import java.util.LinkedHashMap; -@@ -2309,6 +2310,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - // Paper end - -+ // Paper start -+ @Override -+ public Set getTrackedPlayers() { -+ if (entity.tracker == null) { -+ return Collections.emptySet(); -+ } -+ -+ Set set = new HashSet<>(entity.tracker.trackedPlayers.size()); -+ for (EntityPlayer entityPlayer : entity.tracker.trackedPlayers) { -+ set.add(entityPlayer.getBukkitEntity().getPlayer()); -+ } -+ return set; -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { diff --git a/Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch b/Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch deleted file mode 100644 index d5ee1c60ca88..000000000000 --- a/Spigot-Server-Patches/0676-Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Bjarne Koll -Date: Wed, 3 Mar 2021 12:48:48 +0100 -Subject: [PATCH] Remove streams from SensorNearest - -The behavioural nearby sensors are validated every tick on the entities -that registered the respective sensors and are therefore a good subject -to performance improvements. - -More specifically this commit replaces the Stream#filter usage with -ArrayList#removeIf as the removeIf method on an array list is heavily -optimized towards a single internal array re-allocation without any -further overhead on the removeIf call. - -The only negative of this change is the rather agressive diff these -patches introduce as the methods are basically being reimplemented -compared to the previous stream-based implementation. - -See: https://nipafx.dev/java-stream-performance/ - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -index 418cd6d8b40d35aa3be73eb12f2e3b75597238b9..2e3149a0b15299468079796bd3ea56eabdb4998c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -@@ -27,18 +27,16 @@ public class SensorNearestItems extends Sensor { - List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { - return true; - }); -- -- entityinsentient.getClass(); -+ // Paper start - remove streams in favour of lists - list.sort(Comparator.comparingDouble(entityinsentient::h)); -- Stream stream = list.stream().filter((entityitem) -> { -- return entityinsentient.i(entityitem.getItemStack()); -- }).filter((entityitem) -> { -- return entityitem.a((Entity) entityinsentient, 9.0D); -- }); -- -- entityinsentient.getClass(); -- Optional optional = stream.filter(entityinsentient::hasLineOfSight).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ EntityItem nearest = null; -+ for (EntityItem entityItem : list) { -+ if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -index d3bb1c02d80fcd3586030b07f84e7ebdd97d873e..0bc17d148e91277efdf72541e5470fa56d455670 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -@@ -26,10 +26,12 @@ public class SensorNearestLivingEntities extends Sensor { - list.sort(Comparator.comparingDouble(entityliving::h)); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); - -- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { -- return a(entityliving, entityliving1); -- }).collect(Collectors.toList())); -+ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -+ // Paper start - remove streams in favour of lists -+ List visibleMobs = new java.util.ArrayList<>(list); -+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -index 29abc7feec5358dce7d16958f0c5807f4bda992f..60e4da9217d4d950b5077baf6b50eaee20f8df09 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -@@ -26,22 +26,26 @@ public class SensorNearestPlayers extends Sensor { - - @Override - protected void a(WorldServer worldserver, EntityLiving entityliving) { -- Stream stream = worldserver.getPlayers().stream().filter(IEntitySelector.g).filter((entityplayer) -> { -- return entityliving.a((Entity) entityplayer, 16.0D); -- }); -+ // Paper start - remove streams in favour of lists -+ List players = new java.util.ArrayList<>(worldserver.getPlayers()); -+ players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -+ players.sort(Comparator.comparingDouble(entityliving::h)); - -- entityliving.getClass(); -- List list = (List) stream.sorted(Comparator.comparingDouble(entityliving::h)).collect(Collectors.toList()); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); -- List list1 = (List) list.stream().filter((entityhuman) -> { -- return a(entityliving, (EntityLiving) entityhuman); -- }).collect(Collectors.toList()); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (EntityHuman) list1.get(0))); -- Optional optional = list1.stream().filter(IEntitySelector.f).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ EntityHuman nearest = null, nearestTargetable = null; -+ for (EntityHuman player : players) { -+ if (Sensor.a(entityliving, player)) { -+ if (nearest == null) nearest = player; -+ if (IEntitySelector.canAITarget().test(player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch b/Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch deleted file mode 100644 index cb25f2f52734..000000000000 --- a/Spigot-Server-Patches/0677-do-not-create-unnecessary-copies-of-passenger-list.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Sun, 13 Dec 2020 13:42:55 +0100 -Subject: [PATCH] do not create unnecessary copies of passenger list - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -index edc6fff87c4abad2c123b1a46d6e5b792602b3be..5e739b26b6b5490b2c7651d3e9ff8649e776137e 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -@@ -15,7 +15,7 @@ public class PacketPlayOutMount implements Packet { - - public PacketPlayOutMount(Entity entity) { - this.a = entity.getId(); -- List list = entity.getPassengers(); -+ List list = entity.passengers; // Paper - do not create a copy of the list - - this.b = new int[list.size()]; - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 58dd349adf2bc9bac6569464ef7a7aec81729e79..1df8fb8cb3fcf8201e1c5fa8ca13f7a9c632c379 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -103,10 +103,10 @@ public class EntityTrackerEntry { - - public final void tick() { this.a(); } // Paper - OBFHELPER - public void a() { -- List list = this.tracker.getPassengers(); -+ List list = this.tracker.passengers; // Paper - do not copy list - - if (!list.equals(this.p)) { -- this.p = list; -+ this.p = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed - this.broadcastIncludingSelf(new PacketPlayOutMount(this.tracker)); // CraftBukkit - } - -@@ -376,7 +376,7 @@ public class EntityTrackerEntry { - } - } - -- if (!this.tracker.getPassengers().isEmpty()) { -+ if (!this.tracker.passengers.isEmpty()) { // Paper - do not create copy of list - consumer.accept(new PacketPlayOutMount(this.tracker)); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 169fa174f86f8a8dc42d3b9c4954a39d0a738c06..6835401bd7863bbd655502547a9fd4ae0f298da1 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -2315,7 +2315,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - list.add(entity); - } - -- if (!entity.getPassengers().isEmpty()) { -+ if (!entity.passengers.isEmpty()) { // Paper - do not copy list - list1.add(entity); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7abeeefeb579a43bc9ee85fd4150afacfb11c802..429f0591c6a55f6c5d08a0755f7d39da676468bc 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2230,7 +2230,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 1; -+ return this.passengers.size() < 1; // Paper - do not copy list - } - - public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER -@@ -2326,7 +2326,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isVehicle() { -- return !this.getPassengers().isEmpty(); -+ return !this.passengers.isEmpty(); // Paper - do not copy list - } - - public boolean bt() { -@@ -3138,7 +3138,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean w(Entity entity) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity1; - -@@ -3154,7 +3154,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean a(Class oclass) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity; - -@@ -3171,7 +3171,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public Collection getAllPassengers() { - Set set = Sets.newHashSet(); -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -3197,7 +3197,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private void a(boolean flag, Set set) { - Entity entity; - -- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.a(flag, set)) { -+ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.a(flag, set)) { // Paper - do not copy list - entity = (Entity) iterator.next(); - if (!flag || EntityPlayer.class.isAssignableFrom(entity.getClass())) { - set.add(entity); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -index ec51a5532576ce25465bacf61c716ddaffca514e..d285f5aa66fa81a2f56920c05afb4506cb82fa54 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -@@ -52,7 +52,7 @@ public class PathfinderGoalTame extends PathfinderGoal { - @Override - public void e() { - if (!this.entity.isTamed() && this.entity.getRandom().nextInt(50) == 0) { -- Entity entity = (Entity) this.entity.getPassengers().get(0); -+ Entity entity = this.entity.passengers.isEmpty() ? null : this.entity.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well - - if (entity == null) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index d6e1697f64e60f2a567288c604a1690159955f37..676ca381a5e111fc15f319e73504e4e60dbf0d2b 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -86,7 +86,7 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index d678e3164ecdb7f0c600597bcb39d1054dfbc4b2..1e41c45af6dbcf097d7d6104e63db637f199301a 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -972,7 +972,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -index 7781386da593a1c4f3ad7e7e8761767dda7cb66c..16d5cae64887b82e67eeb61ccb714e6125ff0c09 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -@@ -134,7 +134,7 @@ public class EntityRavager extends EntityRaider { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 069076d3c7165440217a7632b089ab2aa0fbdb1d..5e2c13bd6e52ffe182ef034e05ba6fe1cb301005 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -317,7 +317,7 @@ public class EntityBoat extends Entity { - super.tick(); - this.r(); - if (this.cs()) { -- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof EntityHuman)) { -+ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof EntityHuman)) { // Paper - do not copy list - this.a(false, false); - } - -@@ -380,7 +380,7 @@ public class EntityBoat extends Entity { - Entity entity = (Entity) list.get(j); - - if (!entity.w(this)) { -- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { -+ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { // Paper - do not copy passenger list - entity.startRiding(this); - } else { - this.collide(entity); -@@ -727,8 +727,8 @@ public class EntityBoat extends Entity { - float f = 0.0F; - float f1 = (float) ((this.dead ? 0.009999999776482582D : this.bc()) + entity.bb()); - -- if (this.getPassengers().size() > 1) { -- int i = this.getPassengers().indexOf(entity); -+ if (this.passengers.size() > 1) { // Paper - do not copy list -+ int i = this.passengers.indexOf(entity); // Paper - do not copy list - - if (i == 0) { - f = 0.2F; -@@ -747,7 +747,7 @@ public class EntityBoat extends Entity { - entity.yaw += this.ak; - entity.setHeadRotation(entity.getHeadRotation() + this.ak); - this.a(entity); -- if (entity instanceof EntityAnimal && this.getPassengers().size() > 1) { -+ if (entity instanceof EntityAnimal && this.passengers.size() > 1) { // Paper - do not copy list - int j = entity.getId() % 2 == 0 ? 90 : 270; - - entity.n(((EntityAnimal) entity).aA + (float) j); -@@ -907,13 +907,13 @@ public class EntityBoat extends Entity { - - @Override - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 2 && !this.a((Tag) TagsFluid.WATER); -+ return this.passengers.size() < 2 && !this.a((Tag) TagsFluid.WATER); // Paper - do not copy list - } - - @Nullable - @Override - public Entity getRidingPassenger() { -- List list = this.getPassengers(); -+ List list = this.passengers; // Paper - do not copy list - - return list.isEmpty() ? null : (Entity) list.get(0); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 57821301ef031995e6044a17b46c70a693322455..75a88ab5d5b0fdb98ea8d61bb6b82049b21101f3 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -561,7 +561,7 @@ public abstract class EntityMinecartAbstract extends Entity { - - vec3d1 = new Vec3D(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); - this.setMot(vec3d1); -- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - - if (entity instanceof EntityHuman) { - Vec3D vec3d2 = entity.getMot(); diff --git a/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch b/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch deleted file mode 100644 index 53f85dfd860b..000000000000 --- a/Spigot-Server-Patches/0678-MC-29274-Fix-Wither-hostility-towards-players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheShermanTanker -Date: Thu, 1 Oct 2020 01:11:03 +0800 -Subject: [PATCH] MC-29274: Fix Wither hostility towards players - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d2f6e1308a4dfec663770e2c7f4de0cf22402a97..3e6132211912d29e34c94042b0819f11a3bd123e 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -804,4 +804,10 @@ public class PaperWorldConfig { - private void setUpdatePathfindingOnBlockUpdate() { - updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); - } -+ -+ public boolean fixWitherTargetingBug = false; -+ private void witherSettings() { -+ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); -+ log("Withers properly target players: " + fixWitherTargetingBug); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 891905712903bf3ba241187791cfa995375430d5..229eabe0510e6c3660236ed0fb3e80d41074642c 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -104,6 +104,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); -+ if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); - } - diff --git a/Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch b/Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch deleted file mode 100644 index a65efb398f2a..000000000000 --- a/Spigot-Server-Patches/0679-Throw-proper-exception-on-empty-JsonList-file.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 1 Nov 2020 16:43:11 +0100 -Subject: [PATCH] Throw proper exception on empty JsonList file - - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index cd35b833d3047a38be980ee550641e87bd3b9b01..c960852dc60d0598012c5eef0d139fe38bde63fb 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -189,6 +189,7 @@ public abstract class JsonList> { - - try { - JsonArray jsonarray = (JsonArray) JsonList.b.fromJson(bufferedreader, JsonArray.class); -+ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.c.getName() + "\" is either empty or corrupt"); // Paper - - this.d.clear(); - Iterator iterator = jsonarray.iterator(); diff --git a/Spigot-Server-Patches/0680-Improve-ServerGUI.patch b/Spigot-Server-Patches/0680-Improve-ServerGUI.patch deleted file mode 100644 index ae8862a977cc..000000000000 --- a/Spigot-Server-Patches/0680-Improve-ServerGUI.patch +++ /dev/null @@ -1,400 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> -Date: Sat, 3 Oct 2020 08:27:40 +0200 -Subject: [PATCH] Improve ServerGUI - -- Added logo to server frame -- Show tps in the server stats - -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -index 67d064e3959ed8d886df30ce9d97f86c2443fa39..dc6bc1910ad0f9b27144d5750078c3ca607d03d3 100644 ---- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -57,9 +57,18 @@ public class RAMDetails extends JList { - public void update() { - GraphData data = RAMGraph.DATA.peekLast(); - Vector vector = new Vector<>(); -+ -+ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); - vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); - vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); -+ - setListData(vector); - } - -@@ -70,4 +79,9 @@ public class RAMDetails extends JList { - } - return ((double) total / (double) tickTimes.length) * 1.0E-6D; - } -+ -+ private static String format(double tps) -+ { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ } - } -diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -index f85a4079bb2931fd29a526379ba350eb7e8ae636..79cc587d8ad9f576f9e4478a41baabcaf690c568 100644 ---- a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -@@ -18,7 +18,7 @@ public class GuiStatsComponent extends JComponent { - }); - private final int[] b = new int[256]; - private int c; -- private final String[] d = new String[11]; -+ private final String[] d = new String[12]; public String[] getStatEntries() { return this.d; } // Paper - change size, OBFHELPER - private final MinecraftServer e; - private final Timer f; - -@@ -37,8 +37,18 @@ public class GuiStatsComponent extends JComponent { - private void b() { - long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - -+ // Paper start - Add tps entry -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - this.d[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; - this.d[1] = "Avg tick: " + GuiStatsComponent.a.format(this.a(this.e.h) * 1.0E-6D) + " ms"; -+ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); -+ // Paper end -+ - this.b[this.c++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); - this.repaint(); - } -@@ -85,4 +95,10 @@ public class GuiStatsComponent extends JComponent { - public void a() { - this.f.stop(); - } -+ -+ // Paper - start Add tps entry -+ private static String format(double tps) { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index c2c075b9e3b70f863b6c450e4f31d6fde2935be6..d1d98c2f192514a3f511bebb00c088b03e6be84c 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -31,6 +31,11 @@ import net.minecraft.DefaultUncaughtExceptionHandler; - import net.minecraft.server.dedicated.DedicatedServer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+// Paper start -+import java.io.IOException; -+import java.util.Objects; -+import javax.imageio.ImageIO; -+// Paper end - - public class ServerGUI extends JComponent { - -@@ -56,6 +61,15 @@ public class ServerGUI extends JComponent { - jframe.pack(); - jframe.setLocationRelativeTo((Component) null); - jframe.setVisible(true); -+ jframe.setName("Minecraft server"); // Paper -+ -+ // Paper start - Add logo as frame image -+ try { -+ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(ServerGUI.class.getClassLoader().getResourceAsStream("logo.png")))); -+ } catch (IOException ignore) { -+ } -+ // Paper end -+ - jframe.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowevent) { - if (!servergui.f.getAndSet(true)) { -diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -new file mode 100644 -index 0000000000000000000000000000000000000000..a7d785f60c884ee4ee487cc364402d66c3dc2ecc -GIT binary patch -literal 14310 -zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c -zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 -z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez -za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ -zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc -zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 -z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C -z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj -z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO -zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq -zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP -zJxwXvt5fFTCOVgB)Zq -z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( -z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 -zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP -zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN -zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| -z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK -z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf -zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l -z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP -zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 -z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! -zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! -zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX -z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A -z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# -zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x -zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 -zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk -z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B -zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| -zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx -z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE -zllqxy -z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t -z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W -z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); -zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} -z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX -z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx -z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% -zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v -zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< -zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A -zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h -zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- -zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< -zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS -z4&$M&7(|(9nWY%QShCnuN0 -z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm -zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ -z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 -zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; -z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; -z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC -z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> -zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg -zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> -zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k -zL^tBOHF^=)k&U-Tw{gfijqQ&^ -z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 -z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X -z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 -zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( -zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY -zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU -zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ -z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ -z1IGS^Z5t=0Zj86J2MfJc -zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 -z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 -z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf -zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) -z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd -z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= -z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 -z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 -zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA -zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH -zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ -z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< -zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ -zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf -zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- -zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= -zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G -z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp -zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x -zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 -z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN -zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl -z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh -zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; -z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ -zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK -zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! -zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ -z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X -zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* -zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 -zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH -z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw -z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G -z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv -zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L -z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H -zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% -zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz -z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| -zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP -zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 -zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty -zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n -z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 -zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo -zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF -zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V -zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% -zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W -z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 -zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy -zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 -z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 -zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd -zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m -z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I -z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe -zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA -zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` -zh~ggr^knneWU!Nn}AQt=0Id6Hk; -z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# -zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 -z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< -zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r -z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN -zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D -z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk -zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq -z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ -z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ -zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl -zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH -z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif -z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) -zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf -zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m -zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< -zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I -z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 -zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} -zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` - -literal 0 -HcmV?d00001 - diff --git a/Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch deleted file mode 100644 index 852ff8decbca..000000000000 --- a/Spigot-Server-Patches/0681-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 2 Feb 2021 09:17:59 +0100 -Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored - entities - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -index 4c4c8b23c39d26c646b1950023a20446ac798c6f..fba720bf2349a69d0f93642eea4e77063f83380c 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -@@ -82,6 +82,7 @@ public class BlockPressurePlateBinary extends BlockPressurePlateAbstract { - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -+ if (entity.isIgnoreBlockTrigger()) continue; // Paper - don't call event for ignored entities - - // CraftBukkit start - Call interact event when turning on a pressure plate - if (this.getPower(world.getType(blockposition)) == 0) { diff --git a/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch b/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch deleted file mode 100644 index 8ef92016d7b7..000000000000 --- a/Spigot-Server-Patches/0682-fix-converting-txt-to-json-file.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:49:15 -0800 -Subject: [PATCH] fix converting txt to json file - - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -index b13e6f9923a9c5703f4eaeab2d0c112e4726b496..a762cf4c4a52bcbc8dbfd60b3ad7fef5489ba5c5 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -@@ -18,6 +18,11 @@ public class DedicatedPlayerList extends PlayerList { - - this.a(dedicatedserverproperties.viewDistance); - super.setHasWhitelist((Boolean) dedicatedserverproperties.whiteList.get()); -+ // Paper start - moved from constructor -+ } -+ @Override -+ public void loadAndSaveFiles() { -+ // Paper end - this.y(); - this.w(); - this.x(); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index c4df472050622eb2469b2ddb4d2ed917994f6e95..52bb528e75eb43156ee2bf19877bc051a35bb6e3 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -198,6 +198,12 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start - moved up to right after PlayerList creation but before file load/save -+ if (this.convertNames()) { -+ this.getUserCache().save(false); // Paper -+ } -+ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames -+ // Paper end - // Paper start - try { - com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -@@ -260,10 +266,6 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); - } - -- if (this.convertNames()) { -- this.getUserCache().b(false); // Paper -- } -- - if (!NameReferencingFileConverter.e(this)) { - return false; - } else { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 1358993217e601e3bab6e0a4e8c55d555865a13e..484c7cea458dda38e4816fe5f1c05c6836fa38b9 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -175,6 +175,7 @@ public abstract class PlayerList { - this.maxPlayers = i; - this.playerFileData = worldnbtstorage; - } -+ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { - EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 692d95c94df85d752a3ddc66e1f2af765565b160..c617b7dd5a992770fc87113987807947ae68be81 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -243,6 +243,7 @@ public class UserCache { - return arraylist; - } - -+ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER - public void b(boolean asyncSave) { // Paper - JsonArray jsonarray = new JsonArray(); - DateFormat dateformat = e(); diff --git a/Spigot-Server-Patches/0683-Add-worldborder-events.patch b/Spigot-Server-Patches/0683-Add-worldborder-events.patch deleted file mode 100644 index 49bf0c1ca5a4..000000000000 --- a/Spigot-Server-Patches/0683-Add-worldborder-events.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 22:40:34 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index bedaa9dd6390e81df5872c2dd6e202a038367bf6..3c25021835d6d8fd112fc89636616bfd744e7f1a 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -14,6 +14,9 @@ import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.shapes.OperatorBoolean; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapes; -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper - - public class WorldBorder { - -@@ -102,15 +105,19 @@ public class WorldBorder { - } - - public void setCenter(double d0, double d1) { -- this.g = d0; -- this.h = d1; -+ // Paper start -+ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), d0, 0, d1)); -+ if (!event.callEvent()) return; -+ this.g = event.getNewCenter().getX(); -+ this.h = event.getNewCenter().getZ(); -+ // Paper end - this.j.k(); - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1); -+ iworldborderlistener.a(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper - } - - } -@@ -128,25 +135,43 @@ public class WorldBorder { - } - - public void setSize(double d0) { -- this.j = new WorldBorder.d(d0); -+ // Paper start -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), d0, 0); -+ if (!event.callEvent()) return; -+ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition -+ transitionSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); -+ return; -+ } -+ this.j = new WorldBorder.d(event.getNewSize()); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0); -+ iworldborderlistener.a(this, event.getNewSize()); // Paper - } - - } - - public void transitionSizeBetween(double d0, double d1, long i) { -- this.j = (WorldBorder.a) (d0 == d1 ? new WorldBorder.d(d1) : new WorldBorder.b(d0, d1, i)); -+ // Paper start -+ WorldBorderBoundsChangeEvent.Type type; -+ if (d0 == d1) { // new size = old size -+ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. -+ } else { -+ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; -+ } -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, d0, d1, i); -+ if (!event.callEvent()) return; -+ this.j = (WorldBorder.a) (d0 == event.getNewSize() ? new WorldBorder.d(event.getNewSize()) : new WorldBorder.b(d0, event.getNewSize(), event.getDuration())); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1, i); -+ iworldborderlistener.a(this, d0, event.getNewSize(), event.getDuration()); // Paper - } - - } -@@ -434,11 +459,11 @@ public class WorldBorder { - - class b implements WorldBorder.a { - -- private final double b; -- private final double c; -+ private final double b; public final double getOldSize() { return this.b; } // Paper - OBFHELPER -+ private final double c; public final double getNewSize() { return this.c; } // Paper - OBFHELPER - private final long d; - private final long e; -- private final double f; -+ private final double f; public final double getDuration() { return this.f; } // Paper - OBFHELPER - - private b(double d0, double d1, long i) { - this.b = d0; -@@ -493,6 +518,7 @@ public class WorldBorder { - - @Override - public WorldBorder.a l() { -+ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper - return (WorldBorder.a) (this.g() <= 0L ? WorldBorder.this.new d(this.c) : this); - } - -@@ -514,6 +540,7 @@ public class WorldBorder { - - double e(); - -+ default long getLerpTimeRemaining() { return g(); } // Paper - OBFHELPER - long g(); - - double h(); diff --git a/Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch b/Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch deleted file mode 100644 index c4ab87d78921..000000000000 --- a/Spigot-Server-Patches/0684-added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:33:54 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemNameTag.java b/src/main/java/net/minecraft/world/item/ItemNameTag.java -index 140a865f4f8fb3e4f787cf8d334d20fac6cb5eef..b9b2b27e534ba87a1aae3c521f393a066a18a199 100644 ---- a/src/main/java/net/minecraft/world/item/ItemNameTag.java -+++ b/src/main/java/net/minecraft/world/item/ItemNameTag.java -@@ -1,11 +1,17 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - -+// Paper start -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.event.player.PlayerNameEntityEvent; -+// Paper end -+ - public class ItemNameTag extends Item { - - public ItemNameTag(Item.Info item_info) { -@@ -16,11 +22,15 @@ public class ItemNameTag extends Item { - public EnumInteractionResult a(ItemStack itemstack, EntityHuman entityhuman, EntityLiving entityliving, EnumHand enumhand) { - if (itemstack.hasName() && !(entityliving instanceof EntityHuman)) { - if (!entityhuman.world.isClientSide && entityliving.isAlive()) { -- entityliving.setCustomName(itemstack.getName()); -- if (entityliving instanceof EntityInsentient) { -- ((EntityInsentient) entityliving).setPersistent(); -+ // Paper start -+ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((EntityPlayer) entityhuman).getBukkitEntity(), entityliving.getBukkitLivingEntity(), PaperAdventure.asAdventure(itemstack.getName()), true); -+ if (!event.callEvent()) return EnumInteractionResult.PASS; -+ EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); -+ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); -+ if (event.isPersistent() && newEntityLiving instanceof EntityInsentient) { -+ ((EntityInsentient) newEntityLiving).setPersistent(); - } -- -+ // Paper end - itemstack.subtract(1); - } - diff --git a/Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch b/Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch deleted file mode 100644 index 7eba41fbef91..000000000000 --- a/Spigot-Server-Patches/0685-Prevent-grindstones-from-overstacking-items.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 16 Feb 2021 21:37:51 -0600 -Subject: [PATCH] Prevent grindstones from overstacking items - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index 1d5dcbbd3870eb8e1013a97f6ce882bfc096bf95..a841c47c25287080738b04352ea4e8eaa77dacdd 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -196,13 +196,13 @@ public class ContainerGrindstone extends Container { - i = Math.max(item.getMaxDurability() - l, 0); - itemstack2 = this.b(itemstack, itemstack1); - if (!itemstack2.e()) { -- if (!ItemStack.matches(itemstack, itemstack1)) { -+ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check - this.resultInventory.setItem(0, ItemStack.b); - this.c(); - return; - } - -- b0 = 2; -+ b0 = 2; // Paper - the problem line for above change, causing over-stacking - } - } else { - boolean flag3 = !itemstack.isEmpty(); diff --git a/Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch b/Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch deleted file mode 100644 index 41d4ad446076..000000000000 --- a/Spigot-Server-Patches/0686-Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:04:03 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index 62a19f39405cff27f34a3b98fb9310b1c9c27563..08759f461ec947c0d5655557f49d8717afee6f00 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -74,7 +74,10 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - - if (this.cookingTimes[i] >= this.cookingTotalTimes[i]) { - InventorySubcontainer inventorysubcontainer = new InventorySubcontainer(new ItemStack[]{itemstack}); -- ItemStack itemstack1 = (ItemStack) this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world).map((recipecampfire) -> { -+ // Paper start -+ Optional recipe = this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world); -+ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { -+ // Paper end - return recipecampfire.a(inventorysubcontainer); - }).orElse(itemstack); - BlockPosition blockposition = this.getPosition(); -@@ -83,7 +86,7 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result); -+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(RecipeCampfire::toBukkitRecipe).orElse(null)); // Paper - this.world.getServer().getPluginManager().callEvent(blockCookEvent); - - if (blockCookEvent.isCancelled()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 54316a8079b4331a48cac3c43f3f8c506a4af091..1997139fb87dc1947acfdf02e1f116577c3fa943 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -395,7 +395,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result); -+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper - this.world.getServer().getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { diff --git a/Spigot-Server-Patches/0687-Add-Block-isValidTool.patch b/Spigot-Server-Patches/0687-Add-Block-isValidTool.patch deleted file mode 100644 index 6cfa745ab376..000000000000 --- a/Spigot-Server-Patches/0687-Add-Block-isValidTool.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:31 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ed1c92d9f2770f7d0503c6facebc51ddcbdf75cf..0006b3cad5fe46e50b0efeae99102f9d80276d61 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -806,5 +806,9 @@ public class CraftBlock implements Block { - } - return speed; - } -+ -+ public boolean isValidTool(ItemStack itemStack) { -+ return getDrops(itemStack).size() != 0; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch b/Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch deleted file mode 100644 index 070f1d7f725e..000000000000 --- a/Spigot-Server-Patches/0688-Allow-using-signs-inside-spawn-protection.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anton Lindroth -Date: Wed, 15 Apr 2020 01:54:02 +0200 -Subject: [PATCH] Allow using signs inside spawn protection - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3e6132211912d29e34c94042b0819f11a3bd123e..921253a06daa414aed7dc6824effc65db09ea7a5 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -810,4 +810,9 @@ public class PaperWorldConfig { - fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); - log("Withers properly target players: " + fixWitherTargetingBug); - } -+ -+ public boolean allowUsingSignsInsideSpawnProtection = false; -+ private void allowUsingSignsInsideSpawnProtection() { -+ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 358d1095b219fce6b308ec0362f22db7cfc85251..c6a65467d2d096d471ce5c4d761dc69d60644b75 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -143,6 +143,7 @@ import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IWorldReader; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockSign; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityCommand; -@@ -1691,7 +1692,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { -- if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { -+ if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.a((EntityHuman) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getType(blockposition).getBlock() instanceof BlockSign))) { // Paper - // CraftBukkit start - Check if we can actually do something over this large a distance - // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 diff --git a/Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch b/Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch deleted file mode 100644 index 019f32e1dc45..000000000000 --- a/Spigot-Server-Patches/0689-Implement-Keyed-on-World.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:04 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/net/minecraft/core/IRegistry.java b/src/main/java/net/minecraft/core/IRegistry.java -index 3e9ebeffdf66f8a959630b344149d17137c6901c..4f04d8081912e0fe771f0db9e086c789328f246f 100644 ---- a/src/main/java/net/minecraft/core/IRegistry.java -+++ b/src/main/java/net/minecraft/core/IRegistry.java -@@ -130,7 +130,7 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - public static final ResourceKey> I = a("loot_function_type"); - public static final ResourceKey> J = a("loot_condition_type"); - public static final ResourceKey> K = a("dimension_type"); -- public static final ResourceKey> L = a("dimension"); -+ public static final ResourceKey> L = a("dimension"); public static final ResourceKey> getWorldRegistry() { return L; } // Paper - OBFHELPER - public static final ResourceKey> M = a("dimension"); - public static final IRegistry SOUND_EVENT = a(IRegistry.g, () -> { - return SoundEffects.ENTITY_ITEM_PICKUP; -@@ -339,9 +339,9 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - MinecraftKey minecraftkey = resourcekey.a(); - - IRegistry.a.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = IRegistry.e; -+ IRegistryWritable iregistrywritable = IRegistry.e; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); // Paper - decompile fix - } - - protected IRegistry(ResourceKey> resourcekey, Lifecycle lifecycle) { -@@ -428,11 +428,11 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, String s, T t0) { -- return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); // Paper - decompile fix - } - - static { -diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java -index 760579921927b4c8b0f20b2611b95fd626e4b27f..3075700dfa992da81b10246fcf7c7ad1115c4ba3 100644 ---- a/src/main/java/net/minecraft/resources/ResourceKey.java -+++ b/src/main/java/net/minecraft/resources/ResourceKey.java -@@ -12,6 +12,7 @@ public class ResourceKey { - private final MinecraftKey b; - private final MinecraftKey c; - -+ public static ResourceKey newResourceKey(ResourceKey> registryKey, MinecraftKey minecraftKey) { return a(registryKey, minecraftKey); } // Paper - OBFHELPER - public static ResourceKey a(ResourceKey> resourcekey, MinecraftKey minecraftkey) { - return a(resourcekey.c, minecraftkey); - } -@@ -41,6 +42,7 @@ public class ResourceKey { - return this.b.equals(resourcekey.a()); - } - -+ public MinecraftKey getLocation() { return a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e8305df0ce11bf7c297bf5f0acc95f07324e4143..6cc8eb04f42592aa12f76bb4a0a863ea509741b2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1161,7 +1161,7 @@ public final class CraftServer implements Server { - } else if (name.equals(levelName + "_the_end")) { - worldKey = net.minecraft.world.level.World.THE_END; - } else { -- worldKey = ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH))); -+ worldKey = ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), new net.minecraft.resources.MinecraftKey(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper - } - - WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, worldSession, worlddata, worldKey, dimensionmanager, getServer().worldLoadListenerFactory.create(11), -@@ -1253,6 +1253,15 @@ public final class CraftServer implements Server { - return null; - } - -+ // Paper start -+ @Override -+ public World getWorld(NamespacedKey worldKey) { -+ WorldServer worldServer = console.getWorldServer(ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); -+ if (worldServer == null) return null; -+ return worldServer.getWorld(); -+ } -+ // Paper end -+ - public void addWorld(World world) { - // Check if a World already exists with the UID. - if (getWorld(world.getUID()) != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 05a7f5f61330bd52705640345524cdedbf105285..a152d5bec8bf0dd87239b0a3432fb589cea61bd8 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2584,6 +2584,11 @@ public class CraftWorld implements World { - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } -+ -+ @Override -+ public org.bukkit.NamespacedKey getKey() { -+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.getDimensionKey().getLocation()); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch b/Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch deleted file mode 100644 index 65430ea1e74e..000000000000 --- a/Spigot-Server-Patches/0690-Add-fast-alternative-constructor-for-Vector3f.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Irmo van den Berge -Date: Wed, 10 Mar 2021 21:26:31 +0100 -Subject: [PATCH] Add fast alternative constructor for Vector3f - -Signed-off-by: Irmo van den Berge - -diff --git a/src/main/java/net/minecraft/core/Vector3f.java b/src/main/java/net/minecraft/core/Vector3f.java -index 93590ceb0bbe369a1bda987f0c4c21ea6a3b3a1a..da53e294fa5e28406b25614039db49b48c2dcdac 100644 ---- a/src/main/java/net/minecraft/core/Vector3f.java -+++ b/src/main/java/net/minecraft/core/Vector3f.java -@@ -19,6 +19,18 @@ public class Vector3f { - this(nbttaglist.i(0), nbttaglist.i(1), nbttaglist.i(2)); - } - -+ // Paper start - faster alternative constructor -+ private Vector3f(float x, float y, float z, Void dummy_var) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ } -+ -+ public static Vector3f createWithoutValidityChecks(float x, float y, float z) { -+ return new Vector3f(x, y, z, null); -+ } -+ // Paper end -+ - public NBTTagList a() { - NBTTagList nbttaglist = new NBTTagList(); - diff --git a/Spigot-Server-Patches/0691-Item-Rarity-API.patch b/Spigot-Server-Patches/0691-Item-Rarity-API.patch deleted file mode 100644 index d98d46c7edc6..000000000000 --- a/Spigot-Server-Patches/0691-Item-Rarity-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:42 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 467121839b94e09f59c64300de9f26d3c6caf1e5..f7758ee4aa8bbb31a80ec2e331b3fd3c55069808 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -45,7 +45,7 @@ public class Item implements IMaterial { - protected static final UUID g = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); - protected static final Random RANDOM = new Random(); - protected final CreativeModeTab i; -- private final EnumItemRarity a; -+ private final EnumItemRarity a; public final EnumItemRarity getItemRarity() { return a; } // Paper - OBFHELPER - private final int maxStackSize; - private final int durability; - private final boolean d; -@@ -209,6 +209,7 @@ public class Item implements IMaterial { - return itemstack.hasEnchantments(); - } - -+ public EnumItemRarity getItemStackRarity(ItemStack itemStack) { return i(itemStack); } // Paper - OBFHELPER - public EnumItemRarity i(ItemStack itemstack) { - if (!itemstack.hasEnchantments()) { - return this.a; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 848a704fa100c39098a5716bb25b6a9ed85d7a8c..de6a9d795ebaf9c608944415c7dc18c6aee23245 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -472,6 +472,20 @@ public final class CraftMagicNumbers implements UnsafeValues { - public int nextEntityId() { - return net.minecraft.world.entity.Entity.nextEntityId(); - } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { -+ Item item = getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); -+ } -+ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; -+ } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { -+ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch deleted file mode 100644 index 61d73b8e95e0..000000000000 --- a/Spigot-Server-Patches/0692-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Fri, 19 Mar 2021 16:07:21 -0700 -Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by - MobSpawnerTrader - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d..80c229c1852199fda85c03453d64cae33e413e89 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -319,6 +319,12 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - add consumer to modify entity before spawn -+ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); -+ } -+ @Nullable -+ public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { -+ // Paper end - // Paper start - Call PreCreatureSpawnEvent - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); - if (type != null) { -@@ -334,6 +340,7 @@ public class EntityTypes { - } - // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); -+ if (t0 != null && op != null) op.accept(t0); // Paper - - if (t0 != null) { - worldserver.addAllEntities(t0, spawnReason); -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 4f81a97b1451fec0bb5fd1479acad97846c40c7c..37e1b2bf33510c3603efadf219b462e667f573c2 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -62,7 +62,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.attachedToPlayer = true; -- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader -+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index e57938b4591bb103b9dd0d0145a62b5a901f2c63..7c8a2151be8a0f48cba1c15d231d5dbdb500b4d6 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -114,7 +114,7 @@ public class MobSpawnerTrader implements MobSpawner { - return false; - } - -- EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -+ EntityVillagerTrader entityvillagertrader = EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called - - if (entityvillagertrader != null) { - for (int i = 0; i < 2; ++i) { diff --git a/Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch b/Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch deleted file mode 100644 index 25bfef8508dc..000000000000 --- a/Spigot-Server-Patches/0693-copy-TESign-isEditable-from-snapshots.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 23 Mar 2021 06:43:30 +0000 -Subject: [PATCH] copy TESign#isEditable from snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index f4b601277ef75e5bc39d541a0d13c6eed3b1ef2c..f7e2e23e7468928b6bd6961f223c50ca2826a813 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -@@ -110,6 +110,7 @@ public class CraftSign extends CraftBlockEntityState implements - } - // Paper end - } -+ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually - } - - // Paper start diff --git a/Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch b/Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch deleted file mode 100644 index 06a6b95c91ef..000000000000 --- a/Spigot-Server-Patches/0694-Drop-carried-item-when-player-has-disconnected.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dmitry Sidorov -Date: Thu, 4 Feb 2021 20:32:01 +0300 -Subject: [PATCH] Drop carried item when player has disconnected - -Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. -Closes #5036 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 484c7cea458dda38e4816fe5f1c05c6836fa38b9..b257d58a298e82f255b09e9575ee42a56a4b7cee 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -79,6 +79,7 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; -@@ -609,6 +610,14 @@ public abstract class PlayerList { - } - // Paper end - -+ // Paper - Drop carried item when player has disconnected -+ if (!entityplayer.inventory.getCarried().isEmpty()) { -+ ItemStack carried = entityplayer.inventory.getCarried(); -+ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); -+ entityplayer.drop(carried, false); -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); diff --git a/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch b/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch deleted file mode 100644 index a47a8eb2e988..000000000000 --- a/Spigot-Server-Patches/0695-forced-whitelist-use-configurable-kick-message.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 09:24:23 +0100 -Subject: [PATCH] forced whitelist: use configurable kick message - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a116156236caa22d3ee13b5a56f4ed3c8d013f37..35bb4d0b9ed131e6570cce0b43ae78c5557a0bff 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2041,7 +2041,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 29 Mar 2021 09:07:25 +0200 -Subject: [PATCH] Make sure to remove correct TE during TE tick - -This looks like it can cause premature TE removal. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 78dcba08d6d796d5d97c8304bf1f1e7d1e650d5d..6581fe0d93a5c2e7b444a44c01726e02d4a28e63 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -895,7 +895,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - // Paper - prevent double chunk lookups - Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -- chunk.removeTileEntity(tileentity.getPosition()); -+ chunk.removeTileEntity(tileentity.getPosition(), tileentity); // Paper - remove correct TE - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 34a9f7b2f998f77b1279516cd09397ab6c2ac1cc..0727b12b5ff146b4efa9204bf4f495f2f1aa20b9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -819,10 +819,18 @@ public class Chunk implements IChunkAccess { - - @Override - public void removeTileEntity(BlockPosition blockposition) { -+ // Paper start - remove correct TE -+ removeTileEntity(blockposition, null); -+ } -+ public void removeTileEntity(BlockPosition blockposition, TileEntity match) { -+ // Paper end - if (this.loaded || this.world.s_()) { -- TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); -+ // Paper start -+ TileEntity tileentity = (TileEntity) this.tileEntities.get(blockposition); - -- if (tileentity != null) { -+ if (tileentity != null && (match == null || match == tileentity)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - tileentity.al_(); - } - } diff --git a/Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch deleted file mode 100644 index cc90371c8f68..000000000000 --- a/Spigot-Server-Patches/0697-Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Mon, 5 Apr 2021 18:35:15 -0700 -Subject: [PATCH] Don't ignore result of PlayerEditBookEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index c6a65467d2d096d471ce5c4d761dc69d60644b75..6ad075907d56a8f41ca3a7b82ff90a6d3ad9f1d4 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1146,7 +1146,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - list.stream().map(NBTTagString::a).forEach(nbttaglist::add); - ItemStack old = itemstack.cloneItemStack(); // CraftBukkit - itemstack.a("pages", (NBTBase) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -+ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) - } - } - diff --git a/Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch b/Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch deleted file mode 100644 index 099ef07a9797..000000000000 --- a/Spigot-Server-Patches/0698-fix-cancelling-block-falling-causing-client-desync.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 11:13:30 +0100 -Subject: [PATCH] fix cancelling block falling causing client desync - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 62d8b53c024888aa43b8fddf8a475dfb8284a4cc..2a61c24dd26edf4c72e977c6024fe233bab08a2f 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -14,6 +14,7 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.tags.TagsFluid; -@@ -43,6 +44,7 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class EntityFallingBlock extends Entity { -@@ -116,8 +118,18 @@ public class EntityFallingBlock extends Entity { - - if (this.ticksLived++ == 0) { - blockposition = this.getChunkCoordinates(); -- if (this.world.getType(blockposition).a(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -- this.world.a(blockposition, false); -+ // Paper start - fix cancelling block falling causing client desync -+ if (this.world.getType(blockposition).isSameInstance(block)) { -+ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -+ if (this.world.getType(blockposition).isSameInstance(block)) { //if listener didn't update the block -+ ((WorldServer) world).getChunkProvider().flagDirty(blockposition); -+ } -+ this.die(); -+ return; -+ } else { -+ this.world.setAir(blockposition, false); -+ } -+ // Paper end - fix cancelling block falling causing client desync - } else if (!this.world.isClientSide) { - this.die(); - return; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 3fdafc0ff0c4148ec844dbdc1455d17cdcb4a75a..0d26250887f80d0c250bcd6bc7de303362427d3e 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -683,6 +683,7 @@ public abstract class BlockBase { - return this.getBlock().a(tag) && predicate.test(this); - } - -+ public final boolean isSameInstance(Block block) { return a(block); } // Paper - OBFHELPER - public boolean a(Block block) { - return this.getBlock().a(block); - } diff --git a/Spigot-Server-Patches/0699-Expose-protocol-version.patch b/Spigot-Server-Patches/0699-Expose-protocol-version.patch deleted file mode 100644 index 529b85980437..000000000000 --- a/Spigot-Server-Patches/0699-Expose-protocol-version.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Fri, 26 Mar 2021 11:23:17 +0100 -Subject: [PATCH] Expose protocol version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index de6a9d795ebaf9c608944415c7dc18c6aee23245..697949abbe662a55fc31ad811863717e35b9d1b6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -486,6 +486,11 @@ public final class CraftMagicNumbers implements UnsafeValues { - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } -+ -+ @Override -+ public int getProtocolVersion() { -+ return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index fef6b7dd9350..000000000000 --- a/Spigot-Server-Patches/0700-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Thu, 1 Apr 2021 00:34:02 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 6ad075907d56a8f41ca3a7b82ff90a6d3ad9f1d4..db42f3b524adc4458c9c468b0299332e73a07a44 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -771,12 +771,11 @@ public class PlayerConnection implements PacketListenerPlayIn { - - // Paper start - async tab completion - com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); - String buffer = packetplayintabcomplete.c(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), - buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server - if (!event.isHandled()) { - if (!event.isCancelled()) { -@@ -795,10 +794,16 @@ public class PlayerConnection implements PacketListenerPlayIn { - }); - } - } else if (!completions.isEmpty()) { -- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); - -- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -- completions.forEach(builder::suggest); -+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(completion -> { -+ if (completion.tooltip() == null) { -+ builder.suggest(completion.suggestion()); -+ } else { -+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); -+ } -+ }); - com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); - com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); - suggestEvent.setCancelled(suggestions.isEmpty()); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index c5e00bd9e2790992202aadf8eec2002fc88c78f1..dd8e87ad192c19743577bb95253a127072ea196c 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -29,34 +29,56 @@ public class ConsoleCommandCompleter implements Completer { - final CraftServer server = this.server.server; - final String buffer = line.line(); - // Async Tab Complete -- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -- buffer, true, null); -+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = -+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - - if (event.isCancelled() || event.isHandled()) { - // Still fire sync event with the provided completions, if someone is listening - if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -- List finalCompletions = completions; -+ List finalCompletions = new java.util.ArrayList<>(completions); - Waitable> syncCompletions = new Waitable>() { - @Override - protected List evaluate() { -- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, -+ finalCompletions.stream() -+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) -+ .collect(java.util.stream.Collectors.toList())); - return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); - } - }; - server.getServer().processQueue.add(syncCompletions); - try { -- completions = syncCompletions.get(); -+ final List legacyCompletions = syncCompletions.get(); -+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed -+ // add any new suggestions -+ for (final String completion : legacyCompletions) { -+ if (notNewSuggestion(completions, completion)) { -+ continue; -+ } -+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); -+ } - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } - } - - if (!completions.isEmpty()) { -- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(new Candidate( -+ completion.suggestion(), -+ completion.suggestion(), -+ null, -+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), -+ null, -+ null, -+ false -+ )); -+ } - } - return; - } -@@ -106,4 +128,15 @@ public class ConsoleCommandCompleter implements Completer { - Thread.currentThread().interrupt(); - } - } -+ -+ // Paper start -+ private boolean notNewSuggestion(final List completions, final String completion) { -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { -+ if (it.suggestion().equals(completion)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch b/Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch deleted file mode 100644 index 5636a8b6e4c9..000000000000 --- a/Spigot-Server-Patches/0701-Enhance-console-tab-completions-for-brigadier-comman.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Tue, 30 Mar 2021 16:06:08 -0700 -Subject: [PATCH] Enhance console tab completions for brigadier commands - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index c56e7fb18f9a56c8025eb70a524f028b5942da37..efc1e42d606e1c9feb1a4871c0714933ae92a1b2 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -479,4 +479,11 @@ public class PaperConfig { - private static void fixEntityPositionDesync() { - fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); - } -+ -+ public static boolean enableBrigadierConsoleHighlighting = true; -+ public static boolean enableBrigadierConsoleCompletions = true; -+ private static void consoleSettings() { -+ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); -+ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index 89eeb9d202405747409e65fcf226d95379987e29..ad87b575a0261200b280884e054a59e3ce59c41c 100644 ---- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -1,5 +1,7 @@ - package com.destroystokyo.paper.console; - -+import com.destroystokyo.paper.PaperConfig; -+import io.papermc.paper.console.BrigadierCommandHighlighter; - import net.minecraft.server.dedicated.DedicatedServer; - import net.minecrell.terminalconsole.SimpleTerminalConsole; - import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -@@ -16,11 +18,15 @@ public final class PaperConsole extends SimpleTerminalConsole { - - @Override - protected LineReader buildReader(LineReaderBuilder builder) { -- return super.buildReader(builder -+ builder - .appName("Paper") - .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) - .completer(new ConsoleCommandCompleter(this.server)) -- ); -+ .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.getServerCommandListener())); -+ } -+ return super.buildReader(builder); - } - - @Override -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..edd231d95a04a1c4832f1ca8a3da6a56e9472ca1 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -@@ -0,0 +1,95 @@ -+package io.papermc.paper.console; -+ -+import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; -+import com.mojang.brigadier.CommandDispatcher; -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.StringReader; -+import com.mojang.brigadier.suggestion.Suggestion; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.network.chat.ChatComponentUtils; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Candidate; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+ -+import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; -+ -+public final class BrigadierCommandCompleter { -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { -+ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { -+ this.addCandidates(candidates, Collections.emptyList(), existing); -+ return; -+ } -+ final CommandDispatcher dispatcher = this.server.getCommandDispatcher().dispatcher(); -+ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); -+ this.addCandidates( -+ candidates, -+ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), -+ existing -+ ); -+ } -+ -+ private void addCandidates( -+ final @NonNull List candidates, -+ final @NonNull List brigSuggestions, -+ final @NonNull List existing -+ ) { -+ final List completions = new ArrayList<>(); -+ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); -+ for (final Completion completion : existing) { -+ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { -+ continue; -+ } -+ completions.add(completion); -+ } -+ for (final Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(toCandidate(completion)); -+ } -+ } -+ -+ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { -+ final String suggestionText = completion.suggestion(); -+ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); -+ return new Candidate( -+ suggestionText, -+ suggestionText, -+ null, -+ suggestionTooltip, -+ null, -+ null, -+ false -+ ); -+ } -+ -+ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { -+ if (suggestion.getTooltip() == null) { -+ return completion(suggestion.getText()); -+ } -+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(suggestion.getTooltip()))); -+ } -+ -+ static @NonNull StringReader prepareStringReader(final @NonNull String line) { -+ final StringReader stringReader = new StringReader(line); -+ if (stringReader.canRead() && stringReader.peek() == '/') { -+ stringReader.skip(); -+ } -+ return stringReader; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..d51d20a6d1c0c956cdf425503a6c1401acd9c854 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -@@ -0,0 +1,57 @@ -+package io.papermc.paper.console; -+ -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.context.ParsedCommandNode; -+import com.mojang.brigadier.tree.LiteralCommandNode; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Highlighter; -+import org.jline.reader.LineReader; -+import org.jline.utils.AttributedString; -+import org.jline.utils.AttributedStringBuilder; -+import org.jline.utils.AttributedStyle; -+ -+public final class BrigadierCommandHighlighter implements Highlighter { -+ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ @Override -+ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { -+ final AttributedStringBuilder builder = new AttributedStringBuilder(); -+ final ParseResults results = this.server.getCommandDispatcher().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); -+ int pos = 0; -+ if (buffer.startsWith("/")) { -+ builder.append("/", AttributedStyle.DEFAULT); -+ pos = 1; -+ } -+ int component = -1; -+ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { -+ if (node.getRange().getStart() >= buffer.length()) { -+ break; -+ } -+ final int start = node.getRange().getStart(); -+ final int end = Math.min(node.getRange().getEnd(), buffer.length()); -+ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); -+ if (node.getNode() instanceof LiteralCommandNode) { -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); -+ } else { -+ if (++component >= COLORS.length) { -+ component = 0; -+ } -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); -+ } -+ pos = end; -+ } -+ if (pos < buffer.length()) { -+ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); -+ } -+ return builder.toAttributedString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index a70e0761aeddee8fafff971b5cbd0422ab560fb5..988d1c9e9f4f29325043eb083123d12dd5f8081d 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -439,7 +439,7 @@ public class CommandDispatcher { - }; - } - -- public com.mojang.brigadier.CommandDispatcher a() { -+ public com.mojang.brigadier.CommandDispatcher a() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER - return this.b; - } - -diff --git a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -index b00e5d811ddfa12937f57bac4debb2fdd057d6e1..d14e4bf09bc43e78a9da07ea062ed886d27c7cc0 100644 ---- a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -+++ b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -@@ -90,7 +90,7 @@ public class ChatComponentUtils { - ChatComponentText chatcomponenttext = new ChatComponentText(""); - boolean flag = true; - -- for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { -+ for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix - T t0 = iterator.next(); - - if (!flag) { -@@ -108,7 +108,7 @@ public class ChatComponentUtils { - return new ChatMessage("chat.square_brackets", new Object[]{ichatbasecomponent}); - } - -- public static IChatBaseComponent a(Message message) { -+ public static IChatBaseComponent a(Message message) { return fromMessage(message); } public static IChatBaseComponent fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER - return (IChatBaseComponent) (message instanceof IChatBaseComponent ? (IChatBaseComponent) message : new ChatComponentText(message.getString())); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index dd8e87ad192c19743577bb95253a127072ea196c..5e1312941f9a554fc83adc02e81980069b8d015d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -18,9 +18,11 @@ import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { - private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer -+ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper - - public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; -+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.getServerCommandListener()); // Paper - } - - // Paper start - Change method signature for JLine update -@@ -64,7 +66,7 @@ public class ConsoleCommandCompleter implements Completer { - } - } - -- if (!completions.isEmpty()) { -+ if (false && !completions.isEmpty()) { - for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { - if (completion.suggestion().isEmpty()) { - continue; -@@ -80,6 +82,7 @@ public class ConsoleCommandCompleter implements Completer { - )); - } - } -+ this.addCompletions(reader, line, candidates, completions); - return; - } - -@@ -99,10 +102,12 @@ public class ConsoleCommandCompleter implements Completer { - try { - List offers = waitable.get(); - if (offers == null) { -+ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper - return; // Paper - Method returns void - } - - // Paper start - JLine update -+ /* - for (String completion : offers) { - if (completion.isEmpty()) { - continue; -@@ -110,6 +115,8 @@ public class ConsoleCommandCompleter implements Completer { - - candidates.add(new Candidate(completion)); - } -+ */ -+ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); - // Paper end - - // Paper start - JLine handles cursor now -@@ -138,5 +145,9 @@ public class ConsoleCommandCompleter implements Completer { - } - return false; - } -+ -+ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { -+ this.brigadierCompleter.complete(reader, line, candidates, existing); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch deleted file mode 100644 index d9657ceefbf0..000000000000 --- a/Spigot-Server-Patches/0702-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 19 Mar 2021 00:33:15 -0500 -Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly - -When the active item is not cleared, the item is still readied -for use and will repeatedly trigger the PlayerItemConsumeEvent -till their item is switched. -This patch clears the active item when the event is cancelled - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 21341eeb8148be119fbc1dd370c1beaf70a319e0..2537c9fcf155253da53ada3829c3caca765f35f4 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -3351,6 +3351,7 @@ public abstract class EntityLiving extends Entity { - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -+ this.clearActiveItem(); // Paper - event is using an item, clear active item to reset its use - // Update client - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Spigot-Server-Patches/0703-Add-bypass-host-check.patch b/Spigot-Server-Patches/0703-Add-bypass-host-check.patch deleted file mode 100644 index 6993d14f49eb..000000000000 --- a/Spigot-Server-Patches/0703-Add-bypass-host-check.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Apr 2021 21:27:01 +0100 -Subject: [PATCH] Add bypass host check - -Paper.bypassHostCheck - -Seriously, fix your firewalls. -.- - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 97c7914e9826defc3e7167879e387fe697c10f3e..c30270ab3e822977a87240bbb98289e1d03d3748 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -30,6 +30,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; - private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER -+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -117,7 +118,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - // Spigot Start - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); -- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { -+ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper - packethandshakinginsetprotocol.hostname = split[0]; - c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); - c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch b/Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch deleted file mode 100644 index eb7750011726..000000000000 --- a/Spigot-Server-Patches/0704-don-t-throw-when-loading-invalid-TEs.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 20 Apr 2021 01:15:04 +0100 -Subject: [PATCH] don't throw when loading invalid TEs - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..93d02ccb87c17404c55884f52ae40c7b7ddfb103 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -2,6 +2,7 @@ package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; - import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ResourceKeyInvalidException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -@@ -133,7 +134,13 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public static TileEntity create(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - String s = nbttagcompound.getString("id"); - -- return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(new MinecraftKey(s)).map((tileentitytypes) -> { -+ // Paper -+ MinecraftKey minecraftKey = null; -+ try { -+ minecraftKey = new MinecraftKey(s); -+ } catch (ResourceKeyInvalidException ex) {} -+ // Paper end -+ return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { - try { - return tileentitytypes.a(); - } catch (Throwable throwable) { diff --git a/Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch b/Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch deleted file mode 100644 index 25e0a9b5a859..000000000000 --- a/Spigot-Server-Patches/0705-Set-area-affect-cloud-rotation.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 16:58:20 -0400 -Subject: [PATCH] Set area affect cloud rotation - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index a152d5bec8bf0dd87239b0a3432fb589cea61bd8..42417aee4796d39d110e69cb707bd3b7bac30027 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1977,6 +1977,7 @@ public class CraftWorld implements World { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { - entity = new EntityAreaEffectCloud(world, x, y, z); -+ entity.setPositionRotation(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation - } else if (EvokerFangs.class.isAssignableFrom(clazz)) { - entity = new EntityEvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); - } diff --git a/Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch b/Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index 5e1db72d90ce..000000000000 --- a/Spigot-Server-Patches/0706-add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:10 -0700 -Subject: [PATCH] add isDeeplySleeping to HumanEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index b99423b3b413fc6364c6530a99e3c74dd406e1b4..f2b2db663198037ba4b7942815bfcd5ddd0e2a8d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -123,6 +123,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start -+ @Override -+ public boolean isDeeplySleeping() { -+ return getHandle().isDeeplySleeping(); -+ } -+ // Paper end -+ - @Override - public int getSleepTicks() { - return getHandle().sleepTicks; diff --git a/Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch b/Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch deleted file mode 100644 index cee651ba1dbd..000000000000 --- a/Spigot-Server-Patches/0707-Fix-duplicating-give-items-on-item-drop-cancel.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alphaesia -Date: Fri, 23 Apr 2021 09:57:56 +1200 -Subject: [PATCH] Fix duplicating /give items on item drop cancel - -Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). - -For every stack of items to give, /give puts the item stack straight -into the player's inventory. However, it also summons a "fake item" -at the player's location. When the PlayerDropItemEvent for this fake -item is cancelled, the server attempts to put the item back into the -player's inventory. The result is that the fake item, which is never -meant to be obtained, is combined with the real items injected directly -into the player's inventory. This means more items than the amount -specified in /give are given to the player - one for every stack of -items given. (e.g. /give @s dirt 1 gives you 2 dirt). - -While this isn't a big issue for general building usage, it can affect -e.g. adventure maps where the number of items the player receives is -important (and you want to restrict the player from throwing items). - -If there are any overflow items that didn't make it into the inventory -(insufficient space), those items are dropped as a real item instead -of a fake one. While cancelling this drop would also result in the -server attempting to put those items into the inventory, since it is -full this has no effect. - -Just ignoring cancellation of the PlayerDropItemEvent seems like the -cleanest and least intrusive way to fix it. - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGive.java b/src/main/java/net/minecraft/server/commands/CommandGive.java -index 6685bf1757458d908e32d4069f7a8a22a28c28d7..a10207f7cb9455e29db7e6906cb2138ad5609a1f 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGive.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGive.java -@@ -49,7 +49,7 @@ public class CommandGive { - - if (flag && itemstack.isEmpty()) { - itemstack.setCount(1); -- entityitem = entityplayer.drop(itemstack, false); -+ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel - if (entityitem != null) { - entityitem.s(); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index ec0956a98c133bcd3d4f92f696c667eab6ff98f1..3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -642,6 +642,13 @@ public abstract class EntityHuman extends EntityLiving { - - @Nullable - public EntityItem a(ItemStack itemstack, boolean flag, boolean flag1) { -+ // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(itemstack, flag, flag1, false); -+ } -+ -+ @Nullable -+ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { -+ // Paper end - if (itemstack.isEmpty()) { - return null; - } else { -@@ -683,7 +690,7 @@ public abstract class EntityHuman extends EntityLiving { - PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.world.getServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel - org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); - if (flag1 && (cur == null || cur.getAmount() == 0)) { - // The complete stack was dropped diff --git a/Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch b/Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index 410ceaf2969f..000000000000 --- a/Spigot-Server-Patches/0708-add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:28 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 1997139fb87dc1947acfdf02e1f116577c3fa943..9ce19b89c16eb6edd3d5d5cc87a966a37f66895c 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -331,7 +331,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - if (this.isBurning() && furnaceBurnEvent.isBurning()) { - // CraftBukkit end - flag1 = true; -- if (!itemstack.isEmpty()) { -+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper - Item item = itemstack.getItem(); - - itemstack.subtract(1); diff --git a/Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch b/Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index c205b0e09cbd..000000000000 --- a/Spigot-Server-Patches/0709-add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:11 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index 27e0e2767b11195231055f64446afb7ae5e08988..064d8adb47404b0fb839cfa646dfe04f2a2eefb6 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -@@ -245,6 +245,17 @@ public class CraftEntityEquipment implements EntityEquipment { - public void setBootsDropChance(float chance) { - setDropChance(EnumItemSlot.FEET, chance); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return getDropChance(CraftEquipmentSlot.getNMS(slot)); -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); -+ } -+ // Paper end - - private void setDropChance(EnumItemSlot slot, float chance) { - if (slot == EnumItemSlot.MAINHAND || slot == EnumItemSlot.OFFHAND) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index b812e1af411dd7f4509620b6b49b7897603dc970..dacb8e127403ef5234d6bca62aa4a35431724e9e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -@@ -354,4 +354,15 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i - public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return 1; -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch b/Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch deleted file mode 100644 index 532dace60c7c..000000000000 --- a/Spigot-Server-Patches/0710-fix-PigZombieAngerEvent-cancellation.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Thu, 18 Mar 2021 21:38:01 +0100 -Subject: [PATCH] fix PigZombieAngerEvent cancellation - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 59ea1432152051ce8a60c0a526db787593f0e744..1212c8e2af1f7e658d8bec7e5474a35190b1949e 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -28,6 +28,7 @@ public abstract class PathfinderGoal { - - public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - -+ public final void onTaskResetObfHelper() { d(); } // Paper - OBFHELPER - public void d() { - onTaskReset(); // Paper - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -index cc1bff409cad2eb6264d4b691599576960080ccd..d10d1b768601236b9892461ee41d61c7239d1a07 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -@@ -49,6 +49,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - private UUID br; - private static final IntRange bs = TimeRange.a(4, 6); - private int bt; -+ private PathfinderGoalHurtByTarget pathfinderGoalHurtByTarget; // Paper - - public EntityPigZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -69,7 +70,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - protected void m() { - this.goalSelector.a(2, new PathfinderGoalZombieAttack(this, 1.0D, false)); - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); -- this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error -+ this.targetSelector.a(1, pathfinderGoalHurtByTarget = new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error // Paper - assign field - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); - this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); - } -@@ -172,6 +173,7 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - this.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setAngerTarget(null); -+ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation - return; - } - this.setAnger(event.getNewAnger()); diff --git a/Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch b/Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch deleted file mode 100644 index 0a4779d24eda..000000000000 --- a/Spigot-Server-Patches/0711-Fix-checkReach-check-for-Shulker-boxes.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Sun, 4 Apr 2021 14:25:04 -0400 -Subject: [PATCH] Fix checkReach check for Shulker boxes - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -index fdc47411aa3e0e27d3a20c18274fef0a0db9a5b1..6ef70e209a8e282f7c00d80678636c2b8aa49b7a 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -@@ -65,6 +65,7 @@ public class ContainerShulkerBox extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -+ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox - return this.c.a(entityhuman); - } - diff --git a/Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch b/Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch deleted file mode 100644 index 9d3a5dd90b4c..000000000000 --- a/Spigot-Server-Patches/0712-fix-PlayerItemHeldEvent-firing-twice.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Thu, 22 Apr 2021 19:02:07 -0700 -Subject: [PATCH] fix PlayerItemHeldEvent firing twice - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -index d68f3e6b35f0af846c8a66710c5752508c095179..0e8ee44d0104ca7c666f57bdb54e0957935d5b34 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -@@ -24,6 +24,7 @@ public class PacketPlayInHeldItemSlot implements Packet { - packetlistenerplayin.a(this); - } - -+ public int getItemInHandIndex() { return b(); } // Paper - OBFHELPER - public int b() { - return this.itemInHandIndex; - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index db42f3b524adc4458c9c468b0299332e73a07a44..fd9f38f0bb723b3e78bd013ccb9538489a9ca43e 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -1908,6 +1908,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); - if (this.player.isFrozen()) return; // CraftBukkit - if (packetplayinhelditemslot.b() >= 0 && packetplayinhelditemslot.b() < PlayerInventory.getHotbarSize()) { -+ if (packetplayinhelditemslot.getItemInHandIndex() == this.player.inventory.itemInHandIndex) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.b()); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch b/Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index cf56b0987c3e..000000000000 --- a/Spigot-Server-Patches/0713-Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:19 -0700 -Subject: [PATCH] Added PlayerDeepSleepEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3a62bde04d7fbb6c571cfef11d4f6891e11c7ac8..3a13e7a050db7f5c93d810afe56325495cec7aa4 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -235,6 +235,11 @@ public abstract class EntityHuman extends EntityLiving { - - if (this.isSleeping()) { - ++this.sleepTicks; -+ // Paper start -+ if (this.sleepTicks == 100) { -+ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((Player) getBukkitEntity()).callEvent()) { this.sleepTicks = Integer.MIN_VALUE; } -+ } -+ // Paper end - if (this.sleepTicks > 100) { - this.sleepTicks = 100; - } diff --git a/Spigot-Server-Patches/0714-More-World-API.patch b/Spigot-Server-Patches/0714-More-World-API.patch deleted file mode 100644 index 3baa4688761f..000000000000 --- a/Spigot-Server-Patches/0714-More-World-API.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:52:34 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 325eba4e30ddcdfd038a215fbfde3bdc3e7c9b2a..7e032845fe9a46d33236444d62405a41e29daa17 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -1869,6 +1869,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit - } - -+ public BlockPosition getNearestBiome(BiomeBase biomeBase, BlockPosition blockPosition, int radius, int step) { return this.a(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER - @Nullable - public BlockPosition a(BiomeBase biomebase, BlockPosition blockposition, int i, int j) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().a(blockposition.getX(), blockposition.getY(), blockposition.getZ(), i, j, (biomebase1) -> { -@@ -1891,6 +1892,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.savingDisabled; - } - -+ public IRegistryCustom getWorldCustomRegistry() { return r(); } // Paper - OBFHELPER - @Override - public IRegistryCustom r() { - return this.server.getCustomRegistry(); -diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -index 72bc1a1e1c2153550313e93cf7df901a514a9bef..be6d63bcf15027e02a0bfbee0792c24f2300b27e 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -+++ b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -@@ -142,10 +142,10 @@ public class DimensionManager { - public static IRegistryCustom.Dimension a(IRegistryCustom.Dimension iregistrycustom_dimension) { - IRegistryWritable iregistrywritable = iregistrycustom_dimension.b(IRegistry.K); - -- iregistrywritable.a(DimensionManager.OVERWORLD, (Object) DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.l, (Object) DimensionManager.m, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_NETHER, (Object) DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_END, (Object) DimensionManager.THE_END_IMPL, Lifecycle.stable()); -+ iregistrywritable.a(DimensionManager.OVERWORLD, DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.l, DimensionManager.m, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_NETHER, DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_END, DimensionManager.THE_END_IMPL, Lifecycle.stable()); // Paper - decompile fix - return iregistrycustom_dimension; - } - -@@ -164,10 +164,10 @@ public class DimensionManager { - public static RegistryMaterials a(IRegistry iregistry, IRegistry iregistry1, IRegistry iregistry2, long i) { - RegistryMaterials registrymaterials = new RegistryMaterials<>(IRegistry.M, Lifecycle.experimental()); - -- registrymaterials.a(WorldDimension.THE_NETHER, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_NETHER, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_NETHER); - }, b(iregistry1, iregistry2, i))), Lifecycle.stable()); -- registrymaterials.a(WorldDimension.THE_END, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_END, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_END); - }, a(iregistry1, iregistry2, i))), Lifecycle.stable()); - return registrymaterials; -@@ -256,6 +256,7 @@ public class DimensionManager { - return this.E[i]; - } - -+ public Tag getInfiniburnTag() { return o(); } // Paper - OBFHELPER - public Tag o() { - Tag tag = TagsBlock.a().a(this.infiniburn); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 42417aee4796d39d110e69cb707bd3b7bac30027..3b3eda95c0ff8b129adedbae6561bba2d01c2f3a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2533,6 +2533,75 @@ public class CraftWorld implements World { - return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); - } - -+ // Paper start -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius) { -+ return this.locateNearestBiome(origin, biome, radius, 8); -+ } -+ -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { -+ BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPosition nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().b(IRegistry.ay), biome), originPos, radius, step); -+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); -+ } -+ -+ @Override -+ public boolean isUltrawarm() { -+ return getHandle().getDimensionManager().isNether(); -+ } -+ -+ @Override -+ public boolean isNatural() { -+ return getHandle().getDimensionManager().isNatural(); -+ } -+ -+ @Override -+ public double getCoordinateScale() { -+ return getHandle().getDimensionManager().getCoordinateScale(); -+ } -+ -+ @Override -+ public boolean hasSkylight() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean hasBedrockCeiling() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean isPiglinSafe() { -+ return getHandle().getDimensionManager().isPiglinSafe(); -+ } -+ -+ @Override -+ public boolean doesBedWork() { -+ return getHandle().getDimensionManager().isBedWorks(); -+ } -+ -+ @Override -+ public boolean doesRespawnAnchorWork() { -+ return getHandle().getDimensionManager().isRespawnAnchorWorks(); -+ } -+ -+ @Override -+ public boolean hasRaids() { -+ return getHandle().getDimensionManager().hasRaids(); -+ } -+ -+ @Override -+ public boolean isFixedTime() { -+ return getHandle().getDimensionManager().isFixedTime(); -+ } -+ -+ @Override -+ public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().getDimensionManager().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); -+ } -+ // Paper end -+ - @Override - public Raid locateNearestRaid(Location location, int radius) { - Validate.notNull(location, "Location cannot be null"); diff --git a/Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch b/Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index f74fd8eb8809..000000000000 --- a/Spigot-Server-Patches/0715-Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:41 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 3a13e7a050db7f5c93d810afe56325495cec7aa4..c39c50e53549e9cb9d3520bc7e8b7e89cfa20163 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -2233,6 +2233,7 @@ public abstract class EntityHuman extends EntityLiving { - this.g = ichatbasecomponent; - } - -+ public @Nullable IChatBaseComponent getChatComponent() { return this.a(); }; // Paper - OBFHELPER - @Nullable - public IChatBaseComponent a() { - return this.g; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java -index eca84595342756e3550883551e487aaf79574fde..abe0a1c309d526de37efcac44922fa259e1d112c 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java -@@ -43,6 +43,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - import net.minecraft.world.phys.shapes.VoxelShapes; - import org.apache.commons.lang3.ArrayUtils; -+import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - -@@ -101,14 +103,22 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - BlockPosition finalblockposition = blockposition; - // CraftBukkit end - entityhuman.sleep(blockposition).ifLeft((entityhuman_enumbedresult) -> { -+ // Paper start - PlayerBedFailEnterEvent -+ if (entityhuman_enumbedresult != null) { -+ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - handling bed explosion from below here -- if (entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE) { -+ if (event.getWillExplode()) { // Paper - this.explodeBed(finaliblockdata, world, finalblockposition); - } else - // CraftBukkit end - if (entityhuman_enumbedresult != null) { -- entityhuman.a(entityhuman_enumbedresult.a(), true); -+ entityhuman.a(PaperAdventure.asVanilla(event.getMessage()), true); // Paper - } -+ } // Paper - - }); - return EnumInteractionResult.SUCCESS; diff --git a/Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch b/Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch deleted file mode 100644 index 73865ff76398..000000000000 --- a/Spigot-Server-Patches/0716-Implement-methods-to-convert-between-Component-and-B.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: jmp -Date: Sat, 24 Apr 2021 02:09:32 -0700 -Subject: [PATCH] Implement methods to convert between Component and - Brigadier's Message - - -diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..fb1d6632788ae886b7a0e56fb490920c6ba2ce22 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -@@ -0,0 +1,30 @@ -+package io.papermc.paper.brigadier; -+ -+import com.mojang.brigadier.Message; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.ComponentLike; -+import net.minecraft.network.chat.ChatComponentUtils; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { -+ INSTANCE; -+ -+ PaperBrigadierProviderImpl() { -+ PaperBrigadierProvider.initialize(this); -+ } -+ -+ @Override -+ public @NonNull Message message(final @NonNull ComponentLike componentLike) { -+ requireNonNull(componentLike, "componentLike"); -+ return PaperAdventure.asVanilla(componentLike.asComponent()); -+ } -+ -+ @Override -+ public @NonNull Component componentFromMessage(final @NonNull Message message) { -+ requireNonNull(message, "message"); -+ return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 52bb528e75eb43156ee2bf19877bc051a35bb6e3..df8270c40ed7ce6f628686ff6f4fa4cf96af6738 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -213,6 +213,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - } - com.destroystokyo.paper.PaperConfig.registerCommands(); - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now -+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch deleted file mode 100644 index 3d7c4fd05daa..000000000000 --- a/Spigot-Server-Patches/0717-Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Fri, 23 Apr 2021 22:42:42 +0100 -Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end - portal - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b257d58a298e82f255b09e9575ee42a56a4b7cee..a83d8cfac8c5ed84dd5224cc3f18f55dba4741af 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -871,6 +871,7 @@ public abstract class PlayerList { - - // Paper start - boolean isBedSpawn = false; -+ boolean isAnchorSpawn = false; - boolean isRespawn = false; - boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end -@@ -891,6 +892,7 @@ public abstract class PlayerList { - if (optional.isPresent()) { - IBlockData iblockdata = worldserver1.getType(blockposition); - boolean flag3 = iblockdata.a(Blocks.RESPAWN_ANCHOR); -+ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal - Vec3D vec3d = (Vec3D) optional.get(); - float f1; - -@@ -918,7 +920,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch b/Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch deleted file mode 100644 index 8ab58db94cfc..000000000000 --- a/Spigot-Server-Patches/0718-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 17:17:47 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index fd9f38f0bb723b3e78bd013ccb9538489a9ca43e..8c9e97bb093c0e6297397edc71d72deebbcfbed9 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -2441,7 +2441,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - case PERFORM_RESPAWN: - if (this.player.viewingCredits) { - this.player.viewingCredits = false; -- this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, true); -+ this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, this.minecraftServer.getWorldServer(this.player.getSpawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument - CriterionTriggers.v.a(this.player, World.THE_END, World.OVERWORLD); - } else { - if (this.player.getHealth() > 0.0F) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a83d8cfac8c5ed84dd5224cc3f18f55dba4741af..2a76c3624c64e93509a96579f48c507e29901625 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -820,7 +820,13 @@ public abstract class PlayerList { - return this.moveToWorld(entityplayer, this.server.getWorldServer(entityplayer.getSpawnDimension()), flag, null, true); - } - -+ // Paper start - public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation) { -+ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); -+ } -+ -+ public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { -+ // Paper end - entityplayer.stopRiding(); // CraftBukkit - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -920,7 +926,7 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch b/Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index 4b084a47ec0d..000000000000 --- a/Spigot-Server-Patches/0719-Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:28:04 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index 8dfb9eb12d07c2d4737ecf3de1ae7f6de31891bf..fb2e914599ce024fa151735e8c2ac2eb6bdf05e7 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -46,6 +46,8 @@ import org.bukkit.potion.PotionEffect; - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.entity.Player; - import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+import io.papermc.paper.event.block.BeaconActivatedEvent; -+import io.papermc.paper.event.block.BeaconDeactivatedEvent; - // Paper end - - public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable { -@@ -211,6 +213,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - boolean flag1 = this.levels > 0; - - if (!flag && flag1) { -+ // Paper start - BeaconActivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new BeaconActivatedEvent(block).callEvent(); -+ // Paper end - this.a(SoundEffects.BLOCK_BEACON_ACTIVATE); - Iterator iterator = this.world.a(EntityPlayer.class, (new AxisAlignedBB((double) i, (double) j, (double) k, (double) i, (double) (j - 4), (double) k)).grow(10.0D, 5.0D, 10.0D)).iterator(); - -@@ -220,6 +226,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - CriterionTriggers.l.a(entityplayer, this); - } - } else if (flag && !flag1) { -+ // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new BeaconDeactivatedEvent(block).callEvent(); -+ // Paper end - this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); - } - } -@@ -257,6 +267,10 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - @Override - public void al_() { -+ // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new BeaconDeactivatedEvent(block).callEvent(); -+ // Paper end - this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); - super.al_(); - } diff --git a/Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch b/Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch deleted file mode 100644 index 0f5e146c0811..000000000000 --- a/Spigot-Server-Patches/0720-Add-Channel-initialization-listeners.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: KennyTV -Date: Thu, 29 Apr 2021 21:19:33 +0200 -Subject: [PATCH] Add Channel initialization listeners - - -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..88099df34c2d74daba9645aadf65b446ca795a91 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -@@ -0,0 +1,15 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this interface. -+ */ -+@FunctionalInterface -+public interface ChannelInitializeListener { -+ -+ void afterInitChannel(@NonNull Channel channel); -+} -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..30e62719e0a83525daa33cf41cb61df360c0e046 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -@@ -0,0 +1,74 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import net.kyori.adventure.key.Key; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+import java.util.Collections; -+import java.util.HashMap; -+import java.util.Map; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

    -+ * This is not officially supported API and we make no guarantees to the existence or state of this class. -+ */ -+public final class ChannelInitializeListenerHolder { -+ -+ private static final Map LISTENERS = new HashMap<>(); -+ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); -+ -+ private ChannelInitializeListenerHolder() { -+ } -+ -+ /** -+ * Registers whether an initialization listener is registered under the given key. -+ * -+ * @param key key -+ * @return whether an initialization listener is registered under the given key -+ */ -+ public static boolean hasListener(@NonNull Key key) { -+ return LISTENERS.containsKey(key); -+ } -+ -+ /** -+ * Registers a channel initialization listener called after ServerConnection is initialized. -+ * -+ * @param key key -+ * @param listener initialization listeners -+ */ -+ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { -+ LISTENERS.put(key, listener); -+ } -+ -+ /** -+ * Removes and returns an initialization listener registered by the given key if present. -+ * -+ * @param key key -+ * @return removed initialization listener if present -+ */ -+ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { -+ return LISTENERS.remove(key); -+ } -+ -+ /** -+ * Returns an immutable map of registered initialization listeners. -+ * -+ * @return immutable map of registered initialization listeners -+ */ -+ public static @NonNull Map getListeners() { -+ return IMMUTABLE_VIEW; -+ } -+ -+ /** -+ * Calls the registered listeners with the given channel. -+ * -+ * @param channel channel -+ */ -+ public static void callListeners(@NonNull Channel channel) { -+ for (ChannelInitializeListener listener : LISTENERS.values()) { -+ listener.afterInitChannel(channel); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index dc362724ea0cc1b2f9d9ceffff483217b4356c40..69fc2789df88344587b6052f93661ed38f24a503 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -104,6 +104,7 @@ public class ServerConnection { - pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); -+ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } - }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit - } diff --git a/Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch b/Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch deleted file mode 100644 index 818cc40fa365..000000000000 --- a/Spigot-Server-Patches/0721-Send-empty-commands-if-tab-completion-is-disabled.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 26 Apr 2021 01:27:08 +0100 -Subject: [PATCH] Send empty commands if tab completion is disabled - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 988d1c9e9f4f29325043eb083123d12dd5f8081d..29a395e69aab9c50a45c5fd5ab8795fd8e3ef727 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -326,7 +326,12 @@ public class CommandDispatcher { - } - - public void a(EntityPlayer entityplayer) { -- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot -+ // Paper start - Send empty commands if tab completion is disabled -+ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCommands(new RootCommandNode<>())); -+ return; -+ } -+ // Paper end - // CraftBukkit start - // Register Vanilla commands into builtRoot as before - // Paper start - Async command map building diff --git a/Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch b/Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch deleted file mode 100644 index 4679f25de7fa..000000000000 --- a/Spigot-Server-Patches/0722-Add-more-WanderingTrader-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 6 May 2021 14:56:43 +0100 -Subject: [PATCH] Add more WanderingTrader API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 37e1b2bf33510c3603efadf219b462e667f573c2..69044827ed6b34924ffd89a977afa06df0dcefc3 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -58,6 +58,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - @Nullable - private BlockPosition bp; - private int despawnDelay; -+ // Paper start - Add more WanderingTrader API -+ public boolean canDrinkPotion = true; -+ public boolean canDrinkMilk = true; -+ // Paper end - - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -69,10 +73,10 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { -- return this.world.isNight() && !entityvillagertrader.isInvisible(); -+ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, new ItemStack(Items.MILK_BUCKET), SoundEffects.ENTITY_WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { -- return this.world.isDay() && entityvillagertrader.isInvisible(); -+ return canDrinkMilk && this.world.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(1, new PathfinderGoalTradeWithPlayer(this)); - this.goalSelector.a(1, new PathfinderGoalAvoidTarget<>(this, EntityZombie.class, 8.0F, 0.5D, 0.5D)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index c8344ce0a85030b12139d0b2bbe45acdcd33e1e7..6dad8ca649a2fa0a80a4b88c8a3e284fe218f31f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -@@ -35,4 +35,26 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande - public void setDespawnDelay(int despawnDelay) { - getHandle().setDespawnDelay(despawnDelay); - } -+ -+ // Paper start - Add more WanderingTrader API -+ @Override -+ public void setCanDrinkPotion(boolean bool) { -+ getHandle().canDrinkPotion = bool; -+ } -+ -+ @Override -+ public boolean canDrinkPotion() { -+ return getHandle().canDrinkPotion; -+ } -+ -+ @Override -+ public void setCanDrinkMilk(boolean bool) { -+ getHandle().canDrinkMilk = bool; -+ } -+ -+ @Override -+ public boolean canDrinkMilk() { -+ return getHandle().canDrinkMilk; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch b/Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch deleted file mode 100644 index 3fc2d1a33752..000000000000 --- a/Spigot-Server-Patches/0723-Add-EntityBlockStorage-clearEntities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:12:29 -0400 -Subject: [PATCH] Add EntityBlockStorage#clearEntities() - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -index 3cbcbb028b864f1d14e004628bbc0829f71ab476..80083a6666a28372946cf0e68ded44d075357f7d 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -@@ -120,6 +120,11 @@ public class TileEntityBeehive extends TileEntity implements ITickable { - return this.bees.size(); - } - -+ // Paper start - Add EntityBlockStorage clearEntities -+ public void clearBees() { -+ this.bees.clear(); -+ } -+ // Paper end - public static int a(IBlockData iblockdata) { - return (Integer) iblockdata.get(BlockBeehive.b); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -index af691b28b38e388617d241008c2e9d403bc5c15d..9f4fb1ff9c945799d10d6905c8b73376e4133d23 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -@@ -83,4 +83,10 @@ public class CraftBeehive extends CraftBlockEntityState imple - - getSnapshot().addBee(((CraftBee) entity).getHandle(), false); - } -+ // Paper start - Add EntityBlockStorage clearEntities -+ @Override -+ public void clearEntities() { -+ getSnapshot().clearBees(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 07309399fa68..000000000000 --- a/Spigot-Server-Patches/0724-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:31:13 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java -index e3d5d55a2fe5d86db621d3e0c9322f553386d731..2f3d9e5b849093027d3c2ef434494cd600f52a31 100644 ---- a/src/main/java/net/minecraft/advancements/Advancement.java -+++ b/src/main/java/net/minecraft/advancements/Advancement.java -@@ -76,6 +76,7 @@ public class Advancement { - return this.parent; - } - -+ public final @Nullable AdvancementDisplay getAdvancementDisplay() { return this.c(); } // Paper - OBFHELPER - @Nullable - public AdvancementDisplay c() { - return this.display; -@@ -125,6 +126,7 @@ public class Advancement { - return this.requirements; - } - -+ public final IChatBaseComponent getChatComponent() { return this.j(); } // Paper - OBFHELPER - public IChatBaseComponent j() { - return this.chatComponent; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -index 721d7fbab447117349994f710338ca616ab11067..adc6779e53e7b2ee04a80e2ea714e3378b8e6f39 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -@@ -54,10 +54,12 @@ public class AdvancementDisplay { - return this.b; - } - -+ public final AdvancementFrameType getFrameType() { return this.e(); } // Paper - OBFHELPER - public AdvancementFrameType e() { - return this.e; - } - -+ public final boolean shouldAnnounceToChat() { return this.i(); } // Paper - OBFHELPER - public boolean i() { - return this.g; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -index f5d24950d317c78a971472821595fc1b44befc6e..32380346555e194227423999a79f1ebcbbe38d3b 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -@@ -20,6 +20,7 @@ public enum AdvancementFrameType { - this.g = new ChatMessage("advancements.toast." + s); - } - -+ public final String getId() { return this.a(); } // Paper - OBFHELPER - public String a() { - return this.d; - } -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 7a8a1960882e291c46301d07da3e1c5415516893..dfdbc028f68ced197ad179248ed3b1e9d70ba057 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -51,6 +51,7 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.GameRules; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class AdvancementDataPlayer { - -@@ -313,10 +314,18 @@ public class AdvancementDataPlayer { - this.j.add(advancement); - flag = true; - if (!flag1 && advancementprogress.isDone()) { -- this.player.world.getServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); -+ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new ChatMessage("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getScoreboardDisplayName(), advancement.getChatComponent())) : null; -+ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); -+ this.player.world.getServer().getPluginManager().callEvent(event); -+ message = event.message(); -+ // Paper end - advancement.d().a(this.player); -- if (advancement.c() != null && advancement.c().i() && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -- this.e.sendMessage(new ChatMessage("chat.type.advancement." + advancement.c().e().a(), new Object[]{this.player.getScoreboardDisplayName(), advancement.j()}), ChatMessageType.SYSTEM, SystemUtils.b); -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ if (message != null && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -+ this.e.sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); -+ // Paper end - } - } - } diff --git a/Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index f946246fea2c..000000000000 --- a/Spigot-Server-Patches/0725-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index c67b94840e4c967baebf6eb351df15f0e4ead4be..f54af7cabc6b4e062948dc97e577e7fe04b5add4 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -327,12 +327,13 @@ public class LoginListener implements PacketLoginInListener { - // Paper end - String playerName = i.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); -+ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) networkManager.getRawAddress()).getAddress(); // Paper - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); - profile.complete(true); diff --git a/Spigot-Server-Patches/0726-Inventory-close.patch b/Spigot-Server-Patches/0726-Inventory-close.patch deleted file mode 100644 index 79f0c206860f..000000000000 --- a/Spigot-Server-Patches/0726-Inventory-close.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:56 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index c3fa97ac34e1fc61ae02f224f8afe5a0b486fb4d..f6001047ada8308cfa1d9b26677a7a5d7774de51 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -449,6 +449,14 @@ public class CraftInventory implements Inventory { - clear(i); - } - } -+ // Paper start -+ @Override -+ public int close() { -+ int count = this.inventory.getViewers().size(); -+ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); -+ return count; -+ } -+ // Paper end - - @Override - public ListIterator iterator() { diff --git a/Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch b/Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch deleted file mode 100644 index 21890b59ca39..000000000000 --- a/Spigot-Server-Patches/0727-call-PortalCreateEvent-players-and-end-platform.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 12 May 2021 03:21:22 -0700 -Subject: [PATCH] call PortalCreateEvent players and end platform - - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index eb67af795dd716d9f92ac32843accc1ec4efd647..4abc87b7e737bc652e84f76a508ab85501d1556f 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -496,6 +496,7 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); - } - -+ public BlockPosition.MutableBlockPosition withOffset(int x, int y, int z) { return e(x, y, z); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition e(int i, int j, int k) { - return this.d(this.getX() + i, this.getY() + j, this.getZ() + k); - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 3f44d5b8e3bc4f897a5dda473532004078fe0ebe..8683d6ddc5d8ce4a302fa6e2665b7dcd64f6a00a 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -1145,15 +1145,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private void a(WorldServer worldserver, BlockPosition blockposition) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); - -+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); // Paper - for (int i = -2; i <= 2; ++i) { - for (int j = -2; j <= 2; ++j) { - for (int k = -1; k < 3; ++k) { - IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.getBlockData() : Blocks.AIR.getBlockData(); - -- worldserver.setTypeUpdate(blockposition_mutableblockposition.g(blockposition).e(j, k, i), iblockdata); -+ blockList.setTypeAndData(blockposition_mutableblockposition.setValues(blockposition).withOffset(j, k, i), iblockdata, 3); // Paper - } - } - } -+ // Paper start -+ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), worldserver.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { -+ blockList.updateList(); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index 70f7b8aa4182..000000000000 --- a/Spigot-Server-Patches/0728-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:33 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 42cf3fa42b73739182d26fbb524ee5b304c799b2..16c0c960aa1e4d35093b810c7648b5638175e106 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -134,7 +134,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public void movementTick() { -- if (this.isAlive() && this.eG()) { -+ if (this.isAlive() && shouldBurnInDay && this.eG()) { // Paper - Configurable Burning - this.setOnFire(8); - } - -@@ -165,6 +165,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); - } -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); - // Paper end - } - -@@ -179,6 +180,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (this.spawningEntity != null) { - nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); - } -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - // Paper end - } - -@@ -233,6 +235,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return spawningEntity; - } - public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } - // Paper end - - class b extends PathfinderGoal { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 06d50b22ede102556fdb3e2a6f1424f7ff13f120..f8358e40c42f219232bf928f4e0073339a5e19d5 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -98,9 +98,15 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - return EnumMonsterType.UNDEAD; - } - -+ // Paper start -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } -+ // Paper end -+ - @Override - public void movementTick() { -- boolean flag = this.eG(); -+ boolean flag = shouldBurnInDay && this.eG(); // Paper - Configurable Burning - - if (flag) { - ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); -@@ -224,7 +230,16 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); - this.eL(); -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); // Paper -+ } -+ -+ // Paper start -+ @Override -+ public void saveData(NBTTagCompound nbttagcompound) { -+ super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - } -+ // Paper end - - @Override - public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 0cea1d8e23da3a79ef06e43752665a5401b01b4b..476339ef8cafad2d6c78bccb6fd9f3c882b89148 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -40,5 +40,15 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public java.util.UUID getSpawningEntity() { - return getHandle().getSpawningEntity(); - } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index c2acfa2cc27a187154e17b7f45908682b41b52af..f48c4225dbc3467aaf8d14bc4047430548cc7c78 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -36,4 +36,16 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); - } -+ -+ // Paper start -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch b/Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch deleted file mode 100644 index e2ecdf706b91..000000000000 --- a/Spigot-Server-Patches/0729-Fix-CraftPotionBrewer-cache.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sceri -Date: Fri, 14 May 2021 19:06:51 +0500 -Subject: [PATCH] Fix CraftPotionBrewer cache - - -diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -index 7156bd1c8938a0b111be11d93ed2645a58d75611..4d108ed58a768a5a5e2e33213921f0a89487b6a2 100644 ---- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -@@ -15,12 +15,18 @@ import org.bukkit.potion.PotionEffectType; - import org.bukkit.potion.PotionType; - - public class CraftPotionBrewer implements PotionBrewer { -- private static final Map> cache = Maps.newHashMap(); -+ private static final Map> cache = Maps.newHashMap(); // Paper - - @Override - public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); -+ // Paper start -+ int key = damage.ordinal() << 2; -+ key |= (upgraded ? 1 : 0) << 1; -+ key |= extended ? 1 : 0; -+ -+ if (cache.containsKey(key)) -+ return cache.get(key); -+ // Paper end - - List mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).a(); - -@@ -29,9 +35,9 @@ public class CraftPotionBrewer implements PotionBrewer { - builder.add(CraftPotionUtil.toBukkit(effect)); - } - -- cache.put(damage, builder.build()); -+ cache.put(key, builder.build()); // Paper - -- return cache.get(damage); -+ return cache.get(key); // Paper - } - - @Override diff --git a/Spigot-Server-Patches/0730-Remove-interact-event-from-boat.patch b/Spigot-Server-Patches/0730-Remove-interact-event-from-boat.patch deleted file mode 100644 index dc9f9045e6d9..000000000000 --- a/Spigot-Server-Patches/0730-Remove-interact-event-from-boat.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Fri, 23 Apr 2021 16:37:12 -0400 -Subject: [PATCH] Remove interact event from boat - - -diff --git a/src/main/java/net/minecraft/world/item/ItemBoat.java b/src/main/java/net/minecraft/world/item/ItemBoat.java -index 1d812b3e27f87213afc3e441eb20ca984458ce2a..e24085facbc738c5eecbf85dee1b87072c41537c 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBoat.java -+++ b/src/main/java/net/minecraft/world/item/ItemBoat.java -@@ -54,6 +54,7 @@ public class ItemBoat extends Item { - } - - if (movingobjectpositionblock.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ /* Paper - Remove unneeded interaction event trigger - // CraftBukkit start - Boat placement - org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityhuman, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPosition(), movingobjectpositionblock.getDirection(), itemstack, enumhand); - -@@ -61,6 +62,7 @@ public class ItemBoat extends Item { - return InteractionResultWrapper.pass(itemstack); - } - // CraftBukkit end -+ */ // Paper - Remove unneeded interaction event trigger - EntityBoat entityboat = new EntityBoat(world, movingobjectpositionblock.getPos().x, movingobjectpositionblock.getPos().y, movingobjectpositionblock.getPos().z); - - entityboat.setType(this.b); diff --git a/Spigot-Server-Patches/0731-Add-basic-Datapack-API.patch b/Spigot-Server-Patches/0731-Add-basic-Datapack-API.patch deleted file mode 100644 index d0eae2727988..000000000000 --- a/Spigot-Server-Patches/0731-Add-basic-Datapack-API.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6426f646afdd2a75df89d522068a36cf170d697d ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -@@ -0,0 +1,51 @@ -+package io.papermc.paper.datapack; -+ -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+ -+import java.util.List; -+import java.util.stream.Collectors; -+ -+public class PaperDatapack implements Datapack { -+ private final String name; -+ private final Compatibility compatibility; -+ private final boolean enabled; -+ -+ PaperDatapack(ResourcePackLoader loader, boolean enabled) { -+ this.name = loader.getName(); -+ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Compatibility getCompatibility() { -+ return compatibility; -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void setEnabled(boolean enabled) { -+ if (enabled == this.enabled) { -+ return; -+ } -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ List enabledKeys = server.getResourcePackRepository().getEnabledPacks().stream().map(ResourcePackLoader::getName).collect(Collectors.toList()); -+ if (enabled) { -+ enabledKeys.add(this.name); -+ } else { -+ enabledKeys.remove(this.name); -+ } -+ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..378aaeebd7e011565fdc505da68c5b5285339add ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -@@ -0,0 +1,26 @@ -+package io.papermc.paper.datapack; -+ -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+import net.minecraft.server.packs.repository.ResourcePackRepository; -+ -+import java.util.Collection; -+import java.util.stream.Collectors; -+ -+public class PaperDatapackManager implements DatapackManager { -+ private final ResourcePackRepository repository; -+ -+ public PaperDatapackManager(ResourcePackRepository repository) { -+ this.repository = repository; -+ } -+ -+ @Override -+ public Collection getPacks() { -+ Collection enabledPacks = repository.getEnabledPacks(); -+ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); -+ } -+ -+ @Override -+ public Collection getEnabledPacks() { -+ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -index 5c038c02955d8517db0686f3b73c8573d3770466..01c4fda33a138b2d1f6b7c1335378445423a66a9 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -@@ -102,6 +102,7 @@ public class ResourcePackLoader implements AutoCloseable { - }); - } - -+ public final EnumResourcePackVersion getVersion() { return this.c(); } // Paper - OBFHELPER - public EnumResourcePackVersion c() { - return this.g; - } -@@ -110,6 +111,7 @@ public class ResourcePackLoader implements AutoCloseable { - return (IResourcePack) this.d.get(); - } - -+ public final String getName() { return this.e(); } // Paper - OBFHELPER - public String e() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -index e87523612d0423d71eab7b9af851c1c268cdf84f..568da9686c41a41e43ede3fe15e0ca53c9688f8b 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -@@ -88,6 +88,7 @@ public class ResourcePackRepository implements AutoCloseable { - return this.b.keySet(); - } - -+ public final Collection getPacks() { return this.c(); } // Paper - OBFHELPER - public Collection c() { - return this.b.values(); - } -@@ -96,6 +97,7 @@ public class ResourcePackRepository implements AutoCloseable { - return (Collection) this.c.stream().map(ResourcePackLoader::e).collect(ImmutableSet.toImmutableSet()); - } - -+ public final Collection getEnabledPacks() { return this.e(); } // Paper - OBFHELPER - public Collection e() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6cc8eb04f42592aa12f76bb4a0a863ea509741b2..edeb3e542c2e32379a5fb4229b389ad4a4987dbb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.datapack.PaperDatapackManager; // Paper - import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import java.awt.image.BufferedImage; -@@ -268,6 +269,7 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ private final PaperDatapackManager datapackManager; // Paper - public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { -@@ -350,6 +352,7 @@ public final class CraftServer implements Server { - TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); -+ datapackManager = new PaperDatapackManager(console.getResourcePackRepository()); // Paper - } - - public boolean getCommandBlockOverride(String command) { -@@ -2498,5 +2501,11 @@ public final class CraftServer implements Server { - public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return mobGoals; - } -+ -+ @Override -+ public PaperDatapackManager getDatapackManager() { -+ return datapackManager; -+ } -+ - // Paper end - } diff --git a/UPDATE_NOTES.md b/UPDATE_NOTES.md deleted file mode 100644 index 23c915e1959d..000000000000 --- a/UPDATE_NOTES.md +++ /dev/null @@ -1,14 +0,0 @@ -# Shit to check - -* Mini: "Optimize World Server Map": Figure out how to fill PaperWorldMap, it needs a dim key which doesnt exist anymore? -* Mini: "MC-50319": fix if still works -* Make sure the flat bedrock setting doesn't do anything stupid -* Check DataBits foreach -* lighting is bork (load chunk, fly away, come back, everything or parts are black) -* chunk generation seems slow with a lot of it happening -* Fix IDE Debug JVM Flag for new versions of minecraft - -* Check if `PlayerEditBookEvent`: https://github.com/PaperMC/Paper/pull/1751 -The PlayerEditBookEvent is straight up not called anymore. -The method to call it must now be `PlayerConnection#a(List, int)` (CB bug). -The item is presumably edited with the new page contents before it ever reaches this method? \ No newline at end of file diff --git a/build-data/dev-imports.txt b/build-data/dev-imports.txt new file mode 100644 index 000000000000..302359e8a3c1 --- /dev/null +++ b/build-data/dev-imports.txt @@ -0,0 +1,15 @@ +# You can use this file to import files from minecraft libraries into the project +# format: +# +# both fully qualified and a file based syntax are accepted for : +# authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +# datafixerupper com.mojang.datafixers.DataFixerBuilder +# datafixerupper com/mojang/datafixers/util/Either.java +# To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId: +# minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter +# minecraft net/minecraft/world/level/entity/LevelEntityGetter.java +# To import minecraft data files, like the default chat type, use `mc_data` as the prefix: +# mc_data chat_type/chat.json +# mc_data dimension_type/overworld.json +# + diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny new file mode 100644 index 000000000000..14a2a3582aba --- /dev/null +++ b/build-data/mappings-patch.tiny @@ -0,0 +1,5 @@ +tiny 2 0 spigot mojang+yarn + +# Originally DistanceManager, which also implements DistanceManager, so clashes since the implemented class +# is imported and not fully qualified. Easiest fix is to just change the name +c net/minecraft/server/level/PlayerChunkMap$a net/minecraft/server/level/ChunkMap$ChunkDistanceManager diff --git a/build-data/paper.at b/build-data/paper.at new file mode 100644 index 000000000000..48a44de3604b --- /dev/null +++ b/build-data/paper.at @@ -0,0 +1,18 @@ +# You can use this file to change the access modifiers on a member +# This line would make the field rollAmount public in Bee +#public net.minecraft.world.entity.animal.Bee rollAmount +# This line would make the field public and remove the final modifier +#public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender +# Leave out the member and it will apply to the class itself +# More info, see here https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers + +# Remap/Decompile fix (unclear why this is happening) +public net.minecraft.server.MinecraftServer doRunTask(Lnet/minecraft/server/TickTask;)V + +# AT remap issue? todo 1.18 +public net.minecraft.world.level.dimension.end.EndDragonFight findExitPortal()Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch; +public net.minecraft.nbt.TagParser readArrayTag()Lnet/minecraft/nbt/Tag; + +# TODO 1.20 remapSpigotAt.at doesn't remap the return type for this method for some reason +public net/minecraft/world/entity/Display$TextDisplay getText()Lnet/minecraft/network/chat/Component; +public net/minecraft/world/entity/Display$BlockDisplay getBlockState()Lnet/minecraft/world/level/block/state/BlockState; diff --git a/build-data/reobf-mappings-patch.tiny b/build-data/reobf-mappings-patch.tiny new file mode 100644 index 000000000000..b14d9ed34563 --- /dev/null +++ b/build-data/reobf-mappings-patch.tiny @@ -0,0 +1,28 @@ +# We would like for paperweight to generate 100% perfect reobf mappings (and deobf mappings for that matter). +# But unfortunately it's not quite there yet - and it may be some time before that happens. Generating perfect mappings +# from Spigot's mappings is extremely difficult due to Spigot's bad tooling and bad mappings. To add insult to injury +# we remap Spigot's _source code_ which is a lot more complex and error-prone than bytecode remapping. So with all that +# said, this file exists to help fill in the gap. +# +# We will continue to improve paperweight and will work on fixing these issues so they don't come up in the first place, +# but these mappings exist to prevent these issues from holding everything else in Paper up while we work through all +# of these issues. Due to the complex nature of mappings generation and the debugging difficulty involved it may take +# a significant amount of time for us to track down every possible issue, so this file will likely be around and in +# use - at least in some capacity - for a long time. + +tiny 2 0 mojang+yarn spigot + +# CraftBukkit changes type +c net/minecraft/server/level/ServerLevel net/minecraft/server/level/WorldServer + f Lnet/minecraft/world/level/storage/PrimaryLevelData; serverLevelData L + +c net/minecraft/world/level/chunk/LevelChunk net/minecraft/world/level/chunk/Chunk + f Lnet/minecraft/server/level/ServerLevel; level r + +# See mappings-patch.tiny +c net/minecraft/server/level/ChunkMap net/minecraft/server/level/PlayerChunkMap + f Lnet/minecraft/server/level/ChunkMap$ChunkDistanceManager; distanceManager G + +# The method is made public by Spigot, which then causes accidental overrides +c net/minecraft/world/entity/Entity net/minecraft/world/entity/Entity + m ()Z isInRain isInRain0 diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000000..cce2a91f723f --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,296 @@ +import io.papermc.paperweight.PaperweightException +import io.papermc.paperweight.tasks.BaseTask +import io.papermc.paperweight.util.* +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent +import java.io.ByteArrayOutputStream +import java.nio.file.Path +import java.util.regex.Pattern +import kotlin.io.path.* + +plugins { + java + `maven-publish` + id("io.papermc.paperweight.core") version "1.7.7" +} + +allprojects { + apply(plugin = "java") + apply(plugin = "maven-publish") + + java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } + } +} + +val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" + +subprojects { + tasks.withType { + options.encoding = Charsets.UTF_8.name() + options.release = 21 + options.isFork = true + } + tasks.withType { + options.encoding = Charsets.UTF_8.name() + } + tasks.withType { + filteringCharset = Charsets.UTF_8.name() + } + tasks.withType { + testLogging { + showStackTraces = true + exceptionFormat = TestExceptionFormat.FULL + events(TestLogEvent.STANDARD_OUT) + } + } + + repositories { + mavenCentral() + maven(paperMavenPublicUrl) + } +} + +val spigotDecompiler: Configuration by configurations.creating + +repositories { + mavenCentral() + maven(paperMavenPublicUrl) { + content { + onlyForConfigurations( + configurations.paperclip.name, + spigotDecompiler.name, + ) + } + } +} + +dependencies { + paramMappings("net.fabricmc:yarn:1.21.4+build.1:mergedv2") + remapper("net.fabricmc:tiny-remapper:0.10.3:fat") + decompiler("org.vineflower:vineflower:1.10.1") + spigotDecompiler("io.papermc:patched-spigot-fernflower:0.1+build.13") + paperclip("io.papermc:paperclip:3.0.3") +} + +paperweight { + minecraftVersion = providers.gradleProperty("mcVersion") + serverProject = project(":paper-server") + + paramMappingsRepo = paperMavenPublicUrl + remapRepo = paperMavenPublicUrl + decompileRepo = paperMavenPublicUrl + + craftBukkit { + fernFlowerJar = layout.file(spigotDecompiler.elements.map { it.single().asFile }) + } + + paper { + spigotApiPatchDir = layout.projectDirectory.dir("patches/api") + spigotServerPatchDir = layout.projectDirectory.dir("patches/server") + + mappingsPatch = layout.projectDirectory.file("build-data/mappings-patch.tiny") + reobfMappingsPatch = layout.projectDirectory.file("build-data/reobf-mappings-patch.tiny") + + reobfPackagesToFix.addAll( + "co.aikar.timings", + "com.destroystokyo.paper", + "com.mojang", + "io.papermc.paper", + "ca.spottedleaf", + "net.kyori.adventure.bossbar", + "net.minecraft", + "org.bukkit.craftbukkit", + "org.spigotmc", + ) + } +} + +tasks.generateDevelopmentBundle { + apiCoordinates = "io.papermc.paper:paper-api" + libraryRepositories.addAll( + "https://repo.maven.apache.org/maven2/", + paperMavenPublicUrl, + ) +} + +publishing { + if (project.providers.gradleProperty("publishDevBundle").isPresent) { + publications.create("devBundle") { + artifact(tasks.generateDevelopmentBundle) { + artifactId = "dev-bundle" + } + } + } +} + +allprojects { + publishing { + repositories { + maven("https://repo.papermc.io/repository/maven-snapshots/") { + name = "paperSnapshots" + credentials(PasswordCredentials::class) + } + } + } +} + +tasks.register("printMinecraftVersion") { + doLast { + println(providers.gradleProperty("mcVersion").get().trim()) + } +} + +tasks.register("printPaperVersion") { + doLast { + println(project.version) + } +} + +// see gradle.properties +if (providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean()) { + tasks.collectAtsFromPatches { + val dir = layout.projectDirectory.dir("patches/unapplied/server") + if (dir.path.isDirectory()) { + extraPatchDir = dir + } + } + tasks.withType().configureEach { + filterPatches = false + } + tasks.register("continueServerUpdate", RebasePatches::class) { + description = "Moves the next X patches from unapplied to applied, and applies them. X being the number of patches that apply cleanly, plus the terminal failure if any." + projectDir = project.projectDir + appliedPatches = file("patches/server") + unappliedPatches = file("patches/unapplied/server") + applyTaskName = "applyServerPatches" + patchedDir = "Paper-Server" + } +} + +@UntrackedTask(because = "Does not make sense to track state") +abstract class RebasePatches : BaseTask() { + @get:Internal + abstract val projectDir: DirectoryProperty + + @get:InputFiles + abstract val appliedPatches: DirectoryProperty + + @get:InputFiles + abstract val unappliedPatches: DirectoryProperty + + @get:Input + abstract val applyTaskName: Property + + @get:Input + abstract val patchedDir: Property + + private fun unapplied(): List = + unappliedPatches.path.listDirectoryEntries("*.patch").sortedBy { it.name } + + private fun appliedLoc(patch: Path): Path = appliedPatches.path.resolve(unappliedPatches.path.relativize(patch)) + + companion object { + val regex = Pattern.compile("Patch failed at ([0-9]{4}) (.*)") + val continuationRegex = Pattern.compile("^\\s{1}.+\$") + const val subjectPrefix = "Subject: [PATCH] " + } + + @TaskAction + fun run() { + val patchedDirPath = projectDir.path.resolve(patchedDir.get()) + if (patchedDirPath.isDirectory()) { + val status = Git(patchedDirPath)("status").getText() + if (status.contains("You are in the middle of an am session.")) { + throw PaperweightException("Cannot continue update when $patchedDirPath is in the middle of an am session.") + } + } + + val unapplied = unapplied() + for (patch in unapplied) { + patch.copyTo(appliedLoc(patch)) + } + + val out = ByteArrayOutputStream() + val proc = ProcessBuilder() + .directory(projectDir.path) + .command("./gradlew", applyTaskName.get()) + .redirectErrorStream(true) + .start() + + val f = redirect(proc.inputStream, out) + + val exit = proc.waitFor() + f.get() + + if (exit != 0) { + val outStr = String(out.toByteArray()) + val matcher = regex.matcher(outStr) + if (!matcher.find()) error("Could not determine failure point") + val failedSubjectFragment = matcher.group(2) + val failed = unapplied.single { p -> + p.useLines { lines -> + val collect = mutableListOf() + for (line in lines) { + if (line.startsWith(subjectPrefix)) { + collect += line + } else if (collect.size == 1) { + if (continuationRegex.matcher(line).matches()) { + collect += line + } else { + break + } + } + } + val subjectLine = collect.joinToString("").substringAfter(subjectPrefix) + subjectLine.startsWith(failedSubjectFragment) + } + } + + // delete successful & failure point from unapplied patches dir + for (path in unapplied) { + path.deleteIfExists() + if (path == failed) { + break + } + } + + // delete failed from patches dir + var started = false + for (path in unapplied) { + if (path == failed) { + started = true + continue + } + if (started) { + appliedLoc(path).deleteIfExists() + } + } + + // Delete the build file before resetting the AM session in case it has compilation errors + patchedDirPath.resolve("build.gradle.kts").deleteIfExists() + // Apply again to reset the am session (so it ends on the failed patch, to allow us to rebuild after fixing it) + val apply2 = ProcessBuilder() + .directory(projectDir.path) + .command("./gradlew", applyTaskName.get()) + .redirectErrorStream(true) + .start() + + val f1 = redirect(apply2.inputStream, System.out) + apply2.waitFor() + f1.get() + + logger.lifecycle(outStr) + logger.lifecycle("Patch failed at $failed; See Git output above.") + } else { + unapplied.forEach { it.deleteIfExists() } + logger.lifecycle("All patches applied!") + } + + val git = Git(projectDir.path) + git("add", appliedPatches.path.toString() + "/*").runSilently() + git("add", unappliedPatches.path.toString() + "/*").runSilently() + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000000..7a2b3bf89e78 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,10 @@ +group=io.papermc.paper +version=1.21.4-R0.1-SNAPSHOT +mcVersion=1.21.4 + +# Set to true while updating Minecraft version +updatingMinecraft=false + +org.gradle.caching=true +org.gradle.parallel=true +org.gradle.vfs.watch=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000000..a4b76b9530d6 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..e2847c820046 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 000000000000..f5feea6d6b11 --- /dev/null +++ b/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000000..9d21a21834d5 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/licenses/GPL.md b/licenses/GPL.md index 01a7a8018420..2fb2e74d8d7f 100644 --- a/licenses/GPL.md +++ b/licenses/GPL.md @@ -672,4 +672,4 @@ program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, -please read . \ No newline at end of file +please read . diff --git a/paper b/paper deleted file mode 100755 index a397d2786b9f..000000000000 --- a/paper +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env bash - -# resolve shell-specifics -case "$(echo "$SHELL" | sed -E 's|/usr(/local)?||g')" in - "/bin/zsh") - RCPATH="$HOME/.zshrc" - SOURCE="${BASH_SOURCE[0]:-${(%):-%N}}" - ;; - *) - RCPATH="$HOME/.bashrc" - if [[ -f "$HOME/.bash_aliases" ]]; then - RCPATH="$HOME/.bash_aliases" - fi - SOURCE="${BASH_SOURCE[0]}" - ;; -esac - -# get base dir regardless of execution location -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}") -basedir=$(dirname "$SOURCE") -gitcmd="git -c commit.gpgsign=false" - -source "$basedir/scripts/functions.sh" - -"$basedir"/scripts/requireDeps.sh || exit 1 - -failed=0 -case "$1" in - "rb" | "rbp" | "rebuild") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" $2 || exit 1 - ) || failed=1 - ;; - "rbf" | "rbfull") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" "nofilter" || exit 1 - ) || failed=1 - ;; - "p" | "patch") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "j" | "jar") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" || exit 1 - ) || failed=1 - ;; - "b" | "build") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - (cd Paper-API ; mvn clean install) || exit 1 - (cd Paper-MojangAPI ; mvn clean install) || exit 1 - (cd Paper-Server ; mvn clean package) || exit 1 - echo "Paper jar successfully built" - ls -la Paper-Server/target/paper*.jar - ) || failed=1 - ;; - "i" | "install") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - mvn clean install || exit 1 - echo "Paper jar successfully built and installed to local repo" - ) || failed=1 - ;; - "pc" | "paperclip") - ( - set -e - cd "$basedir" - scripts/paperclip.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "make") - ( - if [[ "$2" = "bacon" ]] ; then - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" - fi - ) - ;; - "m" | "mcdev") - ( - set -e - cd "$basedir" - scripts/makemcdevsrc.sh "$basedir" - ) - ;; - "t" | "test" | "testserver") - ( - cd "$basedir" - shift - scripts/testServer.sh "$basedir" "$@" - ) - ;; - "td" | "testdir") - cd "${PAPER_TEST_DIR:-$basedir/work/test-server}" - ;; - "u" | "up" | "upstream") - ( - cd "$basedir" - scripts/upstreamMerge.sh "$basedir" "$2" - ) - ;; - "cu" | "commitup" | "commitupstream" | "upc" | "upcommit" | "upstreamcommit") - ( - cd "$basedir" - shift - scripts/upstreamCommit.sh "$@" - ) - ;; - "r" | "root") - cd "$basedir" - ;; - "a" | "api") - cd "$basedir/Paper-API" - ;; - "s" | "server") - cd "$basedir/Paper-Server" - ;; - "c" | "clean") - rm -rf Paper-API - rm -rf Paper-Server - rm -rf work - echo "Cleaned build files" - ;; - "con" | "continue") - if [ -d ".git/rebase-apply" ]; then - git -c commit.gpgsign=false am --continue - elif [ -d ".git/rebase-merge" ]; then - git -c commit.gpgsign=false rebase --continue - fi - ;; - "e" | "edit") - case "$2" in - "s" | "server") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-Server" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-Server" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "a" | "api") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-API" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-API" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "c" | "continue") - cd "$( < "$basedir/work/Temp/PAPER_LAST_EDIT")" - rm -f "$basedir/work/Temp/PAPER_LAST_EDIT" - ( - set -e - - $gitcmd add . - $gitcmd commit --amend - $gitcmd rebase --continue - - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" - ) - ;; - *) - echo "You must edit either the api or server." - ;; - esac - ;; - "setup") - if [[ -f "$RCPATH" ]] ; then - NAME="paper" - if [[ ! -z "${2+x}" ]] ; then - NAME="$2" - fi - (grep "alias $NAME=" "$RCPATH" > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" "$RCPATH") || (echo "alias $NAME='. $SOURCE'" >> "$RCPATH") - alias "$NAME=. $SOURCE" - echo "You can now just type '$NAME' at any time to access the paper tool." - else - echo "We were unable to setup the paper build tool alias: $RCPATH is missing" - fi - ;; - *) - echo "PaperMC build tool command. This provides a variety of commands to build and manage the PaperMC build" - echo "environment. For all of the functionality of this command to be available, you must first run the" - echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup." - echo "" - echo " Normal commands:" - echo " * rb, rebuild | Rebuild patches, can be called from anywhere." - echo " * p, patch | Apply all patches to the project without building it. Can be run from anywhere." - echo " * j, jar | Apply all patches and build the project, paperclip.jar will be output. Can be run from anywhere." - echo " * i, install | Build and install paper into the local repo. Can be run from anywhere." - echo " * m, mcdev | Setup decompiled sources for non-modified NMS files to be imported into an IDE. Can be run from anywhere." - echo " * u, up, upstream | Updates the submodules used by Paper to their latest upstream versions." - echo " * upc, upstreamcommit | Creates the correctly-formatted upstream commit after updating upstream." - echo " * c, clean | Removes all generated files, Paper-API, Paper-Server, and work." - echo " * t, testserver | Run the test server with the set of plugins Paper uses as a basis for server tests." - echo " * con, continue | Shortcut command for running git am --continue, or git rebase --continue." - echo "" - echo " These commands require the setup command before use:" - echo " * r, root | Change directory to the root of the project." - echo " * a. api | Move to the Paper-API directory." - echo " * s, server | Move to the Paper-Server directory." - echo " * td, testdirectory | Move to the test-server directory." - echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\"" - echo " | respectively to edit the correct project. Use the argument \"continue\" after" - echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere." - echo "" - echo " * setup | Add an alias to $RCPATH to allow full functionality of this script. Run as:" - echo " | . ./paper setup" - echo " | After you run this command you'll be able to just run 'paper' from anywhere." - echo " | The default name for the resulting alias is 'paper', you can give an argument to override" - echo " | this default, such as:" - echo " | . ./paper setup example" - echo " | Which will allow you to run 'example' instead." - ;; -esac - -unset RCPATH -unset SOURCE -unset basedir -unset -f color -unset -f colorend -unset -f paperstash -unset -f paperunstash -if [[ "$failed" == "1" ]]; then - unset failed - false -else - unset failed - true -fi diff --git a/paper-api-generator/build.gradle.kts b/paper-api-generator/build.gradle.kts new file mode 100644 index 000000000000..e1e434773a4c --- /dev/null +++ b/paper-api-generator/build.gradle.kts @@ -0,0 +1,37 @@ +import io.papermc.paperweight.PaperweightSourceGeneratorHelper +import io.papermc.paperweight.extension.PaperweightSourceGeneratorExt +import io.papermc.paperweight.util.defaultJavaLauncher + +plugins { + java +} + +plugins.apply(PaperweightSourceGeneratorHelper::class) + +extensions.configure(PaperweightSourceGeneratorExt::class) { + atFile.set(projectDir.toPath().resolve("wideners.at").toFile()) +} + +dependencies { + implementation("com.squareup:javapoet:1.13.0") + implementation(project(":paper-api")) + implementation("io.github.classgraph:classgraph:4.8.47") + implementation("org.jetbrains:annotations:24.1.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") +} + +tasks.register("generate") { + dependsOn(tasks.check) + mainClass.set("io.papermc.generator.Main") + classpath(sourceSets.main.map { it.runtimeClasspath }) + args(projectDir.toPath().resolve("generated").toString()) + javaLauncher = javaToolchains.defaultJavaLauncher(project) +} + +tasks.test { + useJUnitPlatform() +} + +group = "io.papermc.paper" +version = "1.0-SNAPSHOT" diff --git a/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java new file mode 100644 index 000000000000..f15a7b4471cd --- /dev/null +++ b/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java @@ -0,0 +1,447 @@ +package com.destroystokyo.paper.entity.ai; + +import com.destroystokyo.paper.entity.RangedEntity; +import io.papermc.paper.entity.SchoolableFish; +import io.papermc.paper.generated.GeneratedFrom; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.AbstractSkeleton; +import org.bukkit.entity.AbstractVillager; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Bee; +import org.bukkit.entity.Blaze; +import org.bukkit.entity.Cat; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Dolphin; +import org.bukkit.entity.Drowned; +import org.bukkit.entity.Enderman; +import org.bukkit.entity.Evoker; +import org.bukkit.entity.Fish; +import org.bukkit.entity.Fox; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.Guardian; +import org.bukkit.entity.Illager; +import org.bukkit.entity.Illusioner; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Llama; +import org.bukkit.entity.Mob; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Ocelot; +import org.bukkit.entity.Panda; +import org.bukkit.entity.Parrot; +import org.bukkit.entity.Phantom; +import org.bukkit.entity.PolarBear; +import org.bukkit.entity.PufferFish; +import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Raider; +import org.bukkit.entity.Shulker; +import org.bukkit.entity.Silverfish; +import org.bukkit.entity.SkeletonHorse; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Spellcaster; +import org.bukkit.entity.Spider; +import org.bukkit.entity.Squid; +import org.bukkit.entity.Strider; +import org.bukkit.entity.Tameable; +import org.bukkit.entity.Turtle; +import org.bukkit.entity.Vex; +import org.bukkit.entity.Vindicator; +import org.bukkit.entity.WanderingTrader; +import org.bukkit.entity.Wither; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.Zombie; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for Mob Goals. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +public interface VanillaGoal extends Goal { + GoalKey RANDOM_STAND = create("random_stand", AbstractHorse.class); + + GoalKey RUN_AROUND_LIKE_CRAZY = create("run_around_like_crazy", AbstractHorse.class); + + GoalKey ABSTRACT_SKELETON_MELEE = create("abstract_skeleton_melee", AbstractSkeleton.class); + + GoalKey LOOK_AT_TRADING_PLAYER = create("look_at_trading_player", AbstractVillager.class); + + GoalKey TRADE_WITH_PLAYER = create("trade_with_player", AbstractVillager.class); + + GoalKey BREED = create("breed", Animals.class); + + GoalKey FOLLOW_PARENT = create("follow_parent", Animals.class); + + GoalKey BEE_ATTACK = create("bee_attack", Bee.class); + + GoalKey BEE_BECOME_ANGRY = create("bee_become_angry", Bee.class); + + GoalKey BEE_ENTER_HIVE = create("bee_enter_hive", Bee.class); + + GoalKey BEE_GO_TO_HIVE = create("bee_go_to_hive", Bee.class); + + GoalKey BEE_GO_TO_KNOWN_FLOWER = create("bee_go_to_known_flower", Bee.class); + + GoalKey BEE_GROW_CROP = create("bee_grow_crop", Bee.class); + + GoalKey BEE_HURT_BY_OTHER = create("bee_hurt_by_other", Bee.class); + + GoalKey BEE_LOCATE_HIVE = create("bee_locate_hive", Bee.class); + + GoalKey BEE_POLLINATE = create("bee_pollinate", Bee.class); + + GoalKey BEE_WANDER = create("bee_wander", Bee.class); + + GoalKey VALIDATE_FLOWER = create("validate_flower", Bee.class); + + GoalKey VALIDATE_HIVE = create("validate_hive", Bee.class); + + GoalKey BLAZE_ATTACK = create("blaze_attack", Blaze.class); + + GoalKey CAT_AVOID_ENTITY = create("cat_avoid_entity", Cat.class); + + GoalKey CAT_LIE_ON_BED = create("cat_lie_on_bed", Cat.class); + + GoalKey CAT_RELAX_ON_OWNER = create("cat_relax_on_owner", Cat.class); + + GoalKey CAT_SIT_ON_BLOCK = create("cat_sit_on_block", Cat.class); + + GoalKey CAT_TEMPT = create("cat_tempt", Cat.class); + + GoalKey AVOID_ENTITY = create("avoid_entity", Creature.class); + + GoalKey BREATH_AIR = create("breath_air", Creature.class); + + GoalKey DROWNED_GO_TO_WATER = create("drowned_go_to_water", Creature.class); + + GoalKey FLEE_SUN = create("flee_sun", Creature.class); + + GoalKey FOLLOW_BOAT = create("follow_boat", Creature.class); + + GoalKey GOLEM_RANDOM_STROLL_IN_VILLAGE = create("golem_random_stroll_in_village", Creature.class); + + GoalKey HURT_BY = create("hurt_by", Creature.class); + + GoalKey MELEE_ATTACK = create("melee_attack", Creature.class); + + GoalKey MOVE_BACK_TO_VILLAGE = create("move_back_to_village", Creature.class); + + GoalKey MOVE_THROUGH_VILLAGE = create("move_through_village", Creature.class); + + GoalKey MOVE_TOWARDS = create("move_towards", Creature.class); + + GoalKey MOVE_TOWARDS_RESTRICTION = create("move_towards_restriction", Creature.class); + + GoalKey PANIC = create("panic", Creature.class); + + GoalKey PARROT_WANDER = create("parrot_wander", Creature.class); + + GoalKey RANDOM_STROLL = create("random_stroll", Creature.class); + + GoalKey RANDOM_SWIMMING = create("random_swimming", Creature.class); + + GoalKey REMOVE_BLOCK = create("remove_block", Creature.class); + + GoalKey RESTRICT_SUN = create("restrict_sun", Creature.class); + + GoalKey STROLL_THROUGH_VILLAGE = create("stroll_through_village", Creature.class); + + GoalKey TEMPT = create("tempt", Creature.class); + + GoalKey TRY_FIND_WATER = create("try_find_water", Creature.class); + + GoalKey WATER_AVOIDING_RANDOM_FLYING = create("water_avoiding_random_flying", Creature.class); + + GoalKey WATER_AVOIDING_RANDOM_STROLL = create("water_avoiding_random_stroll", Creature.class); + + GoalKey SWELL = create("swell", Creeper.class); + + GoalKey DOLPHIN_JUMP = create("dolphin_jump", Dolphin.class); + + GoalKey DOLPHIN_SWIM_TO_TREASURE = create("dolphin_swim_to_treasure", Dolphin.class); + + GoalKey DOLPHIN_SWIM_WITH_PLAYER = create("dolphin_swim_with_player", Dolphin.class); + + GoalKey PLAY_WITH_ITEMS = create("play_with_items", Dolphin.class); + + GoalKey DROWNED_ATTACK = create("drowned_attack", Drowned.class); + + GoalKey DROWNED_GO_TO_BEACH = create("drowned_go_to_beach", Drowned.class); + + GoalKey DROWNED_SWIM_UP = create("drowned_swim_up", Drowned.class); + + GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = create("enderman_freeze_when_looked_at", Enderman.class); + + GoalKey ENDERMAN_LEAVE_BLOCK = create("enderman_leave_block", Enderman.class); + + GoalKey ENDERMAN_LOOK_FOR_PLAYER = create("enderman_look_for_player", Enderman.class); + + GoalKey ENDERMAN_TAKE_BLOCK = create("enderman_take_block", Enderman.class); + + GoalKey EVOKER_ATTACK_SPELL = create("evoker_attack_spell", Evoker.class); + + GoalKey EVOKER_CASTING_SPELL = create("evoker_casting_spell", Evoker.class); + + GoalKey EVOKER_SUMMON_SPELL = create("evoker_summon_spell", Evoker.class); + + GoalKey EVOKER_WOLOLO_SPELL = create("evoker_wololo_spell", Evoker.class); + + GoalKey FISH_SWIM = create("fish_swim", Fish.class); + + GoalKey DEFEND_TRUSTED = create("defend_trusted", Fox.class); + + GoalKey FACEPLANT = create("faceplant", Fox.class); + + GoalKey FOX_BREED = create("fox_breed", Fox.class); + + GoalKey FOX_EAT_BERRIES = create("fox_eat_berries", Fox.class); + + GoalKey FOX_FLOAT = create("fox_float", Fox.class); + + GoalKey FOX_FOLLOW_PARENT = create("fox_follow_parent", Fox.class); + + GoalKey FOX_LOOK_AT_PLAYER = create("fox_look_at_player", Fox.class); + + GoalKey FOX_MELEE_ATTACK = create("fox_melee_attack", Fox.class); + + GoalKey FOX_PANIC = create("fox_panic", Fox.class); + + GoalKey FOX_POUNCE = create("fox_pounce", Fox.class); + + GoalKey FOX_SEARCH_FOR_ITEMS = create("fox_search_for_items", Fox.class); + + GoalKey FOX_STROLL_THROUGH_VILLAGE = create("fox_stroll_through_village", Fox.class); + + GoalKey PERCH_AND_SEARCH = create("perch_and_search", Fox.class); + + GoalKey SEEK_SHELTER = create("seek_shelter", Fox.class); + + GoalKey SLEEP = create("sleep", Fox.class); + + GoalKey STALK_PREY = create("stalk_prey", Fox.class); + + GoalKey GHAST_LOOK = create("ghast_look", Ghast.class); + + GoalKey GHAST_SHOOT_FIREBALL = create("ghast_shoot_fireball", Ghast.class); + + GoalKey RANDOM_FLOAT_AROUND = create("random_float_around", Ghast.class); + + GoalKey GUARDIAN_ATTACK = create("guardian_attack", Guardian.class); + + GoalKey HOLD_GROUND_ATTACK = create("hold_ground_attack", Illager.class); + + GoalKey RAIDER_OPEN_DOOR = create("raider_open_door", Illager.class); + + GoalKey ILLUSIONER_BLINDNESS_SPELL = create("illusioner_blindness_spell", Illusioner.class); + + GoalKey ILLUSIONER_MIRROR_SPELL = create("illusioner_mirror_spell", Illusioner.class); + + GoalKey DEFEND_VILLAGE = create("defend_village", IronGolem.class); + + GoalKey OFFER_FLOWER = create("offer_flower", IronGolem.class); + + GoalKey LLAMA_ATTACK_WOLF = create("llama_attack_wolf", Llama.class); + + GoalKey LLAMA_FOLLOW_CARAVAN = create("llama_follow_caravan", Llama.class); + + GoalKey LLAMA_HURT_BY = create("llama_hurt_by", Llama.class); + + GoalKey TRADER_LLAMA_DEFEND_WANDERING_TRADER = create("trader_llama_defend_wandering_trader", Llama.class); + + GoalKey BREAK_DOOR = create("break_door", Mob.class); + + GoalKey CLIMB_ON_TOP_OF_POWDER_SNOW = create("climb_on_top_of_powder_snow", Mob.class); + + GoalKey EAT_BLOCK = create("eat_block", Mob.class); + + GoalKey FLOAT = create("float", Mob.class); + + GoalKey FOLLOW_MOB = create("follow_mob", Mob.class); + + GoalKey INTERACT = create("interact", Mob.class); + + GoalKey LEAP_AT = create("leap_at", Mob.class); + + GoalKey LOOK_AT_PLAYER = create("look_at_player", Mob.class); + + GoalKey NEAREST_ATTACKABLE = create("nearest_attackable", Mob.class); + + GoalKey OCELOT_ATTACK = create("ocelot_attack", Mob.class); + + GoalKey OPEN_DOOR = create("open_door", Mob.class); + + GoalKey RANDOM_LOOK_AROUND = create("random_look_around", Mob.class); + + GoalKey RESET_UNIVERSAL_ANGER = create("reset_universal_anger", Mob.class); + + GoalKey USE_ITEM = create("use_item", Mob.class); + + GoalKey VINDICATOR_BREAK_DOOR = create("vindicator_break_door", Mob.class); + + GoalKey RANGED_BOW_ATTACK = create("ranged_bow_attack", Monster.class); + + GoalKey RANGED_CROSSBOW_ATTACK = create("ranged_crossbow_attack", Monster.class); + + GoalKey OCELOT_AVOID_ENTITY = create("ocelot_avoid_entity", Ocelot.class); + + GoalKey OCELOT_TEMPT = create("ocelot_tempt", Ocelot.class); + + GoalKey PANDA_ATTACK = create("panda_attack", Panda.class); + + GoalKey PANDA_AVOID = create("panda_avoid", Panda.class); + + GoalKey PANDA_BREED = create("panda_breed", Panda.class); + + GoalKey PANDA_HURT_BY = create("panda_hurt_by", Panda.class); + + GoalKey PANDA_LIE_ON_BACK = create("panda_lie_on_back", Panda.class); + + GoalKey PANDA_LOOK_AT_PLAYER = create("panda_look_at_player", Panda.class); + + GoalKey PANDA_PANIC = create("panda_panic", Panda.class); + + GoalKey PANDA_ROLL = create("panda_roll", Panda.class); + + GoalKey PANDA_SIT = create("panda_sit", Panda.class); + + GoalKey PANDA_SNEEZE = create("panda_sneeze", Panda.class); + + GoalKey LAND_ON_OWNERS_SHOULDER = create("land_on_owners_shoulder", Parrot.class); + + GoalKey PHANTOM_ATTACK_PLAYER = create("phantom_attack_player", Phantom.class); + + GoalKey PHANTOM_ATTACK_STRATEGY = create("phantom_attack_strategy", Phantom.class); + + GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = create("phantom_circle_around_anchor", Phantom.class); + + GoalKey PHANTOM_SWEEP_ATTACK = create("phantom_sweep_attack", Phantom.class); + + GoalKey POLAR_BEAR_ATTACK_PLAYERS = create("polar_bear_attack_players", PolarBear.class); + + GoalKey POLAR_BEAR_HURT_BY = create("polar_bear_hurt_by", PolarBear.class); + + GoalKey POLAR_BEAR_MELEE_ATTACK = create("polar_bear_melee_attack", PolarBear.class); + + GoalKey PUFFERFISH_PUFF = create("pufferfish_puff", PufferFish.class); + + GoalKey RABBIT_AVOID_ENTITY = create("rabbit_avoid_entity", Rabbit.class); + + GoalKey RABBIT_PANIC = create("rabbit_panic", Rabbit.class); + + GoalKey RAID_GARDEN = create("raid_garden", Rabbit.class); + + GoalKey LONG_DISTANCE_PATROL = create("long_distance_patrol", Raider.class); + + GoalKey NEAREST_ATTACKABLE_WITCH = create("nearest_attackable_witch", Raider.class); + + GoalKey NEAREST_HEALABLE_RAIDER = create("nearest_healable_raider", Raider.class); + + GoalKey OBTAIN_RAID_LEADER_BANNER = create("obtain_raid_leader_banner", Raider.class); + + GoalKey PATHFIND_TO_RAID = create("pathfind_to_raid", Raider.class); + + GoalKey RAIDER_CELEBRATION = create("raider_celebration", Raider.class); + + GoalKey RAIDER_MOVE_THROUGH_VILLAGE = create("raider_move_through_village", Raider.class); + + GoalKey DROWNED_TRIDENT_ATTACK = create("drowned_trident_attack", RangedEntity.class); + + GoalKey RANGED_ATTACK = create("ranged_attack", RangedEntity.class); + + GoalKey FOLLOW_FLOCK_LEADER = create("follow_flock_leader", SchoolableFish.class); + + GoalKey SHULKER_ATTACK = create("shulker_attack", Shulker.class); + + GoalKey SHULKER_DEFENSE_ATTACK = create("shulker_defense_attack", Shulker.class); + + GoalKey SHULKER_NEAREST_ATTACK = create("shulker_nearest_attack", Shulker.class); + + GoalKey SHULKER_PEEK = create("shulker_peek", Shulker.class); + + GoalKey SILVERFISH_MERGE_WITH_STONE = create("silverfish_merge_with_stone", Silverfish.class); + + GoalKey SILVERFISH_WAKE_UP_FRIENDS = create("silverfish_wake_up_friends", Silverfish.class); + + GoalKey SKELETON_TRAP = create("skeleton_trap", SkeletonHorse.class); + + GoalKey SLIME_ATTACK = create("slime_attack", Slime.class); + + GoalKey SLIME_FLOAT = create("slime_float", Slime.class); + + GoalKey SLIME_KEEP_ON_JUMPING = create("slime_keep_on_jumping", Slime.class); + + GoalKey SLIME_RANDOM_DIRECTION = create("slime_random_direction", Slime.class); + + GoalKey SPELLCASTER_CASTING_SPELL = create("spellcaster_casting_spell", Spellcaster.class); + + GoalKey SPIDER = create("spider", Spider.class); + + GoalKey SPIDER_ATTACK = create("spider_attack", Spider.class); + + GoalKey SQUID_FLEE = create("squid_flee", Squid.class); + + GoalKey SQUID_RANDOM_MOVEMENT = create("squid_random_movement", Squid.class); + + GoalKey STRIDER_GO_TO_LAVA = create("strider_go_to_lava", Strider.class); + + GoalKey FOLLOW_OWNER = create("follow_owner", Tameable.class); + + GoalKey NON_TAME_RANDOM = create("non_tame_random", Tameable.class); + + GoalKey OWNER_HURT = create("owner_hurt", Tameable.class); + + GoalKey OWNER_HURT_BY = create("owner_hurt_by", Tameable.class); + + GoalKey SIT_WHEN_ORDERED_TO = create("sit_when_ordered_to", Tameable.class); + + GoalKey TAMABLE_ANIMAL_PANIC = create("tamable_animal_panic", Tameable.class); + + GoalKey TURTLE_BREED = create("turtle_breed", Turtle.class); + + GoalKey TURTLE_GO_HOME = create("turtle_go_home", Turtle.class); + + GoalKey TURTLE_GO_TO_WATER = create("turtle_go_to_water", Turtle.class); + + GoalKey TURTLE_LAY_EGG = create("turtle_lay_egg", Turtle.class); + + GoalKey TURTLE_PANIC = create("turtle_panic", Turtle.class); + + GoalKey TURTLE_RANDOM_STROLL = create("turtle_random_stroll", Turtle.class); + + GoalKey TURTLE_TRAVEL = create("turtle_travel", Turtle.class); + + GoalKey VEX_CHARGE_ATTACK = create("vex_charge_attack", Vex.class); + + GoalKey VEX_COPY_OWNER = create("vex_copy_owner", Vex.class); + + GoalKey VEX_RANDOM_MOVE = create("vex_random_move", Vex.class); + + GoalKey VINDICATOR_JOHNNY_ATTACK = create("vindicator_johnny_attack", Vindicator.class); + + GoalKey WANDER_TO_POSITION = create("wander_to_position", WanderingTrader.class); + + GoalKey WITHER_DO_NOTHING = create("wither_do_nothing", Wither.class); + + GoalKey BEG = create("beg", Wolf.class); + + GoalKey WOLF_AVOID_ENTITY = create("wolf_avoid_entity", Wolf.class); + + GoalKey ZOMBIE_ATTACK = create("zombie_attack", Zombie.class); + + GoalKey ZOMBIE_ATTACK_TURTLE_EGG = create("zombie_attack_turtle_egg", Zombie.class); + + private static GoalKey create(final String key, final Class type) { + return GoalKey.of(type, NamespacedKey.minecraft(key)); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/AttributeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/AttributeKeys.java new file mode 100644 index 000000000000..be67e86206c2 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/AttributeKeys.java @@ -0,0 +1,260 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.attribute.Attribute; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#ATTRIBUTE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class AttributeKeys { + /** + * {@code minecraft:armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMOR = create(key("armor")); + + /** + * {@code minecraft:armor_toughness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMOR_TOUGHNESS = create(key("armor_toughness")); + + /** + * {@code minecraft:attack_damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ATTACK_DAMAGE = create(key("attack_damage")); + + /** + * {@code minecraft:attack_knockback} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ATTACK_KNOCKBACK = create(key("attack_knockback")); + + /** + * {@code minecraft:attack_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ATTACK_SPEED = create(key("attack_speed")); + + /** + * {@code minecraft:block_break_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BREAK_SPEED = create(key("block_break_speed")); + + /** + * {@code minecraft:block_interaction_range} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_INTERACTION_RANGE = create(key("block_interaction_range")); + + /** + * {@code minecraft:burning_time} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURNING_TIME = create(key("burning_time")); + + /** + * {@code minecraft:entity_interaction_range} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_INTERACTION_RANGE = create(key("entity_interaction_range")); + + /** + * {@code minecraft:explosion_knockback_resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLOSION_KNOCKBACK_RESISTANCE = create(key("explosion_knockback_resistance")); + + /** + * {@code minecraft:fall_damage_multiplier} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALL_DAMAGE_MULTIPLIER = create(key("fall_damage_multiplier")); + + /** + * {@code minecraft:flying_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLYING_SPEED = create(key("flying_speed")); + + /** + * {@code minecraft:follow_range} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FOLLOW_RANGE = create(key("follow_range")); + + /** + * {@code minecraft:gravity} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAVITY = create(key("gravity")); + + /** + * {@code minecraft:jump_strength} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUMP_STRENGTH = create(key("jump_strength")); + + /** + * {@code minecraft:knockback_resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KNOCKBACK_RESISTANCE = create(key("knockback_resistance")); + + /** + * {@code minecraft:luck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUCK = create(key("luck")); + + /** + * {@code minecraft:max_absorption} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAX_ABSORPTION = create(key("max_absorption")); + + /** + * {@code minecraft:max_health} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAX_HEALTH = create(key("max_health")); + + /** + * {@code minecraft:mining_efficiency} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINING_EFFICIENCY = create(key("mining_efficiency")); + + /** + * {@code minecraft:movement_efficiency} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOVEMENT_EFFICIENCY = create(key("movement_efficiency")); + + /** + * {@code minecraft:movement_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOVEMENT_SPEED = create(key("movement_speed")); + + /** + * {@code minecraft:oxygen_bonus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXYGEN_BONUS = create(key("oxygen_bonus")); + + /** + * {@code minecraft:safe_fall_distance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAFE_FALL_DISTANCE = create(key("safe_fall_distance")); + + /** + * {@code minecraft:scale} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCALE = create(key("scale")); + + /** + * {@code minecraft:sneaking_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNEAKING_SPEED = create(key("sneaking_speed")); + + /** + * {@code minecraft:spawn_reinforcements} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPAWN_REINFORCEMENTS = create(key("spawn_reinforcements")); + + /** + * {@code minecraft:step_height} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STEP_HEIGHT = create(key("step_height")); + + /** + * {@code minecraft:submerged_mining_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUBMERGED_MINING_SPEED = create(key("submerged_mining_speed")); + + /** + * {@code minecraft:sweeping_damage_ratio} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEEPING_DAMAGE_RATIO = create(key("sweeping_damage_ratio")); + + /** + * {@code minecraft:tempt_range} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TEMPT_RANGE = create(key("tempt_range")); + + /** + * {@code minecraft:water_movement_efficiency} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER_MOVEMENT_EFFICIENCY = create(key("water_movement_efficiency")); + + private AttributeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.ATTRIBUTE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/BannerPatternKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/BannerPatternKeys.java new file mode 100644 index 000000000000..23e1145e04bd --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/BannerPatternKeys.java @@ -0,0 +1,344 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.banner.PatternType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BANNER_PATTERN}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BannerPatternKeys { + /** + * {@code minecraft:base} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASE = create(key("base")); + + /** + * {@code minecraft:border} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BORDER = create(key("border")); + + /** + * {@code minecraft:bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICKS = create(key("bricks")); + + /** + * {@code minecraft:circle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CIRCLE = create(key("circle")); + + /** + * {@code minecraft:creeper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER = create(key("creeper")); + + /** + * {@code minecraft:cross} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CROSS = create(key("cross")); + + /** + * {@code minecraft:curly_border} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CURLY_BORDER = create(key("curly_border")); + + /** + * {@code minecraft:diagonal_left} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAGONAL_LEFT = create(key("diagonal_left")); + + /** + * {@code minecraft:diagonal_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAGONAL_RIGHT = create(key("diagonal_right")); + + /** + * {@code minecraft:diagonal_up_left} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAGONAL_UP_LEFT = create(key("diagonal_up_left")); + + /** + * {@code minecraft:diagonal_up_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAGONAL_UP_RIGHT = create(key("diagonal_up_right")); + + /** + * {@code minecraft:flow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOW = create(key("flow")); + + /** + * {@code minecraft:flower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER = create(key("flower")); + + /** + * {@code minecraft:globe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOBE = create(key("globe")); + + /** + * {@code minecraft:gradient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRADIENT = create(key("gradient")); + + /** + * {@code minecraft:gradient_up} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRADIENT_UP = create(key("gradient_up")); + + /** + * {@code minecraft:guster} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GUSTER = create(key("guster")); + + /** + * {@code minecraft:half_horizontal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HALF_HORIZONTAL = create(key("half_horizontal")); + + /** + * {@code minecraft:half_horizontal_bottom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HALF_HORIZONTAL_BOTTOM = create(key("half_horizontal_bottom")); + + /** + * {@code minecraft:half_vertical} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HALF_VERTICAL = create(key("half_vertical")); + + /** + * {@code minecraft:half_vertical_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HALF_VERTICAL_RIGHT = create(key("half_vertical_right")); + + /** + * {@code minecraft:mojang} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOJANG = create(key("mojang")); + + /** + * {@code minecraft:piglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN = create(key("piglin")); + + /** + * {@code minecraft:rhombus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RHOMBUS = create(key("rhombus")); + + /** + * {@code minecraft:skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKULL = create(key("skull")); + + /** + * {@code minecraft:small_stripes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_STRIPES = create(key("small_stripes")); + + /** + * {@code minecraft:square_bottom_left} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SQUARE_BOTTOM_LEFT = create(key("square_bottom_left")); + + /** + * {@code minecraft:square_bottom_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SQUARE_BOTTOM_RIGHT = create(key("square_bottom_right")); + + /** + * {@code minecraft:square_top_left} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SQUARE_TOP_LEFT = create(key("square_top_left")); + + /** + * {@code minecraft:square_top_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SQUARE_TOP_RIGHT = create(key("square_top_right")); + + /** + * {@code minecraft:straight_cross} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRAIGHT_CROSS = create(key("straight_cross")); + + /** + * {@code minecraft:stripe_bottom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_BOTTOM = create(key("stripe_bottom")); + + /** + * {@code minecraft:stripe_center} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_CENTER = create(key("stripe_center")); + + /** + * {@code minecraft:stripe_downleft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_DOWNLEFT = create(key("stripe_downleft")); + + /** + * {@code minecraft:stripe_downright} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_DOWNRIGHT = create(key("stripe_downright")); + + /** + * {@code minecraft:stripe_left} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_LEFT = create(key("stripe_left")); + + /** + * {@code minecraft:stripe_middle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_MIDDLE = create(key("stripe_middle")); + + /** + * {@code minecraft:stripe_right} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_RIGHT = create(key("stripe_right")); + + /** + * {@code minecraft:stripe_top} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPE_TOP = create(key("stripe_top")); + + /** + * {@code minecraft:triangle_bottom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIANGLE_BOTTOM = create(key("triangle_bottom")); + + /** + * {@code minecraft:triangle_top} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIANGLE_TOP = create(key("triangle_top")); + + /** + * {@code minecraft:triangles_bottom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIANGLES_BOTTOM = create(key("triangles_bottom")); + + /** + * {@code minecraft:triangles_top} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIANGLES_TOP = create(key("triangles_top")); + + private BannerPatternKeys() { + } + + /** + * Creates a key for {@link PatternType} in the registry {@code minecraft:banner_pattern}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.BANNER_PATTERN, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java new file mode 100644 index 000000000000..bf0c0f6d9b9a --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java @@ -0,0 +1,498 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.Biome; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BIOME}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BiomeKeys { + /** + * {@code minecraft:badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BADLANDS = create(key("badlands")); + + /** + * {@code minecraft:bamboo_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_JUNGLE = create(key("bamboo_jungle")); + + /** + * {@code minecraft:basalt_deltas} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASALT_DELTAS = create(key("basalt_deltas")); + + /** + * {@code minecraft:beach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEACH = create(key("beach")); + + /** + * {@code minecraft:birch_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FOREST = create(key("birch_forest")); + + /** + * {@code minecraft:cherry_grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_GROVE = create(key("cherry_grove")); + + /** + * {@code minecraft:cold_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COLD_OCEAN = create(key("cold_ocean")); + + /** + * {@code minecraft:crimson_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FOREST = create(key("crimson_forest")); + + /** + * {@code minecraft:dark_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_FOREST = create(key("dark_forest")); + + /** + * {@code minecraft:deep_cold_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_COLD_OCEAN = create(key("deep_cold_ocean")); + + /** + * {@code minecraft:deep_dark} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_DARK = create(key("deep_dark")); + + /** + * {@code minecraft:deep_frozen_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_FROZEN_OCEAN = create(key("deep_frozen_ocean")); + + /** + * {@code minecraft:deep_lukewarm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_LUKEWARM_OCEAN = create(key("deep_lukewarm_ocean")); + + /** + * {@code minecraft:deep_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_OCEAN = create(key("deep_ocean")); + + /** + * {@code minecraft:desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT = create(key("desert")); + + /** + * {@code minecraft:dripstone_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIPSTONE_CAVES = create(key("dripstone_caves")); + + /** + * {@code minecraft:end_barrens} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_BARRENS = create(key("end_barrens")); + + /** + * {@code minecraft:end_highlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_HIGHLANDS = create(key("end_highlands")); + + /** + * {@code minecraft:end_midlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_MIDLANDS = create(key("end_midlands")); + + /** + * {@code minecraft:eroded_badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ERODED_BADLANDS = create(key("eroded_badlands")); + + /** + * {@code minecraft:flower_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER_FOREST = create(key("flower_forest")); + + /** + * {@code minecraft:forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FOREST = create(key("forest")); + + /** + * {@code minecraft:frozen_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_OCEAN = create(key("frozen_ocean")); + + /** + * {@code minecraft:frozen_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_PEAKS = create(key("frozen_peaks")); + + /** + * {@code minecraft:frozen_river} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_RIVER = create(key("frozen_river")); + + /** + * {@code minecraft:grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GROVE = create(key("grove")); + + /** + * {@code minecraft:ice_spikes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ICE_SPIKES = create(key("ice_spikes")); + + /** + * {@code minecraft:jagged_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JAGGED_PEAKS = create(key("jagged_peaks")); + + /** + * {@code minecraft:jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE = create(key("jungle")); + + /** + * {@code minecraft:lukewarm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUKEWARM_OCEAN = create(key("lukewarm_ocean")); + + /** + * {@code minecraft:lush_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUSH_CAVES = create(key("lush_caves")); + + /** + * {@code minecraft:mangrove_swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SWAMP = create(key("mangrove_swamp")); + + /** + * {@code minecraft:meadow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MEADOW = create(key("meadow")); + + /** + * {@code minecraft:mushroom_fields} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSHROOM_FIELDS = create(key("mushroom_fields")); + + /** + * {@code minecraft:nether_wastes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WASTES = create(key("nether_wastes")); + + /** + * {@code minecraft:ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN = create(key("ocean")); + + /** + * {@code minecraft:old_growth_birch_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_BIRCH_FOREST = create(key("old_growth_birch_forest")); + + /** + * {@code minecraft:old_growth_pine_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_PINE_TAIGA = create(key("old_growth_pine_taiga")); + + /** + * {@code minecraft:old_growth_spruce_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_SPRUCE_TAIGA = create(key("old_growth_spruce_taiga")); + + /** + * {@code minecraft:pale_garden} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_GARDEN = create(key("pale_garden")); + + /** + * {@code minecraft:plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAINS = create(key("plains")); + + /** + * {@code minecraft:river} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIVER = create(key("river")); + + /** + * {@code minecraft:savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAVANNA = create(key("savanna")); + + /** + * {@code minecraft:savanna_plateau} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAVANNA_PLATEAU = create(key("savanna_plateau")); + + /** + * {@code minecraft:small_end_islands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_END_ISLANDS = create(key("small_end_islands")); + + /** + * {@code minecraft:snowy_beach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_BEACH = create(key("snowy_beach")); + + /** + * {@code minecraft:snowy_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_PLAINS = create(key("snowy_plains")); + + /** + * {@code minecraft:snowy_slopes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_SLOPES = create(key("snowy_slopes")); + + /** + * {@code minecraft:snowy_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_TAIGA = create(key("snowy_taiga")); + + /** + * {@code minecraft:soul_sand_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SAND_VALLEY = create(key("soul_sand_valley")); + + /** + * {@code minecraft:sparse_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPARSE_JUNGLE = create(key("sparse_jungle")); + + /** + * {@code minecraft:stony_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONY_PEAKS = create(key("stony_peaks")); + + /** + * {@code minecraft:stony_shore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONY_SHORE = create(key("stony_shore")); + + /** + * {@code minecraft:sunflower_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNFLOWER_PLAINS = create(key("sunflower_plains")); + + /** + * {@code minecraft:swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP = create(key("swamp")); + + /** + * {@code minecraft:taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TAIGA = create(key("taiga")); + + /** + * {@code minecraft:the_end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THE_END = create(key("the_end")); + + /** + * {@code minecraft:the_void} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THE_VOID = create(key("the_void")); + + /** + * {@code minecraft:warm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARM_OCEAN = create(key("warm_ocean")); + + /** + * {@code minecraft:warped_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FOREST = create(key("warped_forest")); + + /** + * {@code minecraft:windswept_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_FOREST = create(key("windswept_forest")); + + /** + * {@code minecraft:windswept_gravelly_hills} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_GRAVELLY_HILLS = create(key("windswept_gravelly_hills")); + + /** + * {@code minecraft:windswept_hills} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_HILLS = create(key("windswept_hills")); + + /** + * {@code minecraft:windswept_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_SAVANNA = create(key("windswept_savanna")); + + /** + * {@code minecraft:wooded_badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODED_BADLANDS = create(key("wooded_badlands")); + + private BiomeKeys() { + } + + /** + * Creates a key for {@link Biome} in the registry {@code minecraft:worldgen/biome}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.BIOME, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/BlockTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/BlockTypeKeys.java new file mode 100644 index 000000000000..b71182ed34bf --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/BlockTypeKeys.java @@ -0,0 +1,7701 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.BlockType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BLOCK}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BlockTypeKeys { + /** + * {@code minecraft:acacia_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_BUTTON = create(key("acacia_button")); + + /** + * {@code minecraft:acacia_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_DOOR = create(key("acacia_door")); + + /** + * {@code minecraft:acacia_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_FENCE = create(key("acacia_fence")); + + /** + * {@code minecraft:acacia_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_FENCE_GATE = create(key("acacia_fence_gate")); + + /** + * {@code minecraft:acacia_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_HANGING_SIGN = create(key("acacia_hanging_sign")); + + /** + * {@code minecraft:acacia_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_LEAVES = create(key("acacia_leaves")); + + /** + * {@code minecraft:acacia_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_LOG = create(key("acacia_log")); + + /** + * {@code minecraft:acacia_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_PLANKS = create(key("acacia_planks")); + + /** + * {@code minecraft:acacia_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_PRESSURE_PLATE = create(key("acacia_pressure_plate")); + + /** + * {@code minecraft:acacia_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SAPLING = create(key("acacia_sapling")); + + /** + * {@code minecraft:acacia_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SIGN = create(key("acacia_sign")); + + /** + * {@code minecraft:acacia_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SLAB = create(key("acacia_slab")); + + /** + * {@code minecraft:acacia_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_STAIRS = create(key("acacia_stairs")); + + /** + * {@code minecraft:acacia_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_TRAPDOOR = create(key("acacia_trapdoor")); + + /** + * {@code minecraft:acacia_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_WALL_HANGING_SIGN = create(key("acacia_wall_hanging_sign")); + + /** + * {@code minecraft:acacia_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_WALL_SIGN = create(key("acacia_wall_sign")); + + /** + * {@code minecraft:acacia_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_WOOD = create(key("acacia_wood")); + + /** + * {@code minecraft:activator_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACTIVATOR_RAIL = create(key("activator_rail")); + + /** + * {@code minecraft:air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AIR = create(key("air")); + + /** + * {@code minecraft:allium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ALLIUM = create(key("allium")); + + /** + * {@code minecraft:amethyst_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST_BLOCK = create(key("amethyst_block")); + + /** + * {@code minecraft:amethyst_cluster} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST_CLUSTER = create(key("amethyst_cluster")); + + /** + * {@code minecraft:ancient_debris} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANCIENT_DEBRIS = create(key("ancient_debris")); + + /** + * {@code minecraft:andesite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE = create(key("andesite")); + + /** + * {@code minecraft:andesite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_SLAB = create(key("andesite_slab")); + + /** + * {@code minecraft:andesite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_STAIRS = create(key("andesite_stairs")); + + /** + * {@code minecraft:andesite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_WALL = create(key("andesite_wall")); + + /** + * {@code minecraft:anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANVIL = create(key("anvil")); + + /** + * {@code minecraft:attached_melon_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ATTACHED_MELON_STEM = create(key("attached_melon_stem")); + + /** + * {@code minecraft:attached_pumpkin_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ATTACHED_PUMPKIN_STEM = create(key("attached_pumpkin_stem")); + + /** + * {@code minecraft:azalea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZALEA = create(key("azalea")); + + /** + * {@code minecraft:azalea_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZALEA_LEAVES = create(key("azalea_leaves")); + + /** + * {@code minecraft:azure_bluet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZURE_BLUET = create(key("azure_bluet")); + + /** + * {@code minecraft:bamboo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO = create(key("bamboo")); + + /** + * {@code minecraft:bamboo_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_BLOCK = create(key("bamboo_block")); + + /** + * {@code minecraft:bamboo_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_BUTTON = create(key("bamboo_button")); + + /** + * {@code minecraft:bamboo_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_DOOR = create(key("bamboo_door")); + + /** + * {@code minecraft:bamboo_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_FENCE = create(key("bamboo_fence")); + + /** + * {@code minecraft:bamboo_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_FENCE_GATE = create(key("bamboo_fence_gate")); + + /** + * {@code minecraft:bamboo_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_HANGING_SIGN = create(key("bamboo_hanging_sign")); + + /** + * {@code minecraft:bamboo_mosaic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC = create(key("bamboo_mosaic")); + + /** + * {@code minecraft:bamboo_mosaic_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC_SLAB = create(key("bamboo_mosaic_slab")); + + /** + * {@code minecraft:bamboo_mosaic_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC_STAIRS = create(key("bamboo_mosaic_stairs")); + + /** + * {@code minecraft:bamboo_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_PLANKS = create(key("bamboo_planks")); + + /** + * {@code minecraft:bamboo_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_PRESSURE_PLATE = create(key("bamboo_pressure_plate")); + + /** + * {@code minecraft:bamboo_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_SAPLING = create(key("bamboo_sapling")); + + /** + * {@code minecraft:bamboo_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_SIGN = create(key("bamboo_sign")); + + /** + * {@code minecraft:bamboo_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_SLAB = create(key("bamboo_slab")); + + /** + * {@code minecraft:bamboo_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_STAIRS = create(key("bamboo_stairs")); + + /** + * {@code minecraft:bamboo_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_TRAPDOOR = create(key("bamboo_trapdoor")); + + /** + * {@code minecraft:bamboo_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_WALL_HANGING_SIGN = create(key("bamboo_wall_hanging_sign")); + + /** + * {@code minecraft:bamboo_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_WALL_SIGN = create(key("bamboo_wall_sign")); + + /** + * {@code minecraft:barrel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BARREL = create(key("barrel")); + + /** + * {@code minecraft:barrier} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BARRIER = create(key("barrier")); + + /** + * {@code minecraft:basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASALT = create(key("basalt")); + + /** + * {@code minecraft:beacon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEACON = create(key("beacon")); + + /** + * {@code minecraft:bedrock} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEDROCK = create(key("bedrock")); + + /** + * {@code minecraft:bee_nest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEE_NEST = create(key("bee_nest")); + + /** + * {@code minecraft:beehive} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEEHIVE = create(key("beehive")); + + /** + * {@code minecraft:beetroots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEETROOTS = create(key("beetroots")); + + /** + * {@code minecraft:bell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BELL = create(key("bell")); + + /** + * {@code minecraft:big_dripleaf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIG_DRIPLEAF = create(key("big_dripleaf")); + + /** + * {@code minecraft:big_dripleaf_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIG_DRIPLEAF_STEM = create(key("big_dripleaf_stem")); + + /** + * {@code minecraft:birch_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_BUTTON = create(key("birch_button")); + + /** + * {@code minecraft:birch_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_DOOR = create(key("birch_door")); + + /** + * {@code minecraft:birch_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FENCE = create(key("birch_fence")); + + /** + * {@code minecraft:birch_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FENCE_GATE = create(key("birch_fence_gate")); + + /** + * {@code minecraft:birch_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_HANGING_SIGN = create(key("birch_hanging_sign")); + + /** + * {@code minecraft:birch_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_LEAVES = create(key("birch_leaves")); + + /** + * {@code minecraft:birch_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_LOG = create(key("birch_log")); + + /** + * {@code minecraft:birch_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_PLANKS = create(key("birch_planks")); + + /** + * {@code minecraft:birch_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_PRESSURE_PLATE = create(key("birch_pressure_plate")); + + /** + * {@code minecraft:birch_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SAPLING = create(key("birch_sapling")); + + /** + * {@code minecraft:birch_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SIGN = create(key("birch_sign")); + + /** + * {@code minecraft:birch_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SLAB = create(key("birch_slab")); + + /** + * {@code minecraft:birch_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_STAIRS = create(key("birch_stairs")); + + /** + * {@code minecraft:birch_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_TRAPDOOR = create(key("birch_trapdoor")); + + /** + * {@code minecraft:birch_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_WALL_HANGING_SIGN = create(key("birch_wall_hanging_sign")); + + /** + * {@code minecraft:birch_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_WALL_SIGN = create(key("birch_wall_sign")); + + /** + * {@code minecraft:birch_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_WOOD = create(key("birch_wood")); + + /** + * {@code minecraft:black_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_BANNER = create(key("black_banner")); + + /** + * {@code minecraft:black_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_BED = create(key("black_bed")); + + /** + * {@code minecraft:black_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CANDLE = create(key("black_candle")); + + /** + * {@code minecraft:black_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CANDLE_CAKE = create(key("black_candle_cake")); + + /** + * {@code minecraft:black_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CARPET = create(key("black_carpet")); + + /** + * {@code minecraft:black_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CONCRETE = create(key("black_concrete")); + + /** + * {@code minecraft:black_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CONCRETE_POWDER = create(key("black_concrete_powder")); + + /** + * {@code minecraft:black_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_GLAZED_TERRACOTTA = create(key("black_glazed_terracotta")); + + /** + * {@code minecraft:black_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_SHULKER_BOX = create(key("black_shulker_box")); + + /** + * {@code minecraft:black_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_STAINED_GLASS = create(key("black_stained_glass")); + + /** + * {@code minecraft:black_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_STAINED_GLASS_PANE = create(key("black_stained_glass_pane")); + + /** + * {@code minecraft:black_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_TERRACOTTA = create(key("black_terracotta")); + + /** + * {@code minecraft:black_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_WALL_BANNER = create(key("black_wall_banner")); + + /** + * {@code minecraft:black_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_WOOL = create(key("black_wool")); + + /** + * {@code minecraft:blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE = create(key("blackstone")); + + /** + * {@code minecraft:blackstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_SLAB = create(key("blackstone_slab")); + + /** + * {@code minecraft:blackstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_STAIRS = create(key("blackstone_stairs")); + + /** + * {@code minecraft:blackstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_WALL = create(key("blackstone_wall")); + + /** + * {@code minecraft:blast_furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAST_FURNACE = create(key("blast_furnace")); + + /** + * {@code minecraft:blue_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_BANNER = create(key("blue_banner")); + + /** + * {@code minecraft:blue_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_BED = create(key("blue_bed")); + + /** + * {@code minecraft:blue_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CANDLE = create(key("blue_candle")); + + /** + * {@code minecraft:blue_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CANDLE_CAKE = create(key("blue_candle_cake")); + + /** + * {@code minecraft:blue_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CARPET = create(key("blue_carpet")); + + /** + * {@code minecraft:blue_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CONCRETE = create(key("blue_concrete")); + + /** + * {@code minecraft:blue_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CONCRETE_POWDER = create(key("blue_concrete_powder")); + + /** + * {@code minecraft:blue_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_GLAZED_TERRACOTTA = create(key("blue_glazed_terracotta")); + + /** + * {@code minecraft:blue_ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_ICE = create(key("blue_ice")); + + /** + * {@code minecraft:blue_orchid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_ORCHID = create(key("blue_orchid")); + + /** + * {@code minecraft:blue_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_SHULKER_BOX = create(key("blue_shulker_box")); + + /** + * {@code minecraft:blue_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_STAINED_GLASS = create(key("blue_stained_glass")); + + /** + * {@code minecraft:blue_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_STAINED_GLASS_PANE = create(key("blue_stained_glass_pane")); + + /** + * {@code minecraft:blue_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_TERRACOTTA = create(key("blue_terracotta")); + + /** + * {@code minecraft:blue_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_WALL_BANNER = create(key("blue_wall_banner")); + + /** + * {@code minecraft:blue_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_WOOL = create(key("blue_wool")); + + /** + * {@code minecraft:bone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BONE_BLOCK = create(key("bone_block")); + + /** + * {@code minecraft:bookshelf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOOKSHELF = create(key("bookshelf")); + + /** + * {@code minecraft:brain_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL = create(key("brain_coral")); + + /** + * {@code minecraft:brain_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL_BLOCK = create(key("brain_coral_block")); + + /** + * {@code minecraft:brain_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL_FAN = create(key("brain_coral_fan")); + + /** + * {@code minecraft:brain_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL_WALL_FAN = create(key("brain_coral_wall_fan")); + + /** + * {@code minecraft:brewing_stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREWING_STAND = create(key("brewing_stand")); + + /** + * {@code minecraft:brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_SLAB = create(key("brick_slab")); + + /** + * {@code minecraft:brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_STAIRS = create(key("brick_stairs")); + + /** + * {@code minecraft:brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_WALL = create(key("brick_wall")); + + /** + * {@code minecraft:bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICKS = create(key("bricks")); + + /** + * {@code minecraft:brown_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_BANNER = create(key("brown_banner")); + + /** + * {@code minecraft:brown_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_BED = create(key("brown_bed")); + + /** + * {@code minecraft:brown_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CANDLE = create(key("brown_candle")); + + /** + * {@code minecraft:brown_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CANDLE_CAKE = create(key("brown_candle_cake")); + + /** + * {@code minecraft:brown_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CARPET = create(key("brown_carpet")); + + /** + * {@code minecraft:brown_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CONCRETE = create(key("brown_concrete")); + + /** + * {@code minecraft:brown_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CONCRETE_POWDER = create(key("brown_concrete_powder")); + + /** + * {@code minecraft:brown_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_GLAZED_TERRACOTTA = create(key("brown_glazed_terracotta")); + + /** + * {@code minecraft:brown_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_MUSHROOM = create(key("brown_mushroom")); + + /** + * {@code minecraft:brown_mushroom_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_MUSHROOM_BLOCK = create(key("brown_mushroom_block")); + + /** + * {@code minecraft:brown_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_SHULKER_BOX = create(key("brown_shulker_box")); + + /** + * {@code minecraft:brown_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_STAINED_GLASS = create(key("brown_stained_glass")); + + /** + * {@code minecraft:brown_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_STAINED_GLASS_PANE = create(key("brown_stained_glass_pane")); + + /** + * {@code minecraft:brown_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_TERRACOTTA = create(key("brown_terracotta")); + + /** + * {@code minecraft:brown_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_WALL_BANNER = create(key("brown_wall_banner")); + + /** + * {@code minecraft:brown_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_WOOL = create(key("brown_wool")); + + /** + * {@code minecraft:bubble_column} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_COLUMN = create(key("bubble_column")); + + /** + * {@code minecraft:bubble_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL = create(key("bubble_coral")); + + /** + * {@code minecraft:bubble_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL_BLOCK = create(key("bubble_coral_block")); + + /** + * {@code minecraft:bubble_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL_FAN = create(key("bubble_coral_fan")); + + /** + * {@code minecraft:bubble_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL_WALL_FAN = create(key("bubble_coral_wall_fan")); + + /** + * {@code minecraft:budding_amethyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUDDING_AMETHYST = create(key("budding_amethyst")); + + /** + * {@code minecraft:cactus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CACTUS = create(key("cactus")); + + /** + * {@code minecraft:cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAKE = create(key("cake")); + + /** + * {@code minecraft:calcite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALCITE = create(key("calcite")); + + /** + * {@code minecraft:calibrated_sculk_sensor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALIBRATED_SCULK_SENSOR = create(key("calibrated_sculk_sensor")); + + /** + * {@code minecraft:campfire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAMPFIRE = create(key("campfire")); + + /** + * {@code minecraft:candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CANDLE = create(key("candle")); + + /** + * {@code minecraft:candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CANDLE_CAKE = create(key("candle_cake")); + + /** + * {@code minecraft:carrots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARROTS = create(key("carrots")); + + /** + * {@code minecraft:cartography_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARTOGRAPHY_TABLE = create(key("cartography_table")); + + /** + * {@code minecraft:carved_pumpkin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARVED_PUMPKIN = create(key("carved_pumpkin")); + + /** + * {@code minecraft:cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAULDRON = create(key("cauldron")); + + /** + * {@code minecraft:cave_air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAVE_AIR = create(key("cave_air")); + + /** + * {@code minecraft:cave_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAVE_VINES = create(key("cave_vines")); + + /** + * {@code minecraft:cave_vines_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAVE_VINES_PLANT = create(key("cave_vines_plant")); + + /** + * {@code minecraft:chain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAIN = create(key("chain")); + + /** + * {@code minecraft:chain_command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAIN_COMMAND_BLOCK = create(key("chain_command_block")); + + /** + * {@code minecraft:cherry_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_BUTTON = create(key("cherry_button")); + + /** + * {@code minecraft:cherry_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_DOOR = create(key("cherry_door")); + + /** + * {@code minecraft:cherry_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_FENCE = create(key("cherry_fence")); + + /** + * {@code minecraft:cherry_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_FENCE_GATE = create(key("cherry_fence_gate")); + + /** + * {@code minecraft:cherry_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_HANGING_SIGN = create(key("cherry_hanging_sign")); + + /** + * {@code minecraft:cherry_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_LEAVES = create(key("cherry_leaves")); + + /** + * {@code minecraft:cherry_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_LOG = create(key("cherry_log")); + + /** + * {@code minecraft:cherry_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_PLANKS = create(key("cherry_planks")); + + /** + * {@code minecraft:cherry_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_PRESSURE_PLATE = create(key("cherry_pressure_plate")); + + /** + * {@code minecraft:cherry_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SAPLING = create(key("cherry_sapling")); + + /** + * {@code minecraft:cherry_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SIGN = create(key("cherry_sign")); + + /** + * {@code minecraft:cherry_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SLAB = create(key("cherry_slab")); + + /** + * {@code minecraft:cherry_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_STAIRS = create(key("cherry_stairs")); + + /** + * {@code minecraft:cherry_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_TRAPDOOR = create(key("cherry_trapdoor")); + + /** + * {@code minecraft:cherry_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_WALL_HANGING_SIGN = create(key("cherry_wall_hanging_sign")); + + /** + * {@code minecraft:cherry_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_WALL_SIGN = create(key("cherry_wall_sign")); + + /** + * {@code minecraft:cherry_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_WOOD = create(key("cherry_wood")); + + /** + * {@code minecraft:chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHEST = create(key("chest")); + + /** + * {@code minecraft:chipped_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHIPPED_ANVIL = create(key("chipped_anvil")); + + /** + * {@code minecraft:chiseled_bookshelf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_BOOKSHELF = create(key("chiseled_bookshelf")); + + /** + * {@code minecraft:chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_COPPER = create(key("chiseled_copper")); + + /** + * {@code minecraft:chiseled_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_DEEPSLATE = create(key("chiseled_deepslate")); + + /** + * {@code minecraft:chiseled_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_NETHER_BRICKS = create(key("chiseled_nether_bricks")); + + /** + * {@code minecraft:chiseled_polished_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_POLISHED_BLACKSTONE = create(key("chiseled_polished_blackstone")); + + /** + * {@code minecraft:chiseled_quartz_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_QUARTZ_BLOCK = create(key("chiseled_quartz_block")); + + /** + * {@code minecraft:chiseled_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_RED_SANDSTONE = create(key("chiseled_red_sandstone")); + + /** + * {@code minecraft:chiseled_resin_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_RESIN_BRICKS = create(key("chiseled_resin_bricks")); + + /** + * {@code minecraft:chiseled_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_SANDSTONE = create(key("chiseled_sandstone")); + + /** + * {@code minecraft:chiseled_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_STONE_BRICKS = create(key("chiseled_stone_bricks")); + + /** + * {@code minecraft:chiseled_tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_TUFF = create(key("chiseled_tuff")); + + /** + * {@code minecraft:chiseled_tuff_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_TUFF_BRICKS = create(key("chiseled_tuff_bricks")); + + /** + * {@code minecraft:chorus_flower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHORUS_FLOWER = create(key("chorus_flower")); + + /** + * {@code minecraft:chorus_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHORUS_PLANT = create(key("chorus_plant")); + + /** + * {@code minecraft:clay} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLAY = create(key("clay")); + + /** + * {@code minecraft:closed_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLOSED_EYEBLOSSOM = create(key("closed_eyeblossom")); + + /** + * {@code minecraft:coal_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAL_BLOCK = create(key("coal_block")); + + /** + * {@code minecraft:coal_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAL_ORE = create(key("coal_ore")); + + /** + * {@code minecraft:coarse_dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COARSE_DIRT = create(key("coarse_dirt")); + + /** + * {@code minecraft:cobbled_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE = create(key("cobbled_deepslate")); + + /** + * {@code minecraft:cobbled_deepslate_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_SLAB = create(key("cobbled_deepslate_slab")); + + /** + * {@code minecraft:cobbled_deepslate_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_STAIRS = create(key("cobbled_deepslate_stairs")); + + /** + * {@code minecraft:cobbled_deepslate_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_WALL = create(key("cobbled_deepslate_wall")); + + /** + * {@code minecraft:cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE = create(key("cobblestone")); + + /** + * {@code minecraft:cobblestone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_SLAB = create(key("cobblestone_slab")); + + /** + * {@code minecraft:cobblestone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_STAIRS = create(key("cobblestone_stairs")); + + /** + * {@code minecraft:cobblestone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_WALL = create(key("cobblestone_wall")); + + /** + * {@code minecraft:cobweb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBWEB = create(key("cobweb")); + + /** + * {@code minecraft:cocoa} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COCOA = create(key("cocoa")); + + /** + * {@code minecraft:command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMMAND_BLOCK = create(key("command_block")); + + /** + * {@code minecraft:comparator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMPARATOR = create(key("comparator")); + + /** + * {@code minecraft:composter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMPOSTER = create(key("composter")); + + /** + * {@code minecraft:conduit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONDUIT = create(key("conduit")); + + /** + * {@code minecraft:copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_BLOCK = create(key("copper_block")); + + /** + * {@code minecraft:copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_BULB = create(key("copper_bulb")); + + /** + * {@code minecraft:copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_DOOR = create(key("copper_door")); + + /** + * {@code minecraft:copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_GRATE = create(key("copper_grate")); + + /** + * {@code minecraft:copper_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_ORE = create(key("copper_ore")); + + /** + * {@code minecraft:copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_TRAPDOOR = create(key("copper_trapdoor")); + + /** + * {@code minecraft:cornflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CORNFLOWER = create(key("cornflower")); + + /** + * {@code minecraft:cracked_deepslate_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_DEEPSLATE_BRICKS = create(key("cracked_deepslate_bricks")); + + /** + * {@code minecraft:cracked_deepslate_tiles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_DEEPSLATE_TILES = create(key("cracked_deepslate_tiles")); + + /** + * {@code minecraft:cracked_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_NETHER_BRICKS = create(key("cracked_nether_bricks")); + + /** + * {@code minecraft:cracked_polished_blackstone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_POLISHED_BLACKSTONE_BRICKS = create(key("cracked_polished_blackstone_bricks")); + + /** + * {@code minecraft:cracked_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_STONE_BRICKS = create(key("cracked_stone_bricks")); + + /** + * {@code minecraft:crafter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTER = create(key("crafter")); + + /** + * {@code minecraft:crafting_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTING_TABLE = create(key("crafting_table")); + + /** + * {@code minecraft:creaking_heart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREAKING_HEART = create(key("creaking_heart")); + + /** + * {@code minecraft:creeper_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER_HEAD = create(key("creeper_head")); + + /** + * {@code minecraft:creeper_wall_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER_WALL_HEAD = create(key("creeper_wall_head")); + + /** + * {@code minecraft:crimson_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_BUTTON = create(key("crimson_button")); + + /** + * {@code minecraft:crimson_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_DOOR = create(key("crimson_door")); + + /** + * {@code minecraft:crimson_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FENCE = create(key("crimson_fence")); + + /** + * {@code minecraft:crimson_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FENCE_GATE = create(key("crimson_fence_gate")); + + /** + * {@code minecraft:crimson_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FUNGUS = create(key("crimson_fungus")); + + /** + * {@code minecraft:crimson_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_HANGING_SIGN = create(key("crimson_hanging_sign")); + + /** + * {@code minecraft:crimson_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_HYPHAE = create(key("crimson_hyphae")); + + /** + * {@code minecraft:crimson_nylium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_NYLIUM = create(key("crimson_nylium")); + + /** + * {@code minecraft:crimson_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_PLANKS = create(key("crimson_planks")); + + /** + * {@code minecraft:crimson_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_PRESSURE_PLATE = create(key("crimson_pressure_plate")); + + /** + * {@code minecraft:crimson_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_ROOTS = create(key("crimson_roots")); + + /** + * {@code minecraft:crimson_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_SIGN = create(key("crimson_sign")); + + /** + * {@code minecraft:crimson_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_SLAB = create(key("crimson_slab")); + + /** + * {@code minecraft:crimson_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_STAIRS = create(key("crimson_stairs")); + + /** + * {@code minecraft:crimson_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_STEM = create(key("crimson_stem")); + + /** + * {@code minecraft:crimson_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_TRAPDOOR = create(key("crimson_trapdoor")); + + /** + * {@code minecraft:crimson_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_WALL_HANGING_SIGN = create(key("crimson_wall_hanging_sign")); + + /** + * {@code minecraft:crimson_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_WALL_SIGN = create(key("crimson_wall_sign")); + + /** + * {@code minecraft:crying_obsidian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRYING_OBSIDIAN = create(key("crying_obsidian")); + + /** + * {@code minecraft:cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER = create(key("cut_copper")); + + /** + * {@code minecraft:cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER_SLAB = create(key("cut_copper_slab")); + + /** + * {@code minecraft:cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER_STAIRS = create(key("cut_copper_stairs")); + + /** + * {@code minecraft:cut_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_RED_SANDSTONE = create(key("cut_red_sandstone")); + + /** + * {@code minecraft:cut_red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_RED_SANDSTONE_SLAB = create(key("cut_red_sandstone_slab")); + + /** + * {@code minecraft:cut_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_SANDSTONE = create(key("cut_sandstone")); + + /** + * {@code minecraft:cut_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_SANDSTONE_SLAB = create(key("cut_sandstone_slab")); + + /** + * {@code minecraft:cyan_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_BANNER = create(key("cyan_banner")); + + /** + * {@code minecraft:cyan_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_BED = create(key("cyan_bed")); + + /** + * {@code minecraft:cyan_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CANDLE = create(key("cyan_candle")); + + /** + * {@code minecraft:cyan_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CANDLE_CAKE = create(key("cyan_candle_cake")); + + /** + * {@code minecraft:cyan_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CARPET = create(key("cyan_carpet")); + + /** + * {@code minecraft:cyan_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CONCRETE = create(key("cyan_concrete")); + + /** + * {@code minecraft:cyan_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CONCRETE_POWDER = create(key("cyan_concrete_powder")); + + /** + * {@code minecraft:cyan_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_GLAZED_TERRACOTTA = create(key("cyan_glazed_terracotta")); + + /** + * {@code minecraft:cyan_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_SHULKER_BOX = create(key("cyan_shulker_box")); + + /** + * {@code minecraft:cyan_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_STAINED_GLASS = create(key("cyan_stained_glass")); + + /** + * {@code minecraft:cyan_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_STAINED_GLASS_PANE = create(key("cyan_stained_glass_pane")); + + /** + * {@code minecraft:cyan_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_TERRACOTTA = create(key("cyan_terracotta")); + + /** + * {@code minecraft:cyan_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_WALL_BANNER = create(key("cyan_wall_banner")); + + /** + * {@code minecraft:cyan_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_WOOL = create(key("cyan_wool")); + + /** + * {@code minecraft:damaged_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DAMAGED_ANVIL = create(key("damaged_anvil")); + + /** + * {@code minecraft:dandelion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DANDELION = create(key("dandelion")); + + /** + * {@code minecraft:dark_oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_BUTTON = create(key("dark_oak_button")); + + /** + * {@code minecraft:dark_oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_DOOR = create(key("dark_oak_door")); + + /** + * {@code minecraft:dark_oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_FENCE = create(key("dark_oak_fence")); + + /** + * {@code minecraft:dark_oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_FENCE_GATE = create(key("dark_oak_fence_gate")); + + /** + * {@code minecraft:dark_oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_HANGING_SIGN = create(key("dark_oak_hanging_sign")); + + /** + * {@code minecraft:dark_oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_LEAVES = create(key("dark_oak_leaves")); + + /** + * {@code minecraft:dark_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_LOG = create(key("dark_oak_log")); + + /** + * {@code minecraft:dark_oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_PLANKS = create(key("dark_oak_planks")); + + /** + * {@code minecraft:dark_oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_PRESSURE_PLATE = create(key("dark_oak_pressure_plate")); + + /** + * {@code minecraft:dark_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SAPLING = create(key("dark_oak_sapling")); + + /** + * {@code minecraft:dark_oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SIGN = create(key("dark_oak_sign")); + + /** + * {@code minecraft:dark_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SLAB = create(key("dark_oak_slab")); + + /** + * {@code minecraft:dark_oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_STAIRS = create(key("dark_oak_stairs")); + + /** + * {@code minecraft:dark_oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_TRAPDOOR = create(key("dark_oak_trapdoor")); + + /** + * {@code minecraft:dark_oak_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_WALL_HANGING_SIGN = create(key("dark_oak_wall_hanging_sign")); + + /** + * {@code minecraft:dark_oak_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_WALL_SIGN = create(key("dark_oak_wall_sign")); + + /** + * {@code minecraft:dark_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_WOOD = create(key("dark_oak_wood")); + + /** + * {@code minecraft:dark_prismarine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE = create(key("dark_prismarine")); + + /** + * {@code minecraft:dark_prismarine_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE_SLAB = create(key("dark_prismarine_slab")); + + /** + * {@code minecraft:dark_prismarine_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE_STAIRS = create(key("dark_prismarine_stairs")); + + /** + * {@code minecraft:daylight_detector} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DAYLIGHT_DETECTOR = create(key("daylight_detector")); + + /** + * {@code minecraft:dead_brain_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL = create(key("dead_brain_coral")); + + /** + * {@code minecraft:dead_brain_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL_BLOCK = create(key("dead_brain_coral_block")); + + /** + * {@code minecraft:dead_brain_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL_FAN = create(key("dead_brain_coral_fan")); + + /** + * {@code minecraft:dead_brain_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL_WALL_FAN = create(key("dead_brain_coral_wall_fan")); + + /** + * {@code minecraft:dead_bubble_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL = create(key("dead_bubble_coral")); + + /** + * {@code minecraft:dead_bubble_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL_BLOCK = create(key("dead_bubble_coral_block")); + + /** + * {@code minecraft:dead_bubble_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL_FAN = create(key("dead_bubble_coral_fan")); + + /** + * {@code minecraft:dead_bubble_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL_WALL_FAN = create(key("dead_bubble_coral_wall_fan")); + + /** + * {@code minecraft:dead_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUSH = create(key("dead_bush")); + + /** + * {@code minecraft:dead_fire_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL = create(key("dead_fire_coral")); + + /** + * {@code minecraft:dead_fire_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL_BLOCK = create(key("dead_fire_coral_block")); + + /** + * {@code minecraft:dead_fire_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL_FAN = create(key("dead_fire_coral_fan")); + + /** + * {@code minecraft:dead_fire_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL_WALL_FAN = create(key("dead_fire_coral_wall_fan")); + + /** + * {@code minecraft:dead_horn_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL = create(key("dead_horn_coral")); + + /** + * {@code minecraft:dead_horn_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL_BLOCK = create(key("dead_horn_coral_block")); + + /** + * {@code minecraft:dead_horn_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL_FAN = create(key("dead_horn_coral_fan")); + + /** + * {@code minecraft:dead_horn_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL_WALL_FAN = create(key("dead_horn_coral_wall_fan")); + + /** + * {@code minecraft:dead_tube_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL = create(key("dead_tube_coral")); + + /** + * {@code minecraft:dead_tube_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL_BLOCK = create(key("dead_tube_coral_block")); + + /** + * {@code minecraft:dead_tube_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL_FAN = create(key("dead_tube_coral_fan")); + + /** + * {@code minecraft:dead_tube_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL_WALL_FAN = create(key("dead_tube_coral_wall_fan")); + + /** + * {@code minecraft:decorated_pot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DECORATED_POT = create(key("decorated_pot")); + + /** + * {@code minecraft:deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE = create(key("deepslate")); + + /** + * {@code minecraft:deepslate_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_SLAB = create(key("deepslate_brick_slab")); + + /** + * {@code minecraft:deepslate_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_STAIRS = create(key("deepslate_brick_stairs")); + + /** + * {@code minecraft:deepslate_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_WALL = create(key("deepslate_brick_wall")); + + /** + * {@code minecraft:deepslate_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICKS = create(key("deepslate_bricks")); + + /** + * {@code minecraft:deepslate_coal_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_COAL_ORE = create(key("deepslate_coal_ore")); + + /** + * {@code minecraft:deepslate_copper_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_COPPER_ORE = create(key("deepslate_copper_ore")); + + /** + * {@code minecraft:deepslate_diamond_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_DIAMOND_ORE = create(key("deepslate_diamond_ore")); + + /** + * {@code minecraft:deepslate_emerald_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_EMERALD_ORE = create(key("deepslate_emerald_ore")); + + /** + * {@code minecraft:deepslate_gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_GOLD_ORE = create(key("deepslate_gold_ore")); + + /** + * {@code minecraft:deepslate_iron_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_IRON_ORE = create(key("deepslate_iron_ore")); + + /** + * {@code minecraft:deepslate_lapis_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_LAPIS_ORE = create(key("deepslate_lapis_ore")); + + /** + * {@code minecraft:deepslate_redstone_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_REDSTONE_ORE = create(key("deepslate_redstone_ore")); + + /** + * {@code minecraft:deepslate_tile_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_SLAB = create(key("deepslate_tile_slab")); + + /** + * {@code minecraft:deepslate_tile_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_STAIRS = create(key("deepslate_tile_stairs")); + + /** + * {@code minecraft:deepslate_tile_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_WALL = create(key("deepslate_tile_wall")); + + /** + * {@code minecraft:deepslate_tiles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILES = create(key("deepslate_tiles")); + + /** + * {@code minecraft:detector_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DETECTOR_RAIL = create(key("detector_rail")); + + /** + * {@code minecraft:diamond_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_BLOCK = create(key("diamond_block")); + + /** + * {@code minecraft:diamond_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_ORE = create(key("diamond_ore")); + + /** + * {@code minecraft:diorite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE = create(key("diorite")); + + /** + * {@code minecraft:diorite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_SLAB = create(key("diorite_slab")); + + /** + * {@code minecraft:diorite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_STAIRS = create(key("diorite_stairs")); + + /** + * {@code minecraft:diorite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_WALL = create(key("diorite_wall")); + + /** + * {@code minecraft:dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIRT = create(key("dirt")); + + /** + * {@code minecraft:dirt_path} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIRT_PATH = create(key("dirt_path")); + + /** + * {@code minecraft:dispenser} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DISPENSER = create(key("dispenser")); + + /** + * {@code minecraft:dragon_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_EGG = create(key("dragon_egg")); + + /** + * {@code minecraft:dragon_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_HEAD = create(key("dragon_head")); + + /** + * {@code minecraft:dragon_wall_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_WALL_HEAD = create(key("dragon_wall_head")); + + /** + * {@code minecraft:dried_kelp_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIED_KELP_BLOCK = create(key("dried_kelp_block")); + + /** + * {@code minecraft:dripstone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIPSTONE_BLOCK = create(key("dripstone_block")); + + /** + * {@code minecraft:dropper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DROPPER = create(key("dropper")); + + /** + * {@code minecraft:emerald_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD_BLOCK = create(key("emerald_block")); + + /** + * {@code minecraft:emerald_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD_ORE = create(key("emerald_ore")); + + /** + * {@code minecraft:enchanting_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANTING_TABLE = create(key("enchanting_table")); + + /** + * {@code minecraft:end_gateway} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_GATEWAY = create(key("end_gateway")); + + /** + * {@code minecraft:end_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_PORTAL = create(key("end_portal")); + + /** + * {@code minecraft:end_portal_frame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_PORTAL_FRAME = create(key("end_portal_frame")); + + /** + * {@code minecraft:end_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_ROD = create(key("end_rod")); + + /** + * {@code minecraft:end_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE = create(key("end_stone")); + + /** + * {@code minecraft:end_stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_SLAB = create(key("end_stone_brick_slab")); + + /** + * {@code minecraft:end_stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_STAIRS = create(key("end_stone_brick_stairs")); + + /** + * {@code minecraft:end_stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_WALL = create(key("end_stone_brick_wall")); + + /** + * {@code minecraft:end_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICKS = create(key("end_stone_bricks")); + + /** + * {@code minecraft:ender_chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_CHEST = create(key("ender_chest")); + + /** + * {@code minecraft:exposed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CHISELED_COPPER = create(key("exposed_chiseled_copper")); + + /** + * {@code minecraft:exposed_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER = create(key("exposed_copper")); + + /** + * {@code minecraft:exposed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_BULB = create(key("exposed_copper_bulb")); + + /** + * {@code minecraft:exposed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_DOOR = create(key("exposed_copper_door")); + + /** + * {@code minecraft:exposed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_GRATE = create(key("exposed_copper_grate")); + + /** + * {@code minecraft:exposed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_TRAPDOOR = create(key("exposed_copper_trapdoor")); + + /** + * {@code minecraft:exposed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER = create(key("exposed_cut_copper")); + + /** + * {@code minecraft:exposed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER_SLAB = create(key("exposed_cut_copper_slab")); + + /** + * {@code minecraft:exposed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER_STAIRS = create(key("exposed_cut_copper_stairs")); + + /** + * {@code minecraft:farmland} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FARMLAND = create(key("farmland")); + + /** + * {@code minecraft:fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FERN = create(key("fern")); + + /** + * {@code minecraft:fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE = create(key("fire")); + + /** + * {@code minecraft:fire_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL = create(key("fire_coral")); + + /** + * {@code minecraft:fire_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL_BLOCK = create(key("fire_coral_block")); + + /** + * {@code minecraft:fire_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL_FAN = create(key("fire_coral_fan")); + + /** + * {@code minecraft:fire_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL_WALL_FAN = create(key("fire_coral_wall_fan")); + + /** + * {@code minecraft:fletching_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLETCHING_TABLE = create(key("fletching_table")); + + /** + * {@code minecraft:flower_pot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER_POT = create(key("flower_pot")); + + /** + * {@code minecraft:flowering_azalea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWERING_AZALEA = create(key("flowering_azalea")); + + /** + * {@code minecraft:flowering_azalea_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWERING_AZALEA_LEAVES = create(key("flowering_azalea_leaves")); + + /** + * {@code minecraft:frogspawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROGSPAWN = create(key("frogspawn")); + + /** + * {@code minecraft:frosted_ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROSTED_ICE = create(key("frosted_ice")); + + /** + * {@code minecraft:furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FURNACE = create(key("furnace")); + + /** + * {@code minecraft:gilded_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GILDED_BLACKSTONE = create(key("gilded_blackstone")); + + /** + * {@code minecraft:glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLASS = create(key("glass")); + + /** + * {@code minecraft:glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLASS_PANE = create(key("glass_pane")); + + /** + * {@code minecraft:glow_lichen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_LICHEN = create(key("glow_lichen")); + + /** + * {@code minecraft:glowstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOWSTONE = create(key("glowstone")); + + /** + * {@code minecraft:gold_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_BLOCK = create(key("gold_block")); + + /** + * {@code minecraft:gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_ORE = create(key("gold_ore")); + + /** + * {@code minecraft:granite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE = create(key("granite")); + + /** + * {@code minecraft:granite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_SLAB = create(key("granite_slab")); + + /** + * {@code minecraft:granite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_STAIRS = create(key("granite_stairs")); + + /** + * {@code minecraft:granite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_WALL = create(key("granite_wall")); + + /** + * {@code minecraft:grass_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRASS_BLOCK = create(key("grass_block")); + + /** + * {@code minecraft:gravel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAVEL = create(key("gravel")); + + /** + * {@code minecraft:gray_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_BANNER = create(key("gray_banner")); + + /** + * {@code minecraft:gray_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_BED = create(key("gray_bed")); + + /** + * {@code minecraft:gray_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CANDLE = create(key("gray_candle")); + + /** + * {@code minecraft:gray_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CANDLE_CAKE = create(key("gray_candle_cake")); + + /** + * {@code minecraft:gray_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CARPET = create(key("gray_carpet")); + + /** + * {@code minecraft:gray_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CONCRETE = create(key("gray_concrete")); + + /** + * {@code minecraft:gray_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CONCRETE_POWDER = create(key("gray_concrete_powder")); + + /** + * {@code minecraft:gray_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_GLAZED_TERRACOTTA = create(key("gray_glazed_terracotta")); + + /** + * {@code minecraft:gray_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_SHULKER_BOX = create(key("gray_shulker_box")); + + /** + * {@code minecraft:gray_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_STAINED_GLASS = create(key("gray_stained_glass")); + + /** + * {@code minecraft:gray_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_STAINED_GLASS_PANE = create(key("gray_stained_glass_pane")); + + /** + * {@code minecraft:gray_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_TERRACOTTA = create(key("gray_terracotta")); + + /** + * {@code minecraft:gray_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_WALL_BANNER = create(key("gray_wall_banner")); + + /** + * {@code minecraft:gray_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_WOOL = create(key("gray_wool")); + + /** + * {@code minecraft:green_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_BANNER = create(key("green_banner")); + + /** + * {@code minecraft:green_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_BED = create(key("green_bed")); + + /** + * {@code minecraft:green_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CANDLE = create(key("green_candle")); + + /** + * {@code minecraft:green_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CANDLE_CAKE = create(key("green_candle_cake")); + + /** + * {@code minecraft:green_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CARPET = create(key("green_carpet")); + + /** + * {@code minecraft:green_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CONCRETE = create(key("green_concrete")); + + /** + * {@code minecraft:green_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CONCRETE_POWDER = create(key("green_concrete_powder")); + + /** + * {@code minecraft:green_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_GLAZED_TERRACOTTA = create(key("green_glazed_terracotta")); + + /** + * {@code minecraft:green_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_SHULKER_BOX = create(key("green_shulker_box")); + + /** + * {@code minecraft:green_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_STAINED_GLASS = create(key("green_stained_glass")); + + /** + * {@code minecraft:green_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_STAINED_GLASS_PANE = create(key("green_stained_glass_pane")); + + /** + * {@code minecraft:green_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_TERRACOTTA = create(key("green_terracotta")); + + /** + * {@code minecraft:green_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_WALL_BANNER = create(key("green_wall_banner")); + + /** + * {@code minecraft:green_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_WOOL = create(key("green_wool")); + + /** + * {@code minecraft:grindstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRINDSTONE = create(key("grindstone")); + + /** + * {@code minecraft:hanging_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HANGING_ROOTS = create(key("hanging_roots")); + + /** + * {@code minecraft:hay_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HAY_BLOCK = create(key("hay_block")); + + /** + * {@code minecraft:heavy_core} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEAVY_CORE = create(key("heavy_core")); + + /** + * {@code minecraft:heavy_weighted_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEAVY_WEIGHTED_PRESSURE_PLATE = create(key("heavy_weighted_pressure_plate")); + + /** + * {@code minecraft:honey_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEY_BLOCK = create(key("honey_block")); + + /** + * {@code minecraft:honeycomb_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEYCOMB_BLOCK = create(key("honeycomb_block")); + + /** + * {@code minecraft:hopper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOPPER = create(key("hopper")); + + /** + * {@code minecraft:horn_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL = create(key("horn_coral")); + + /** + * {@code minecraft:horn_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL_BLOCK = create(key("horn_coral_block")); + + /** + * {@code minecraft:horn_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL_FAN = create(key("horn_coral_fan")); + + /** + * {@code minecraft:horn_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL_WALL_FAN = create(key("horn_coral_wall_fan")); + + /** + * {@code minecraft:ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ICE = create(key("ice")); + + /** + * {@code minecraft:infested_chiseled_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_CHISELED_STONE_BRICKS = create(key("infested_chiseled_stone_bricks")); + + /** + * {@code minecraft:infested_cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_COBBLESTONE = create(key("infested_cobblestone")); + + /** + * {@code minecraft:infested_cracked_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_CRACKED_STONE_BRICKS = create(key("infested_cracked_stone_bricks")); + + /** + * {@code minecraft:infested_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_DEEPSLATE = create(key("infested_deepslate")); + + /** + * {@code minecraft:infested_mossy_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_MOSSY_STONE_BRICKS = create(key("infested_mossy_stone_bricks")); + + /** + * {@code minecraft:infested_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_STONE = create(key("infested_stone")); + + /** + * {@code minecraft:infested_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_STONE_BRICKS = create(key("infested_stone_bricks")); + + /** + * {@code minecraft:iron_bars} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_BARS = create(key("iron_bars")); + + /** + * {@code minecraft:iron_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_BLOCK = create(key("iron_block")); + + /** + * {@code minecraft:iron_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_DOOR = create(key("iron_door")); + + /** + * {@code minecraft:iron_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_ORE = create(key("iron_ore")); + + /** + * {@code minecraft:iron_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_TRAPDOOR = create(key("iron_trapdoor")); + + /** + * {@code minecraft:jack_o_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JACK_O_LANTERN = create(key("jack_o_lantern")); + + /** + * {@code minecraft:jigsaw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JIGSAW = create(key("jigsaw")); + + /** + * {@code minecraft:jukebox} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX = create(key("jukebox")); + + /** + * {@code minecraft:jungle_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_BUTTON = create(key("jungle_button")); + + /** + * {@code minecraft:jungle_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_DOOR = create(key("jungle_door")); + + /** + * {@code minecraft:jungle_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_FENCE = create(key("jungle_fence")); + + /** + * {@code minecraft:jungle_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_FENCE_GATE = create(key("jungle_fence_gate")); + + /** + * {@code minecraft:jungle_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_HANGING_SIGN = create(key("jungle_hanging_sign")); + + /** + * {@code minecraft:jungle_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_LEAVES = create(key("jungle_leaves")); + + /** + * {@code minecraft:jungle_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_LOG = create(key("jungle_log")); + + /** + * {@code minecraft:jungle_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_PLANKS = create(key("jungle_planks")); + + /** + * {@code minecraft:jungle_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_PRESSURE_PLATE = create(key("jungle_pressure_plate")); + + /** + * {@code minecraft:jungle_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SAPLING = create(key("jungle_sapling")); + + /** + * {@code minecraft:jungle_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SIGN = create(key("jungle_sign")); + + /** + * {@code minecraft:jungle_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SLAB = create(key("jungle_slab")); + + /** + * {@code minecraft:jungle_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_STAIRS = create(key("jungle_stairs")); + + /** + * {@code minecraft:jungle_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_TRAPDOOR = create(key("jungle_trapdoor")); + + /** + * {@code minecraft:jungle_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_WALL_HANGING_SIGN = create(key("jungle_wall_hanging_sign")); + + /** + * {@code minecraft:jungle_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_WALL_SIGN = create(key("jungle_wall_sign")); + + /** + * {@code minecraft:jungle_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_WOOD = create(key("jungle_wood")); + + /** + * {@code minecraft:kelp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KELP = create(key("kelp")); + + /** + * {@code minecraft:kelp_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KELP_PLANT = create(key("kelp_plant")); + + /** + * {@code minecraft:ladder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LADDER = create(key("ladder")); + + /** + * {@code minecraft:lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LANTERN = create(key("lantern")); + + /** + * {@code minecraft:lapis_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS_BLOCK = create(key("lapis_block")); + + /** + * {@code minecraft:lapis_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS_ORE = create(key("lapis_ore")); + + /** + * {@code minecraft:large_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LARGE_AMETHYST_BUD = create(key("large_amethyst_bud")); + + /** + * {@code minecraft:large_fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LARGE_FERN = create(key("large_fern")); + + /** + * {@code minecraft:lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA = create(key("lava")); + + /** + * {@code minecraft:lava_cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA_CAULDRON = create(key("lava_cauldron")); + + /** + * {@code minecraft:lectern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LECTERN = create(key("lectern")); + + /** + * {@code minecraft:lever} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEVER = create(key("lever")); + + /** + * {@code minecraft:light} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT = create(key("light")); + + /** + * {@code minecraft:light_blue_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_BANNER = create(key("light_blue_banner")); + + /** + * {@code minecraft:light_blue_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_BED = create(key("light_blue_bed")); + + /** + * {@code minecraft:light_blue_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CANDLE = create(key("light_blue_candle")); + + /** + * {@code minecraft:light_blue_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CANDLE_CAKE = create(key("light_blue_candle_cake")); + + /** + * {@code minecraft:light_blue_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CARPET = create(key("light_blue_carpet")); + + /** + * {@code minecraft:light_blue_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CONCRETE = create(key("light_blue_concrete")); + + /** + * {@code minecraft:light_blue_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CONCRETE_POWDER = create(key("light_blue_concrete_powder")); + + /** + * {@code minecraft:light_blue_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_GLAZED_TERRACOTTA = create(key("light_blue_glazed_terracotta")); + + /** + * {@code minecraft:light_blue_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_SHULKER_BOX = create(key("light_blue_shulker_box")); + + /** + * {@code minecraft:light_blue_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_STAINED_GLASS = create(key("light_blue_stained_glass")); + + /** + * {@code minecraft:light_blue_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_STAINED_GLASS_PANE = create(key("light_blue_stained_glass_pane")); + + /** + * {@code minecraft:light_blue_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_TERRACOTTA = create(key("light_blue_terracotta")); + + /** + * {@code minecraft:light_blue_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_WALL_BANNER = create(key("light_blue_wall_banner")); + + /** + * {@code minecraft:light_blue_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_WOOL = create(key("light_blue_wool")); + + /** + * {@code minecraft:light_gray_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_BANNER = create(key("light_gray_banner")); + + /** + * {@code minecraft:light_gray_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_BED = create(key("light_gray_bed")); + + /** + * {@code minecraft:light_gray_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CANDLE = create(key("light_gray_candle")); + + /** + * {@code minecraft:light_gray_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CANDLE_CAKE = create(key("light_gray_candle_cake")); + + /** + * {@code minecraft:light_gray_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CARPET = create(key("light_gray_carpet")); + + /** + * {@code minecraft:light_gray_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CONCRETE = create(key("light_gray_concrete")); + + /** + * {@code minecraft:light_gray_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CONCRETE_POWDER = create(key("light_gray_concrete_powder")); + + /** + * {@code minecraft:light_gray_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_GLAZED_TERRACOTTA = create(key("light_gray_glazed_terracotta")); + + /** + * {@code minecraft:light_gray_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_SHULKER_BOX = create(key("light_gray_shulker_box")); + + /** + * {@code minecraft:light_gray_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_STAINED_GLASS = create(key("light_gray_stained_glass")); + + /** + * {@code minecraft:light_gray_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_STAINED_GLASS_PANE = create(key("light_gray_stained_glass_pane")); + + /** + * {@code minecraft:light_gray_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_TERRACOTTA = create(key("light_gray_terracotta")); + + /** + * {@code minecraft:light_gray_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_WALL_BANNER = create(key("light_gray_wall_banner")); + + /** + * {@code minecraft:light_gray_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_WOOL = create(key("light_gray_wool")); + + /** + * {@code minecraft:light_weighted_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_WEIGHTED_PRESSURE_PLATE = create(key("light_weighted_pressure_plate")); + + /** + * {@code minecraft:lightning_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_ROD = create(key("lightning_rod")); + + /** + * {@code minecraft:lilac} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILAC = create(key("lilac")); + + /** + * {@code minecraft:lily_of_the_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILY_OF_THE_VALLEY = create(key("lily_of_the_valley")); + + /** + * {@code minecraft:lily_pad} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILY_PAD = create(key("lily_pad")); + + /** + * {@code minecraft:lime_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_BANNER = create(key("lime_banner")); + + /** + * {@code minecraft:lime_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_BED = create(key("lime_bed")); + + /** + * {@code minecraft:lime_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CANDLE = create(key("lime_candle")); + + /** + * {@code minecraft:lime_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CANDLE_CAKE = create(key("lime_candle_cake")); + + /** + * {@code minecraft:lime_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CARPET = create(key("lime_carpet")); + + /** + * {@code minecraft:lime_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CONCRETE = create(key("lime_concrete")); + + /** + * {@code minecraft:lime_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CONCRETE_POWDER = create(key("lime_concrete_powder")); + + /** + * {@code minecraft:lime_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_GLAZED_TERRACOTTA = create(key("lime_glazed_terracotta")); + + /** + * {@code minecraft:lime_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_SHULKER_BOX = create(key("lime_shulker_box")); + + /** + * {@code minecraft:lime_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_STAINED_GLASS = create(key("lime_stained_glass")); + + /** + * {@code minecraft:lime_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_STAINED_GLASS_PANE = create(key("lime_stained_glass_pane")); + + /** + * {@code minecraft:lime_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_TERRACOTTA = create(key("lime_terracotta")); + + /** + * {@code minecraft:lime_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_WALL_BANNER = create(key("lime_wall_banner")); + + /** + * {@code minecraft:lime_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_WOOL = create(key("lime_wool")); + + /** + * {@code minecraft:lodestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LODESTONE = create(key("lodestone")); + + /** + * {@code minecraft:loom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOOM = create(key("loom")); + + /** + * {@code minecraft:magenta_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_BANNER = create(key("magenta_banner")); + + /** + * {@code minecraft:magenta_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_BED = create(key("magenta_bed")); + + /** + * {@code minecraft:magenta_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CANDLE = create(key("magenta_candle")); + + /** + * {@code minecraft:magenta_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CANDLE_CAKE = create(key("magenta_candle_cake")); + + /** + * {@code minecraft:magenta_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CARPET = create(key("magenta_carpet")); + + /** + * {@code minecraft:magenta_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CONCRETE = create(key("magenta_concrete")); + + /** + * {@code minecraft:magenta_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CONCRETE_POWDER = create(key("magenta_concrete_powder")); + + /** + * {@code minecraft:magenta_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_GLAZED_TERRACOTTA = create(key("magenta_glazed_terracotta")); + + /** + * {@code minecraft:magenta_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_SHULKER_BOX = create(key("magenta_shulker_box")); + + /** + * {@code minecraft:magenta_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_STAINED_GLASS = create(key("magenta_stained_glass")); + + /** + * {@code minecraft:magenta_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_STAINED_GLASS_PANE = create(key("magenta_stained_glass_pane")); + + /** + * {@code minecraft:magenta_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_TERRACOTTA = create(key("magenta_terracotta")); + + /** + * {@code minecraft:magenta_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_WALL_BANNER = create(key("magenta_wall_banner")); + + /** + * {@code minecraft:magenta_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_WOOL = create(key("magenta_wool")); + + /** + * {@code minecraft:magma_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGMA_BLOCK = create(key("magma_block")); + + /** + * {@code minecraft:mangrove_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_BUTTON = create(key("mangrove_button")); + + /** + * {@code minecraft:mangrove_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_DOOR = create(key("mangrove_door")); + + /** + * {@code minecraft:mangrove_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_FENCE = create(key("mangrove_fence")); + + /** + * {@code minecraft:mangrove_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_FENCE_GATE = create(key("mangrove_fence_gate")); + + /** + * {@code minecraft:mangrove_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_HANGING_SIGN = create(key("mangrove_hanging_sign")); + + /** + * {@code minecraft:mangrove_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_LEAVES = create(key("mangrove_leaves")); + + /** + * {@code minecraft:mangrove_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_LOG = create(key("mangrove_log")); + + /** + * {@code minecraft:mangrove_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PLANKS = create(key("mangrove_planks")); + + /** + * {@code minecraft:mangrove_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PRESSURE_PLATE = create(key("mangrove_pressure_plate")); + + /** + * {@code minecraft:mangrove_propagule} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PROPAGULE = create(key("mangrove_propagule")); + + /** + * {@code minecraft:mangrove_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_ROOTS = create(key("mangrove_roots")); + + /** + * {@code minecraft:mangrove_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SIGN = create(key("mangrove_sign")); + + /** + * {@code minecraft:mangrove_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SLAB = create(key("mangrove_slab")); + + /** + * {@code minecraft:mangrove_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_STAIRS = create(key("mangrove_stairs")); + + /** + * {@code minecraft:mangrove_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_TRAPDOOR = create(key("mangrove_trapdoor")); + + /** + * {@code minecraft:mangrove_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_WALL_HANGING_SIGN = create(key("mangrove_wall_hanging_sign")); + + /** + * {@code minecraft:mangrove_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_WALL_SIGN = create(key("mangrove_wall_sign")); + + /** + * {@code minecraft:mangrove_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_WOOD = create(key("mangrove_wood")); + + /** + * {@code minecraft:medium_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MEDIUM_AMETHYST_BUD = create(key("medium_amethyst_bud")); + + /** + * {@code minecraft:melon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELON = create(key("melon")); + + /** + * {@code minecraft:melon_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELON_STEM = create(key("melon_stem")); + + /** + * {@code minecraft:moss_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSS_BLOCK = create(key("moss_block")); + + /** + * {@code minecraft:moss_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSS_CARPET = create(key("moss_carpet")); + + /** + * {@code minecraft:mossy_cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE = create(key("mossy_cobblestone")); + + /** + * {@code minecraft:mossy_cobblestone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_SLAB = create(key("mossy_cobblestone_slab")); + + /** + * {@code minecraft:mossy_cobblestone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_STAIRS = create(key("mossy_cobblestone_stairs")); + + /** + * {@code minecraft:mossy_cobblestone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_WALL = create(key("mossy_cobblestone_wall")); + + /** + * {@code minecraft:mossy_stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_SLAB = create(key("mossy_stone_brick_slab")); + + /** + * {@code minecraft:mossy_stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_STAIRS = create(key("mossy_stone_brick_stairs")); + + /** + * {@code minecraft:mossy_stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_WALL = create(key("mossy_stone_brick_wall")); + + /** + * {@code minecraft:mossy_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICKS = create(key("mossy_stone_bricks")); + + /** + * {@code minecraft:moving_piston} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOVING_PISTON = create(key("moving_piston")); + + /** + * {@code minecraft:mud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD = create(key("mud")); + + /** + * {@code minecraft:mud_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_SLAB = create(key("mud_brick_slab")); + + /** + * {@code minecraft:mud_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_STAIRS = create(key("mud_brick_stairs")); + + /** + * {@code minecraft:mud_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_WALL = create(key("mud_brick_wall")); + + /** + * {@code minecraft:mud_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICKS = create(key("mud_bricks")); + + /** + * {@code minecraft:muddy_mangrove_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUDDY_MANGROVE_ROOTS = create(key("muddy_mangrove_roots")); + + /** + * {@code minecraft:mushroom_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSHROOM_STEM = create(key("mushroom_stem")); + + /** + * {@code minecraft:mycelium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MYCELIUM = create(key("mycelium")); + + /** + * {@code minecraft:nether_brick_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_FENCE = create(key("nether_brick_fence")); + + /** + * {@code minecraft:nether_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_SLAB = create(key("nether_brick_slab")); + + /** + * {@code minecraft:nether_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_STAIRS = create(key("nether_brick_stairs")); + + /** + * {@code minecraft:nether_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_WALL = create(key("nether_brick_wall")); + + /** + * {@code minecraft:nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICKS = create(key("nether_bricks")); + + /** + * {@code minecraft:nether_gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_GOLD_ORE = create(key("nether_gold_ore")); + + /** + * {@code minecraft:nether_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_PORTAL = create(key("nether_portal")); + + /** + * {@code minecraft:nether_quartz_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_QUARTZ_ORE = create(key("nether_quartz_ore")); + + /** + * {@code minecraft:nether_sprouts} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_SPROUTS = create(key("nether_sprouts")); + + /** + * {@code minecraft:nether_wart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WART = create(key("nether_wart")); + + /** + * {@code minecraft:nether_wart_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WART_BLOCK = create(key("nether_wart_block")); + + /** + * {@code minecraft:netherite_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_BLOCK = create(key("netherite_block")); + + /** + * {@code minecraft:netherrack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERRACK = create(key("netherrack")); + + /** + * {@code minecraft:note_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NOTE_BLOCK = create(key("note_block")); + + /** + * {@code minecraft:oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_BUTTON = create(key("oak_button")); + + /** + * {@code minecraft:oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_DOOR = create(key("oak_door")); + + /** + * {@code minecraft:oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_FENCE = create(key("oak_fence")); + + /** + * {@code minecraft:oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_FENCE_GATE = create(key("oak_fence_gate")); + + /** + * {@code minecraft:oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_HANGING_SIGN = create(key("oak_hanging_sign")); + + /** + * {@code minecraft:oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_LEAVES = create(key("oak_leaves")); + + /** + * {@code minecraft:oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_LOG = create(key("oak_log")); + + /** + * {@code minecraft:oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_PLANKS = create(key("oak_planks")); + + /** + * {@code minecraft:oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_PRESSURE_PLATE = create(key("oak_pressure_plate")); + + /** + * {@code minecraft:oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SAPLING = create(key("oak_sapling")); + + /** + * {@code minecraft:oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SIGN = create(key("oak_sign")); + + /** + * {@code minecraft:oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SLAB = create(key("oak_slab")); + + /** + * {@code minecraft:oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_STAIRS = create(key("oak_stairs")); + + /** + * {@code minecraft:oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_TRAPDOOR = create(key("oak_trapdoor")); + + /** + * {@code minecraft:oak_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_WALL_HANGING_SIGN = create(key("oak_wall_hanging_sign")); + + /** + * {@code minecraft:oak_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_WALL_SIGN = create(key("oak_wall_sign")); + + /** + * {@code minecraft:oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_WOOD = create(key("oak_wood")); + + /** + * {@code minecraft:observer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OBSERVER = create(key("observer")); + + /** + * {@code minecraft:obsidian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OBSIDIAN = create(key("obsidian")); + + /** + * {@code minecraft:ochre_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCHRE_FROGLIGHT = create(key("ochre_froglight")); + + /** + * {@code minecraft:open_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OPEN_EYEBLOSSOM = create(key("open_eyeblossom")); + + /** + * {@code minecraft:orange_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_BANNER = create(key("orange_banner")); + + /** + * {@code minecraft:orange_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_BED = create(key("orange_bed")); + + /** + * {@code minecraft:orange_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CANDLE = create(key("orange_candle")); + + /** + * {@code minecraft:orange_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CANDLE_CAKE = create(key("orange_candle_cake")); + + /** + * {@code minecraft:orange_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CARPET = create(key("orange_carpet")); + + /** + * {@code minecraft:orange_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CONCRETE = create(key("orange_concrete")); + + /** + * {@code minecraft:orange_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CONCRETE_POWDER = create(key("orange_concrete_powder")); + + /** + * {@code minecraft:orange_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_GLAZED_TERRACOTTA = create(key("orange_glazed_terracotta")); + + /** + * {@code minecraft:orange_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_SHULKER_BOX = create(key("orange_shulker_box")); + + /** + * {@code minecraft:orange_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_STAINED_GLASS = create(key("orange_stained_glass")); + + /** + * {@code minecraft:orange_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_STAINED_GLASS_PANE = create(key("orange_stained_glass_pane")); + + /** + * {@code minecraft:orange_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_TERRACOTTA = create(key("orange_terracotta")); + + /** + * {@code minecraft:orange_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_TULIP = create(key("orange_tulip")); + + /** + * {@code minecraft:orange_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_WALL_BANNER = create(key("orange_wall_banner")); + + /** + * {@code minecraft:orange_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_WOOL = create(key("orange_wool")); + + /** + * {@code minecraft:oxeye_daisy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXEYE_DAISY = create(key("oxeye_daisy")); + + /** + * {@code minecraft:oxidized_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CHISELED_COPPER = create(key("oxidized_chiseled_copper")); + + /** + * {@code minecraft:oxidized_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER = create(key("oxidized_copper")); + + /** + * {@code minecraft:oxidized_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_BULB = create(key("oxidized_copper_bulb")); + + /** + * {@code minecraft:oxidized_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_DOOR = create(key("oxidized_copper_door")); + + /** + * {@code minecraft:oxidized_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_GRATE = create(key("oxidized_copper_grate")); + + /** + * {@code minecraft:oxidized_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_TRAPDOOR = create(key("oxidized_copper_trapdoor")); + + /** + * {@code minecraft:oxidized_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER = create(key("oxidized_cut_copper")); + + /** + * {@code minecraft:oxidized_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER_SLAB = create(key("oxidized_cut_copper_slab")); + + /** + * {@code minecraft:oxidized_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER_STAIRS = create(key("oxidized_cut_copper_stairs")); + + /** + * {@code minecraft:packed_ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PACKED_ICE = create(key("packed_ice")); + + /** + * {@code minecraft:packed_mud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PACKED_MUD = create(key("packed_mud")); + + /** + * {@code minecraft:pale_hanging_moss} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_HANGING_MOSS = create(key("pale_hanging_moss")); + + /** + * {@code minecraft:pale_moss_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_MOSS_BLOCK = create(key("pale_moss_block")); + + /** + * {@code minecraft:pale_moss_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_MOSS_CARPET = create(key("pale_moss_carpet")); + + /** + * {@code minecraft:pale_oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_BUTTON = create(key("pale_oak_button")); + + /** + * {@code minecraft:pale_oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_DOOR = create(key("pale_oak_door")); + + /** + * {@code minecraft:pale_oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_FENCE = create(key("pale_oak_fence")); + + /** + * {@code minecraft:pale_oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_FENCE_GATE = create(key("pale_oak_fence_gate")); + + /** + * {@code minecraft:pale_oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_HANGING_SIGN = create(key("pale_oak_hanging_sign")); + + /** + * {@code minecraft:pale_oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_LEAVES = create(key("pale_oak_leaves")); + + /** + * {@code minecraft:pale_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_LOG = create(key("pale_oak_log")); + + /** + * {@code minecraft:pale_oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_PLANKS = create(key("pale_oak_planks")); + + /** + * {@code minecraft:pale_oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_PRESSURE_PLATE = create(key("pale_oak_pressure_plate")); + + /** + * {@code minecraft:pale_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SAPLING = create(key("pale_oak_sapling")); + + /** + * {@code minecraft:pale_oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SIGN = create(key("pale_oak_sign")); + + /** + * {@code minecraft:pale_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SLAB = create(key("pale_oak_slab")); + + /** + * {@code minecraft:pale_oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_STAIRS = create(key("pale_oak_stairs")); + + /** + * {@code minecraft:pale_oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_TRAPDOOR = create(key("pale_oak_trapdoor")); + + /** + * {@code minecraft:pale_oak_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_WALL_HANGING_SIGN = create(key("pale_oak_wall_hanging_sign")); + + /** + * {@code minecraft:pale_oak_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_WALL_SIGN = create(key("pale_oak_wall_sign")); + + /** + * {@code minecraft:pale_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_WOOD = create(key("pale_oak_wood")); + + /** + * {@code minecraft:pearlescent_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PEARLESCENT_FROGLIGHT = create(key("pearlescent_froglight")); + + /** + * {@code minecraft:peony} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PEONY = create(key("peony")); + + /** + * {@code minecraft:petrified_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PETRIFIED_OAK_SLAB = create(key("petrified_oak_slab")); + + /** + * {@code minecraft:piglin_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_HEAD = create(key("piglin_head")); + + /** + * {@code minecraft:piglin_wall_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_WALL_HEAD = create(key("piglin_wall_head")); + + /** + * {@code minecraft:pink_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_BANNER = create(key("pink_banner")); + + /** + * {@code minecraft:pink_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_BED = create(key("pink_bed")); + + /** + * {@code minecraft:pink_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CANDLE = create(key("pink_candle")); + + /** + * {@code minecraft:pink_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CANDLE_CAKE = create(key("pink_candle_cake")); + + /** + * {@code minecraft:pink_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CARPET = create(key("pink_carpet")); + + /** + * {@code minecraft:pink_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CONCRETE = create(key("pink_concrete")); + + /** + * {@code minecraft:pink_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CONCRETE_POWDER = create(key("pink_concrete_powder")); + + /** + * {@code minecraft:pink_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_GLAZED_TERRACOTTA = create(key("pink_glazed_terracotta")); + + /** + * {@code minecraft:pink_petals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_PETALS = create(key("pink_petals")); + + /** + * {@code minecraft:pink_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_SHULKER_BOX = create(key("pink_shulker_box")); + + /** + * {@code minecraft:pink_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_STAINED_GLASS = create(key("pink_stained_glass")); + + /** + * {@code minecraft:pink_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_STAINED_GLASS_PANE = create(key("pink_stained_glass_pane")); + + /** + * {@code minecraft:pink_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_TERRACOTTA = create(key("pink_terracotta")); + + /** + * {@code minecraft:pink_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_TULIP = create(key("pink_tulip")); + + /** + * {@code minecraft:pink_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_WALL_BANNER = create(key("pink_wall_banner")); + + /** + * {@code minecraft:pink_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_WOOL = create(key("pink_wool")); + + /** + * {@code minecraft:piston} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PISTON = create(key("piston")); + + /** + * {@code minecraft:piston_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PISTON_HEAD = create(key("piston_head")); + + /** + * {@code minecraft:pitcher_crop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PITCHER_CROP = create(key("pitcher_crop")); + + /** + * {@code minecraft:pitcher_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PITCHER_PLANT = create(key("pitcher_plant")); + + /** + * {@code minecraft:player_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_HEAD = create(key("player_head")); + + /** + * {@code minecraft:player_wall_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_WALL_HEAD = create(key("player_wall_head")); + + /** + * {@code minecraft:podzol} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PODZOL = create(key("podzol")); + + /** + * {@code minecraft:pointed_dripstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POINTED_DRIPSTONE = create(key("pointed_dripstone")); + + /** + * {@code minecraft:polished_andesite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE = create(key("polished_andesite")); + + /** + * {@code minecraft:polished_andesite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE_SLAB = create(key("polished_andesite_slab")); + + /** + * {@code minecraft:polished_andesite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE_STAIRS = create(key("polished_andesite_stairs")); + + /** + * {@code minecraft:polished_basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BASALT = create(key("polished_basalt")); + + /** + * {@code minecraft:polished_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE = create(key("polished_blackstone")); + + /** + * {@code minecraft:polished_blackstone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_SLAB = create(key("polished_blackstone_brick_slab")); + + /** + * {@code minecraft:polished_blackstone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_STAIRS = create(key("polished_blackstone_brick_stairs")); + + /** + * {@code minecraft:polished_blackstone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_WALL = create(key("polished_blackstone_brick_wall")); + + /** + * {@code minecraft:polished_blackstone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICKS = create(key("polished_blackstone_bricks")); + + /** + * {@code minecraft:polished_blackstone_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BUTTON = create(key("polished_blackstone_button")); + + /** + * {@code minecraft:polished_blackstone_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_PRESSURE_PLATE = create(key("polished_blackstone_pressure_plate")); + + /** + * {@code minecraft:polished_blackstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_SLAB = create(key("polished_blackstone_slab")); + + /** + * {@code minecraft:polished_blackstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_STAIRS = create(key("polished_blackstone_stairs")); + + /** + * {@code minecraft:polished_blackstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_WALL = create(key("polished_blackstone_wall")); + + /** + * {@code minecraft:polished_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE = create(key("polished_deepslate")); + + /** + * {@code minecraft:polished_deepslate_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_SLAB = create(key("polished_deepslate_slab")); + + /** + * {@code minecraft:polished_deepslate_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_STAIRS = create(key("polished_deepslate_stairs")); + + /** + * {@code minecraft:polished_deepslate_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_WALL = create(key("polished_deepslate_wall")); + + /** + * {@code minecraft:polished_diorite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE = create(key("polished_diorite")); + + /** + * {@code minecraft:polished_diorite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE_SLAB = create(key("polished_diorite_slab")); + + /** + * {@code minecraft:polished_diorite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE_STAIRS = create(key("polished_diorite_stairs")); + + /** + * {@code minecraft:polished_granite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE = create(key("polished_granite")); + + /** + * {@code minecraft:polished_granite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE_SLAB = create(key("polished_granite_slab")); + + /** + * {@code minecraft:polished_granite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE_STAIRS = create(key("polished_granite_stairs")); + + /** + * {@code minecraft:polished_tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF = create(key("polished_tuff")); + + /** + * {@code minecraft:polished_tuff_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_SLAB = create(key("polished_tuff_slab")); + + /** + * {@code minecraft:polished_tuff_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_STAIRS = create(key("polished_tuff_stairs")); + + /** + * {@code minecraft:polished_tuff_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_WALL = create(key("polished_tuff_wall")); + + /** + * {@code minecraft:poppy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POPPY = create(key("poppy")); + + /** + * {@code minecraft:potatoes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTATOES = create(key("potatoes")); + + /** + * {@code minecraft:potted_acacia_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_ACACIA_SAPLING = create(key("potted_acacia_sapling")); + + /** + * {@code minecraft:potted_allium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_ALLIUM = create(key("potted_allium")); + + /** + * {@code minecraft:potted_azalea_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_AZALEA_BUSH = create(key("potted_azalea_bush")); + + /** + * {@code minecraft:potted_azure_bluet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_AZURE_BLUET = create(key("potted_azure_bluet")); + + /** + * {@code minecraft:potted_bamboo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_BAMBOO = create(key("potted_bamboo")); + + /** + * {@code minecraft:potted_birch_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_BIRCH_SAPLING = create(key("potted_birch_sapling")); + + /** + * {@code minecraft:potted_blue_orchid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_BLUE_ORCHID = create(key("potted_blue_orchid")); + + /** + * {@code minecraft:potted_brown_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_BROWN_MUSHROOM = create(key("potted_brown_mushroom")); + + /** + * {@code minecraft:potted_cactus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CACTUS = create(key("potted_cactus")); + + /** + * {@code minecraft:potted_cherry_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CHERRY_SAPLING = create(key("potted_cherry_sapling")); + + /** + * {@code minecraft:potted_closed_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CLOSED_EYEBLOSSOM = create(key("potted_closed_eyeblossom")); + + /** + * {@code minecraft:potted_cornflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CORNFLOWER = create(key("potted_cornflower")); + + /** + * {@code minecraft:potted_crimson_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CRIMSON_FUNGUS = create(key("potted_crimson_fungus")); + + /** + * {@code minecraft:potted_crimson_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_CRIMSON_ROOTS = create(key("potted_crimson_roots")); + + /** + * {@code minecraft:potted_dandelion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_DANDELION = create(key("potted_dandelion")); + + /** + * {@code minecraft:potted_dark_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_DARK_OAK_SAPLING = create(key("potted_dark_oak_sapling")); + + /** + * {@code minecraft:potted_dead_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_DEAD_BUSH = create(key("potted_dead_bush")); + + /** + * {@code minecraft:potted_fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_FERN = create(key("potted_fern")); + + /** + * {@code minecraft:potted_flowering_azalea_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_FLOWERING_AZALEA_BUSH = create(key("potted_flowering_azalea_bush")); + + /** + * {@code minecraft:potted_jungle_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_JUNGLE_SAPLING = create(key("potted_jungle_sapling")); + + /** + * {@code minecraft:potted_lily_of_the_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_LILY_OF_THE_VALLEY = create(key("potted_lily_of_the_valley")); + + /** + * {@code minecraft:potted_mangrove_propagule} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_MANGROVE_PROPAGULE = create(key("potted_mangrove_propagule")); + + /** + * {@code minecraft:potted_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_OAK_SAPLING = create(key("potted_oak_sapling")); + + /** + * {@code minecraft:potted_open_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_OPEN_EYEBLOSSOM = create(key("potted_open_eyeblossom")); + + /** + * {@code minecraft:potted_orange_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_ORANGE_TULIP = create(key("potted_orange_tulip")); + + /** + * {@code minecraft:potted_oxeye_daisy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_OXEYE_DAISY = create(key("potted_oxeye_daisy")); + + /** + * {@code minecraft:potted_pale_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_PALE_OAK_SAPLING = create(key("potted_pale_oak_sapling")); + + /** + * {@code minecraft:potted_pink_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_PINK_TULIP = create(key("potted_pink_tulip")); + + /** + * {@code minecraft:potted_poppy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_POPPY = create(key("potted_poppy")); + + /** + * {@code minecraft:potted_red_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_RED_MUSHROOM = create(key("potted_red_mushroom")); + + /** + * {@code minecraft:potted_red_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_RED_TULIP = create(key("potted_red_tulip")); + + /** + * {@code minecraft:potted_spruce_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_SPRUCE_SAPLING = create(key("potted_spruce_sapling")); + + /** + * {@code minecraft:potted_torchflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_TORCHFLOWER = create(key("potted_torchflower")); + + /** + * {@code minecraft:potted_warped_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_WARPED_FUNGUS = create(key("potted_warped_fungus")); + + /** + * {@code minecraft:potted_warped_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_WARPED_ROOTS = create(key("potted_warped_roots")); + + /** + * {@code minecraft:potted_white_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_WHITE_TULIP = create(key("potted_white_tulip")); + + /** + * {@code minecraft:potted_wither_rose} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTTED_WITHER_ROSE = create(key("potted_wither_rose")); + + /** + * {@code minecraft:powder_snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWDER_SNOW = create(key("powder_snow")); + + /** + * {@code minecraft:powder_snow_cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWDER_SNOW_CAULDRON = create(key("powder_snow_cauldron")); + + /** + * {@code minecraft:powered_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWERED_RAIL = create(key("powered_rail")); + + /** + * {@code minecraft:prismarine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE = create(key("prismarine")); + + /** + * {@code minecraft:prismarine_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICK_SLAB = create(key("prismarine_brick_slab")); + + /** + * {@code minecraft:prismarine_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICK_STAIRS = create(key("prismarine_brick_stairs")); + + /** + * {@code minecraft:prismarine_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICKS = create(key("prismarine_bricks")); + + /** + * {@code minecraft:prismarine_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_SLAB = create(key("prismarine_slab")); + + /** + * {@code minecraft:prismarine_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_STAIRS = create(key("prismarine_stairs")); + + /** + * {@code minecraft:prismarine_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_WALL = create(key("prismarine_wall")); + + /** + * {@code minecraft:pumpkin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUMPKIN = create(key("pumpkin")); + + /** + * {@code minecraft:pumpkin_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUMPKIN_STEM = create(key("pumpkin_stem")); + + /** + * {@code minecraft:purple_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_BANNER = create(key("purple_banner")); + + /** + * {@code minecraft:purple_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_BED = create(key("purple_bed")); + + /** + * {@code minecraft:purple_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CANDLE = create(key("purple_candle")); + + /** + * {@code minecraft:purple_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CANDLE_CAKE = create(key("purple_candle_cake")); + + /** + * {@code minecraft:purple_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CARPET = create(key("purple_carpet")); + + /** + * {@code minecraft:purple_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CONCRETE = create(key("purple_concrete")); + + /** + * {@code minecraft:purple_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CONCRETE_POWDER = create(key("purple_concrete_powder")); + + /** + * {@code minecraft:purple_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_GLAZED_TERRACOTTA = create(key("purple_glazed_terracotta")); + + /** + * {@code minecraft:purple_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_SHULKER_BOX = create(key("purple_shulker_box")); + + /** + * {@code minecraft:purple_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_STAINED_GLASS = create(key("purple_stained_glass")); + + /** + * {@code minecraft:purple_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_STAINED_GLASS_PANE = create(key("purple_stained_glass_pane")); + + /** + * {@code minecraft:purple_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_TERRACOTTA = create(key("purple_terracotta")); + + /** + * {@code minecraft:purple_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_WALL_BANNER = create(key("purple_wall_banner")); + + /** + * {@code minecraft:purple_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_WOOL = create(key("purple_wool")); + + /** + * {@code minecraft:purpur_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_BLOCK = create(key("purpur_block")); + + /** + * {@code minecraft:purpur_pillar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_PILLAR = create(key("purpur_pillar")); + + /** + * {@code minecraft:purpur_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_SLAB = create(key("purpur_slab")); + + /** + * {@code minecraft:purpur_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_STAIRS = create(key("purpur_stairs")); + + /** + * {@code minecraft:quartz_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_BLOCK = create(key("quartz_block")); + + /** + * {@code minecraft:quartz_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_BRICKS = create(key("quartz_bricks")); + + /** + * {@code minecraft:quartz_pillar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_PILLAR = create(key("quartz_pillar")); + + /** + * {@code minecraft:quartz_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_SLAB = create(key("quartz_slab")); + + /** + * {@code minecraft:quartz_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_STAIRS = create(key("quartz_stairs")); + + /** + * {@code minecraft:rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAIL = create(key("rail")); + + /** + * {@code minecraft:raw_copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_COPPER_BLOCK = create(key("raw_copper_block")); + + /** + * {@code minecraft:raw_gold_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_GOLD_BLOCK = create(key("raw_gold_block")); + + /** + * {@code minecraft:raw_iron_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_IRON_BLOCK = create(key("raw_iron_block")); + + /** + * {@code minecraft:red_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_BANNER = create(key("red_banner")); + + /** + * {@code minecraft:red_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_BED = create(key("red_bed")); + + /** + * {@code minecraft:red_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CANDLE = create(key("red_candle")); + + /** + * {@code minecraft:red_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CANDLE_CAKE = create(key("red_candle_cake")); + + /** + * {@code minecraft:red_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CARPET = create(key("red_carpet")); + + /** + * {@code minecraft:red_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CONCRETE = create(key("red_concrete")); + + /** + * {@code minecraft:red_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CONCRETE_POWDER = create(key("red_concrete_powder")); + + /** + * {@code minecraft:red_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_GLAZED_TERRACOTTA = create(key("red_glazed_terracotta")); + + /** + * {@code minecraft:red_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_MUSHROOM = create(key("red_mushroom")); + + /** + * {@code minecraft:red_mushroom_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_MUSHROOM_BLOCK = create(key("red_mushroom_block")); + + /** + * {@code minecraft:red_nether_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_SLAB = create(key("red_nether_brick_slab")); + + /** + * {@code minecraft:red_nether_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_STAIRS = create(key("red_nether_brick_stairs")); + + /** + * {@code minecraft:red_nether_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_WALL = create(key("red_nether_brick_wall")); + + /** + * {@code minecraft:red_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICKS = create(key("red_nether_bricks")); + + /** + * {@code minecraft:red_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SAND = create(key("red_sand")); + + /** + * {@code minecraft:red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE = create(key("red_sandstone")); + + /** + * {@code minecraft:red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_SLAB = create(key("red_sandstone_slab")); + + /** + * {@code minecraft:red_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_STAIRS = create(key("red_sandstone_stairs")); + + /** + * {@code minecraft:red_sandstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_WALL = create(key("red_sandstone_wall")); + + /** + * {@code minecraft:red_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SHULKER_BOX = create(key("red_shulker_box")); + + /** + * {@code minecraft:red_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_STAINED_GLASS = create(key("red_stained_glass")); + + /** + * {@code minecraft:red_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_STAINED_GLASS_PANE = create(key("red_stained_glass_pane")); + + /** + * {@code minecraft:red_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_TERRACOTTA = create(key("red_terracotta")); + + /** + * {@code minecraft:red_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_TULIP = create(key("red_tulip")); + + /** + * {@code minecraft:red_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_WALL_BANNER = create(key("red_wall_banner")); + + /** + * {@code minecraft:red_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_WOOL = create(key("red_wool")); + + /** + * {@code minecraft:redstone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_BLOCK = create(key("redstone_block")); + + /** + * {@code minecraft:redstone_lamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_LAMP = create(key("redstone_lamp")); + + /** + * {@code minecraft:redstone_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_ORE = create(key("redstone_ore")); + + /** + * {@code minecraft:redstone_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_TORCH = create(key("redstone_torch")); + + /** + * {@code minecraft:redstone_wall_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_WALL_TORCH = create(key("redstone_wall_torch")); + + /** + * {@code minecraft:redstone_wire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_WIRE = create(key("redstone_wire")); + + /** + * {@code minecraft:reinforced_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REINFORCED_DEEPSLATE = create(key("reinforced_deepslate")); + + /** + * {@code minecraft:repeater} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REPEATER = create(key("repeater")); + + /** + * {@code minecraft:repeating_command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REPEATING_COMMAND_BLOCK = create(key("repeating_command_block")); + + /** + * {@code minecraft:resin_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BLOCK = create(key("resin_block")); + + /** + * {@code minecraft:resin_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_SLAB = create(key("resin_brick_slab")); + + /** + * {@code minecraft:resin_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_STAIRS = create(key("resin_brick_stairs")); + + /** + * {@code minecraft:resin_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_WALL = create(key("resin_brick_wall")); + + /** + * {@code minecraft:resin_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICKS = create(key("resin_bricks")); + + /** + * {@code minecraft:resin_clump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_CLUMP = create(key("resin_clump")); + + /** + * {@code minecraft:respawn_anchor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESPAWN_ANCHOR = create(key("respawn_anchor")); + + /** + * {@code minecraft:rooted_dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ROOTED_DIRT = create(key("rooted_dirt")); + + /** + * {@code minecraft:rose_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ROSE_BUSH = create(key("rose_bush")); + + /** + * {@code minecraft:sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAND = create(key("sand")); + + /** + * {@code minecraft:sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE = create(key("sandstone")); + + /** + * {@code minecraft:sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_SLAB = create(key("sandstone_slab")); + + /** + * {@code minecraft:sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_STAIRS = create(key("sandstone_stairs")); + + /** + * {@code minecraft:sandstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_WALL = create(key("sandstone_wall")); + + /** + * {@code minecraft:scaffolding} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCAFFOLDING = create(key("scaffolding")); + + /** + * {@code minecraft:sculk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK = create(key("sculk")); + + /** + * {@code minecraft:sculk_catalyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_CATALYST = create(key("sculk_catalyst")); + + /** + * {@code minecraft:sculk_sensor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SENSOR = create(key("sculk_sensor")); + + /** + * {@code minecraft:sculk_shrieker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SHRIEKER = create(key("sculk_shrieker")); + + /** + * {@code minecraft:sculk_vein} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_VEIN = create(key("sculk_vein")); + + /** + * {@code minecraft:sea_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEA_LANTERN = create(key("sea_lantern")); + + /** + * {@code minecraft:sea_pickle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEA_PICKLE = create(key("sea_pickle")); + + /** + * {@code minecraft:seagrass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEAGRASS = create(key("seagrass")); + + /** + * {@code minecraft:short_grass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHORT_GRASS = create(key("short_grass")); + + /** + * {@code minecraft:shroomlight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHROOMLIGHT = create(key("shroomlight")); + + /** + * {@code minecraft:shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHULKER_BOX = create(key("shulker_box")); + + /** + * {@code minecraft:skeleton_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON_SKULL = create(key("skeleton_skull")); + + /** + * {@code minecraft:skeleton_wall_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON_WALL_SKULL = create(key("skeleton_wall_skull")); + + /** + * {@code minecraft:slime_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLIME_BLOCK = create(key("slime_block")); + + /** + * {@code minecraft:small_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_AMETHYST_BUD = create(key("small_amethyst_bud")); + + /** + * {@code minecraft:small_dripleaf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_DRIPLEAF = create(key("small_dripleaf")); + + /** + * {@code minecraft:smithing_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMITHING_TABLE = create(key("smithing_table")); + + /** + * {@code minecraft:smoker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOKER = create(key("smoker")); + + /** + * {@code minecraft:smooth_basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_BASALT = create(key("smooth_basalt")); + + /** + * {@code minecraft:smooth_quartz} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ = create(key("smooth_quartz")); + + /** + * {@code minecraft:smooth_quartz_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ_SLAB = create(key("smooth_quartz_slab")); + + /** + * {@code minecraft:smooth_quartz_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ_STAIRS = create(key("smooth_quartz_stairs")); + + /** + * {@code minecraft:smooth_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE = create(key("smooth_red_sandstone")); + + /** + * {@code minecraft:smooth_red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE_SLAB = create(key("smooth_red_sandstone_slab")); + + /** + * {@code minecraft:smooth_red_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE_STAIRS = create(key("smooth_red_sandstone_stairs")); + + /** + * {@code minecraft:smooth_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE = create(key("smooth_sandstone")); + + /** + * {@code minecraft:smooth_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE_SLAB = create(key("smooth_sandstone_slab")); + + /** + * {@code minecraft:smooth_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE_STAIRS = create(key("smooth_sandstone_stairs")); + + /** + * {@code minecraft:smooth_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_STONE = create(key("smooth_stone")); + + /** + * {@code minecraft:smooth_stone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_STONE_SLAB = create(key("smooth_stone_slab")); + + /** + * {@code minecraft:sniffer_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNIFFER_EGG = create(key("sniffer_egg")); + + /** + * {@code minecraft:snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW = create(key("snow")); + + /** + * {@code minecraft:snow_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW_BLOCK = create(key("snow_block")); + + /** + * {@code minecraft:soul_campfire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_CAMPFIRE = create(key("soul_campfire")); + + /** + * {@code minecraft:soul_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_FIRE = create(key("soul_fire")); + + /** + * {@code minecraft:soul_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_LANTERN = create(key("soul_lantern")); + + /** + * {@code minecraft:soul_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SAND = create(key("soul_sand")); + + /** + * {@code minecraft:soul_soil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SOIL = create(key("soul_soil")); + + /** + * {@code minecraft:soul_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_TORCH = create(key("soul_torch")); + + /** + * {@code minecraft:soul_wall_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_WALL_TORCH = create(key("soul_wall_torch")); + + /** + * {@code minecraft:spawner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPAWNER = create(key("spawner")); + + /** + * {@code minecraft:sponge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPONGE = create(key("sponge")); + + /** + * {@code minecraft:spore_blossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPORE_BLOSSOM = create(key("spore_blossom")); + + /** + * {@code minecraft:spruce_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_BUTTON = create(key("spruce_button")); + + /** + * {@code minecraft:spruce_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_DOOR = create(key("spruce_door")); + + /** + * {@code minecraft:spruce_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_FENCE = create(key("spruce_fence")); + + /** + * {@code minecraft:spruce_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_FENCE_GATE = create(key("spruce_fence_gate")); + + /** + * {@code minecraft:spruce_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_HANGING_SIGN = create(key("spruce_hanging_sign")); + + /** + * {@code minecraft:spruce_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_LEAVES = create(key("spruce_leaves")); + + /** + * {@code minecraft:spruce_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_LOG = create(key("spruce_log")); + + /** + * {@code minecraft:spruce_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_PLANKS = create(key("spruce_planks")); + + /** + * {@code minecraft:spruce_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_PRESSURE_PLATE = create(key("spruce_pressure_plate")); + + /** + * {@code minecraft:spruce_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SAPLING = create(key("spruce_sapling")); + + /** + * {@code minecraft:spruce_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SIGN = create(key("spruce_sign")); + + /** + * {@code minecraft:spruce_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SLAB = create(key("spruce_slab")); + + /** + * {@code minecraft:spruce_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_STAIRS = create(key("spruce_stairs")); + + /** + * {@code minecraft:spruce_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_TRAPDOOR = create(key("spruce_trapdoor")); + + /** + * {@code minecraft:spruce_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_WALL_HANGING_SIGN = create(key("spruce_wall_hanging_sign")); + + /** + * {@code minecraft:spruce_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_WALL_SIGN = create(key("spruce_wall_sign")); + + /** + * {@code minecraft:spruce_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_WOOD = create(key("spruce_wood")); + + /** + * {@code minecraft:sticky_piston} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STICKY_PISTON = create(key("sticky_piston")); + + /** + * {@code minecraft:stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE = create(key("stone")); + + /** + * {@code minecraft:stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_SLAB = create(key("stone_brick_slab")); + + /** + * {@code minecraft:stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_STAIRS = create(key("stone_brick_stairs")); + + /** + * {@code minecraft:stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_WALL = create(key("stone_brick_wall")); + + /** + * {@code minecraft:stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICKS = create(key("stone_bricks")); + + /** + * {@code minecraft:stone_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BUTTON = create(key("stone_button")); + + /** + * {@code minecraft:stone_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_PRESSURE_PLATE = create(key("stone_pressure_plate")); + + /** + * {@code minecraft:stone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_SLAB = create(key("stone_slab")); + + /** + * {@code minecraft:stone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_STAIRS = create(key("stone_stairs")); + + /** + * {@code minecraft:stonecutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONECUTTER = create(key("stonecutter")); + + /** + * {@code minecraft:stripped_acacia_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_ACACIA_LOG = create(key("stripped_acacia_log")); + + /** + * {@code minecraft:stripped_acacia_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_ACACIA_WOOD = create(key("stripped_acacia_wood")); + + /** + * {@code minecraft:stripped_bamboo_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BAMBOO_BLOCK = create(key("stripped_bamboo_block")); + + /** + * {@code minecraft:stripped_birch_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BIRCH_LOG = create(key("stripped_birch_log")); + + /** + * {@code minecraft:stripped_birch_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BIRCH_WOOD = create(key("stripped_birch_wood")); + + /** + * {@code minecraft:stripped_cherry_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CHERRY_LOG = create(key("stripped_cherry_log")); + + /** + * {@code minecraft:stripped_cherry_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CHERRY_WOOD = create(key("stripped_cherry_wood")); + + /** + * {@code minecraft:stripped_crimson_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CRIMSON_HYPHAE = create(key("stripped_crimson_hyphae")); + + /** + * {@code minecraft:stripped_crimson_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CRIMSON_STEM = create(key("stripped_crimson_stem")); + + /** + * {@code minecraft:stripped_dark_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_DARK_OAK_LOG = create(key("stripped_dark_oak_log")); + + /** + * {@code minecraft:stripped_dark_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_DARK_OAK_WOOD = create(key("stripped_dark_oak_wood")); + + /** + * {@code minecraft:stripped_jungle_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_JUNGLE_LOG = create(key("stripped_jungle_log")); + + /** + * {@code minecraft:stripped_jungle_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_JUNGLE_WOOD = create(key("stripped_jungle_wood")); + + /** + * {@code minecraft:stripped_mangrove_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_MANGROVE_LOG = create(key("stripped_mangrove_log")); + + /** + * {@code minecraft:stripped_mangrove_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_MANGROVE_WOOD = create(key("stripped_mangrove_wood")); + + /** + * {@code minecraft:stripped_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_OAK_LOG = create(key("stripped_oak_log")); + + /** + * {@code minecraft:stripped_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_OAK_WOOD = create(key("stripped_oak_wood")); + + /** + * {@code minecraft:stripped_pale_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_PALE_OAK_LOG = create(key("stripped_pale_oak_log")); + + /** + * {@code minecraft:stripped_pale_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_PALE_OAK_WOOD = create(key("stripped_pale_oak_wood")); + + /** + * {@code minecraft:stripped_spruce_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_SPRUCE_LOG = create(key("stripped_spruce_log")); + + /** + * {@code minecraft:stripped_spruce_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_SPRUCE_WOOD = create(key("stripped_spruce_wood")); + + /** + * {@code minecraft:stripped_warped_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_WARPED_HYPHAE = create(key("stripped_warped_hyphae")); + + /** + * {@code minecraft:stripped_warped_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_WARPED_STEM = create(key("stripped_warped_stem")); + + /** + * {@code minecraft:structure_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRUCTURE_BLOCK = create(key("structure_block")); + + /** + * {@code minecraft:structure_void} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRUCTURE_VOID = create(key("structure_void")); + + /** + * {@code minecraft:sugar_cane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUGAR_CANE = create(key("sugar_cane")); + + /** + * {@code minecraft:sunflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNFLOWER = create(key("sunflower")); + + /** + * {@code minecraft:suspicious_gravel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUSPICIOUS_GRAVEL = create(key("suspicious_gravel")); + + /** + * {@code minecraft:suspicious_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUSPICIOUS_SAND = create(key("suspicious_sand")); + + /** + * {@code minecraft:sweet_berry_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEET_BERRY_BUSH = create(key("sweet_berry_bush")); + + /** + * {@code minecraft:tall_grass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TALL_GRASS = create(key("tall_grass")); + + /** + * {@code minecraft:tall_seagrass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TALL_SEAGRASS = create(key("tall_seagrass")); + + /** + * {@code minecraft:target} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TARGET = create(key("target")); + + /** + * {@code minecraft:terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TERRACOTTA = create(key("terracotta")); + + /** + * {@code minecraft:tinted_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TINTED_GLASS = create(key("tinted_glass")); + + /** + * {@code minecraft:tnt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TNT = create(key("tnt")); + + /** + * {@code minecraft:torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCH = create(key("torch")); + + /** + * {@code minecraft:torchflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCHFLOWER = create(key("torchflower")); + + /** + * {@code minecraft:torchflower_crop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCHFLOWER_CROP = create(key("torchflower_crop")); + + /** + * {@code minecraft:trapped_chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRAPPED_CHEST = create(key("trapped_chest")); + + /** + * {@code minecraft:trial_spawner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_SPAWNER = create(key("trial_spawner")); + + /** + * {@code minecraft:tripwire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIPWIRE = create(key("tripwire")); + + /** + * {@code minecraft:tripwire_hook} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIPWIRE_HOOK = create(key("tripwire_hook")); + + /** + * {@code minecraft:tube_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL = create(key("tube_coral")); + + /** + * {@code minecraft:tube_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL_BLOCK = create(key("tube_coral_block")); + + /** + * {@code minecraft:tube_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL_FAN = create(key("tube_coral_fan")); + + /** + * {@code minecraft:tube_coral_wall_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL_WALL_FAN = create(key("tube_coral_wall_fan")); + + /** + * {@code minecraft:tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF = create(key("tuff")); + + /** + * {@code minecraft:tuff_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_SLAB = create(key("tuff_brick_slab")); + + /** + * {@code minecraft:tuff_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_STAIRS = create(key("tuff_brick_stairs")); + + /** + * {@code minecraft:tuff_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_WALL = create(key("tuff_brick_wall")); + + /** + * {@code minecraft:tuff_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICKS = create(key("tuff_bricks")); + + /** + * {@code minecraft:tuff_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_SLAB = create(key("tuff_slab")); + + /** + * {@code minecraft:tuff_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_STAIRS = create(key("tuff_stairs")); + + /** + * {@code minecraft:tuff_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_WALL = create(key("tuff_wall")); + + /** + * {@code minecraft:turtle_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TURTLE_EGG = create(key("turtle_egg")); + + /** + * {@code minecraft:twisting_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TWISTING_VINES = create(key("twisting_vines")); + + /** + * {@code minecraft:twisting_vines_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TWISTING_VINES_PLANT = create(key("twisting_vines_plant")); + + /** + * {@code minecraft:vault} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VAULT = create(key("vault")); + + /** + * {@code minecraft:verdant_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VERDANT_FROGLIGHT = create(key("verdant_froglight")); + + /** + * {@code minecraft:vine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VINE = create(key("vine")); + + /** + * {@code minecraft:void_air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VOID_AIR = create(key("void_air")); + + /** + * {@code minecraft:wall_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WALL_TORCH = create(key("wall_torch")); + + /** + * {@code minecraft:warped_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_BUTTON = create(key("warped_button")); + + /** + * {@code minecraft:warped_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_DOOR = create(key("warped_door")); + + /** + * {@code minecraft:warped_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FENCE = create(key("warped_fence")); + + /** + * {@code minecraft:warped_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FENCE_GATE = create(key("warped_fence_gate")); + + /** + * {@code minecraft:warped_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FUNGUS = create(key("warped_fungus")); + + /** + * {@code minecraft:warped_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_HANGING_SIGN = create(key("warped_hanging_sign")); + + /** + * {@code minecraft:warped_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_HYPHAE = create(key("warped_hyphae")); + + /** + * {@code minecraft:warped_nylium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_NYLIUM = create(key("warped_nylium")); + + /** + * {@code minecraft:warped_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_PLANKS = create(key("warped_planks")); + + /** + * {@code minecraft:warped_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_PRESSURE_PLATE = create(key("warped_pressure_plate")); + + /** + * {@code minecraft:warped_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_ROOTS = create(key("warped_roots")); + + /** + * {@code minecraft:warped_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_SIGN = create(key("warped_sign")); + + /** + * {@code minecraft:warped_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_SLAB = create(key("warped_slab")); + + /** + * {@code minecraft:warped_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_STAIRS = create(key("warped_stairs")); + + /** + * {@code minecraft:warped_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_STEM = create(key("warped_stem")); + + /** + * {@code minecraft:warped_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_TRAPDOOR = create(key("warped_trapdoor")); + + /** + * {@code minecraft:warped_wall_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_WALL_HANGING_SIGN = create(key("warped_wall_hanging_sign")); + + /** + * {@code minecraft:warped_wall_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_WALL_SIGN = create(key("warped_wall_sign")); + + /** + * {@code minecraft:warped_wart_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_WART_BLOCK = create(key("warped_wart_block")); + + /** + * {@code minecraft:water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER = create(key("water")); + + /** + * {@code minecraft:water_cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER_CAULDRON = create(key("water_cauldron")); + + /** + * {@code minecraft:waxed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CHISELED_COPPER = create(key("waxed_chiseled_copper")); + + /** + * {@code minecraft:waxed_copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_BLOCK = create(key("waxed_copper_block")); + + /** + * {@code minecraft:waxed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_BULB = create(key("waxed_copper_bulb")); + + /** + * {@code minecraft:waxed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_DOOR = create(key("waxed_copper_door")); + + /** + * {@code minecraft:waxed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_GRATE = create(key("waxed_copper_grate")); + + /** + * {@code minecraft:waxed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_TRAPDOOR = create(key("waxed_copper_trapdoor")); + + /** + * {@code minecraft:waxed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER = create(key("waxed_cut_copper")); + + /** + * {@code minecraft:waxed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER_SLAB = create(key("waxed_cut_copper_slab")); + + /** + * {@code minecraft:waxed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER_STAIRS = create(key("waxed_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_exposed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CHISELED_COPPER = create(key("waxed_exposed_chiseled_copper")); + + /** + * {@code minecraft:waxed_exposed_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER = create(key("waxed_exposed_copper")); + + /** + * {@code minecraft:waxed_exposed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_BULB = create(key("waxed_exposed_copper_bulb")); + + /** + * {@code minecraft:waxed_exposed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_DOOR = create(key("waxed_exposed_copper_door")); + + /** + * {@code minecraft:waxed_exposed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_GRATE = create(key("waxed_exposed_copper_grate")); + + /** + * {@code minecraft:waxed_exposed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_TRAPDOOR = create(key("waxed_exposed_copper_trapdoor")); + + /** + * {@code minecraft:waxed_exposed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER = create(key("waxed_exposed_cut_copper")); + + /** + * {@code minecraft:waxed_exposed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER_SLAB = create(key("waxed_exposed_cut_copper_slab")); + + /** + * {@code minecraft:waxed_exposed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER_STAIRS = create(key("waxed_exposed_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_oxidized_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CHISELED_COPPER = create(key("waxed_oxidized_chiseled_copper")); + + /** + * {@code minecraft:waxed_oxidized_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER = create(key("waxed_oxidized_copper")); + + /** + * {@code minecraft:waxed_oxidized_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_BULB = create(key("waxed_oxidized_copper_bulb")); + + /** + * {@code minecraft:waxed_oxidized_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_DOOR = create(key("waxed_oxidized_copper_door")); + + /** + * {@code minecraft:waxed_oxidized_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_GRATE = create(key("waxed_oxidized_copper_grate")); + + /** + * {@code minecraft:waxed_oxidized_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_TRAPDOOR = create(key("waxed_oxidized_copper_trapdoor")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER = create(key("waxed_oxidized_cut_copper")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER_SLAB = create(key("waxed_oxidized_cut_copper_slab")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER_STAIRS = create(key("waxed_oxidized_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_weathered_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CHISELED_COPPER = create(key("waxed_weathered_chiseled_copper")); + + /** + * {@code minecraft:waxed_weathered_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER = create(key("waxed_weathered_copper")); + + /** + * {@code minecraft:waxed_weathered_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_BULB = create(key("waxed_weathered_copper_bulb")); + + /** + * {@code minecraft:waxed_weathered_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_DOOR = create(key("waxed_weathered_copper_door")); + + /** + * {@code minecraft:waxed_weathered_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_GRATE = create(key("waxed_weathered_copper_grate")); + + /** + * {@code minecraft:waxed_weathered_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_TRAPDOOR = create(key("waxed_weathered_copper_trapdoor")); + + /** + * {@code minecraft:waxed_weathered_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER = create(key("waxed_weathered_cut_copper")); + + /** + * {@code minecraft:waxed_weathered_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER_SLAB = create(key("waxed_weathered_cut_copper_slab")); + + /** + * {@code minecraft:waxed_weathered_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER_STAIRS = create(key("waxed_weathered_cut_copper_stairs")); + + /** + * {@code minecraft:weathered_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CHISELED_COPPER = create(key("weathered_chiseled_copper")); + + /** + * {@code minecraft:weathered_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER = create(key("weathered_copper")); + + /** + * {@code minecraft:weathered_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_BULB = create(key("weathered_copper_bulb")); + + /** + * {@code minecraft:weathered_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_DOOR = create(key("weathered_copper_door")); + + /** + * {@code minecraft:weathered_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_GRATE = create(key("weathered_copper_grate")); + + /** + * {@code minecraft:weathered_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_TRAPDOOR = create(key("weathered_copper_trapdoor")); + + /** + * {@code minecraft:weathered_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER = create(key("weathered_cut_copper")); + + /** + * {@code minecraft:weathered_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER_SLAB = create(key("weathered_cut_copper_slab")); + + /** + * {@code minecraft:weathered_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER_STAIRS = create(key("weathered_cut_copper_stairs")); + + /** + * {@code minecraft:weeping_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEEPING_VINES = create(key("weeping_vines")); + + /** + * {@code minecraft:weeping_vines_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEEPING_VINES_PLANT = create(key("weeping_vines_plant")); + + /** + * {@code minecraft:wet_sponge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WET_SPONGE = create(key("wet_sponge")); + + /** + * {@code minecraft:wheat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHEAT = create(key("wheat")); + + /** + * {@code minecraft:white_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_BANNER = create(key("white_banner")); + + /** + * {@code minecraft:white_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_BED = create(key("white_bed")); + + /** + * {@code minecraft:white_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CANDLE = create(key("white_candle")); + + /** + * {@code minecraft:white_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CANDLE_CAKE = create(key("white_candle_cake")); + + /** + * {@code minecraft:white_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CARPET = create(key("white_carpet")); + + /** + * {@code minecraft:white_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CONCRETE = create(key("white_concrete")); + + /** + * {@code minecraft:white_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CONCRETE_POWDER = create(key("white_concrete_powder")); + + /** + * {@code minecraft:white_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_GLAZED_TERRACOTTA = create(key("white_glazed_terracotta")); + + /** + * {@code minecraft:white_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_SHULKER_BOX = create(key("white_shulker_box")); + + /** + * {@code minecraft:white_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_STAINED_GLASS = create(key("white_stained_glass")); + + /** + * {@code minecraft:white_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_STAINED_GLASS_PANE = create(key("white_stained_glass_pane")); + + /** + * {@code minecraft:white_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_TERRACOTTA = create(key("white_terracotta")); + + /** + * {@code minecraft:white_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_TULIP = create(key("white_tulip")); + + /** + * {@code minecraft:white_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_WALL_BANNER = create(key("white_wall_banner")); + + /** + * {@code minecraft:white_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_WOOL = create(key("white_wool")); + + /** + * {@code minecraft:wither_rose} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_ROSE = create(key("wither_rose")); + + /** + * {@code minecraft:wither_skeleton_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKELETON_SKULL = create(key("wither_skeleton_skull")); + + /** + * {@code minecraft:wither_skeleton_wall_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKELETON_WALL_SKULL = create(key("wither_skeleton_wall_skull")); + + /** + * {@code minecraft:yellow_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_BANNER = create(key("yellow_banner")); + + /** + * {@code minecraft:yellow_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_BED = create(key("yellow_bed")); + + /** + * {@code minecraft:yellow_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CANDLE = create(key("yellow_candle")); + + /** + * {@code minecraft:yellow_candle_cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CANDLE_CAKE = create(key("yellow_candle_cake")); + + /** + * {@code minecraft:yellow_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CARPET = create(key("yellow_carpet")); + + /** + * {@code minecraft:yellow_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CONCRETE = create(key("yellow_concrete")); + + /** + * {@code minecraft:yellow_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CONCRETE_POWDER = create(key("yellow_concrete_powder")); + + /** + * {@code minecraft:yellow_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_GLAZED_TERRACOTTA = create(key("yellow_glazed_terracotta")); + + /** + * {@code minecraft:yellow_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_SHULKER_BOX = create(key("yellow_shulker_box")); + + /** + * {@code minecraft:yellow_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_STAINED_GLASS = create(key("yellow_stained_glass")); + + /** + * {@code minecraft:yellow_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_STAINED_GLASS_PANE = create(key("yellow_stained_glass_pane")); + + /** + * {@code minecraft:yellow_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_TERRACOTTA = create(key("yellow_terracotta")); + + /** + * {@code minecraft:yellow_wall_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_WALL_BANNER = create(key("yellow_wall_banner")); + + /** + * {@code minecraft:yellow_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_WOOL = create(key("yellow_wool")); + + /** + * {@code minecraft:zombie_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_HEAD = create(key("zombie_head")); + + /** + * {@code minecraft:zombie_wall_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_WALL_HEAD = create(key("zombie_wall_head")); + + private BlockTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.BLOCK, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/CatVariantKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/CatVariantKeys.java new file mode 100644 index 000000000000..cb3ee5d280fe --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/CatVariantKeys.java @@ -0,0 +1,113 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Cat; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#CAT_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class CatVariantKeys { + /** + * {@code minecraft:all_black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ALL_BLACK = create(key("all_black")); + + /** + * {@code minecraft:black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK = create(key("black")); + + /** + * {@code minecraft:british_shorthair} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRITISH_SHORTHAIR = create(key("british_shorthair")); + + /** + * {@code minecraft:calico} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALICO = create(key("calico")); + + /** + * {@code minecraft:jellie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JELLIE = create(key("jellie")); + + /** + * {@code minecraft:persian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PERSIAN = create(key("persian")); + + /** + * {@code minecraft:ragdoll} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAGDOLL = create(key("ragdoll")); + + /** + * {@code minecraft:red} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED = create(key("red")); + + /** + * {@code minecraft:siamese} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SIAMESE = create(key("siamese")); + + /** + * {@code minecraft:tabby} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TABBY = create(key("tabby")); + + /** + * {@code minecraft:white} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE = create(key("white")); + + private CatVariantKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.CAT_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java new file mode 100644 index 000000000000..37476f7b8c4e --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java @@ -0,0 +1,386 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.damage.DamageType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#DAMAGE_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class DamageTypeKeys { + /** + * {@code minecraft:arrow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARROW = create(key("arrow")); + + /** + * {@code minecraft:bad_respawn_point} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAD_RESPAWN_POINT = create(key("bad_respawn_point")); + + /** + * {@code minecraft:cactus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CACTUS = create(key("cactus")); + + /** + * {@code minecraft:campfire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAMPFIRE = create(key("campfire")); + + /** + * {@code minecraft:cramming} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAMMING = create(key("cramming")); + + /** + * {@code minecraft:dragon_breath} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_BREATH = create(key("dragon_breath")); + + /** + * {@code minecraft:drown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DROWN = create(key("drown")); + + /** + * {@code minecraft:dry_out} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRY_OUT = create(key("dry_out")); + + /** + * {@code minecraft:ender_pearl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_PEARL = create(key("ender_pearl")); + + /** + * {@code minecraft:explosion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLOSION = create(key("explosion")); + + /** + * {@code minecraft:fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALL = create(key("fall")); + + /** + * {@code minecraft:falling_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_ANVIL = create(key("falling_anvil")); + + /** + * {@code minecraft:falling_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_BLOCK = create(key("falling_block")); + + /** + * {@code minecraft:falling_stalactite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_STALACTITE = create(key("falling_stalactite")); + + /** + * {@code minecraft:fireball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREBALL = create(key("fireball")); + + /** + * {@code minecraft:fireworks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREWORKS = create(key("fireworks")); + + /** + * {@code minecraft:fly_into_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLY_INTO_WALL = create(key("fly_into_wall")); + + /** + * {@code minecraft:freeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FREEZE = create(key("freeze")); + + /** + * {@code minecraft:generic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC = create(key("generic")); + + /** + * {@code minecraft:generic_kill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_KILL = create(key("generic_kill")); + + /** + * {@code minecraft:hot_floor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOT_FLOOR = create(key("hot_floor")); + + /** + * {@code minecraft:in_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IN_FIRE = create(key("in_fire")); + + /** + * {@code minecraft:in_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IN_WALL = create(key("in_wall")); + + /** + * {@code minecraft:indirect_magic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INDIRECT_MAGIC = create(key("indirect_magic")); + + /** + * {@code minecraft:lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA = create(key("lava")); + + /** + * {@code minecraft:lightning_bolt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_BOLT = create(key("lightning_bolt")); + + /** + * {@code minecraft:mace_smash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MACE_SMASH = create(key("mace_smash")); + + /** + * {@code minecraft:magic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGIC = create(key("magic")); + + /** + * {@code minecraft:mob_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_ATTACK = create(key("mob_attack")); + + /** + * {@code minecraft:mob_attack_no_aggro} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_ATTACK_NO_AGGRO = create(key("mob_attack_no_aggro")); + + /** + * {@code minecraft:mob_projectile} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_PROJECTILE = create(key("mob_projectile")); + + /** + * {@code minecraft:on_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ON_FIRE = create(key("on_fire")); + + /** + * {@code minecraft:out_of_world} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OUT_OF_WORLD = create(key("out_of_world")); + + /** + * {@code minecraft:outside_border} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OUTSIDE_BORDER = create(key("outside_border")); + + /** + * {@code minecraft:player_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_ATTACK = create(key("player_attack")); + + /** + * {@code minecraft:player_explosion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_EXPLOSION = create(key("player_explosion")); + + /** + * {@code minecraft:sonic_boom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SONIC_BOOM = create(key("sonic_boom")); + + /** + * {@code minecraft:spit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIT = create(key("spit")); + + /** + * {@code minecraft:stalagmite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STALAGMITE = create(key("stalagmite")); + + /** + * {@code minecraft:starve} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STARVE = create(key("starve")); + + /** + * {@code minecraft:sting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STING = create(key("sting")); + + /** + * {@code minecraft:sweet_berry_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEET_BERRY_BUSH = create(key("sweet_berry_bush")); + + /** + * {@code minecraft:thorns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THORNS = create(key("thorns")); + + /** + * {@code minecraft:thrown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THROWN = create(key("thrown")); + + /** + * {@code minecraft:trident} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIDENT = create(key("trident")); + + /** + * {@code minecraft:unattributed_fireball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNATTRIBUTED_FIREBALL = create(key("unattributed_fireball")); + + /** + * {@code minecraft:wind_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WIND_CHARGE = create(key("wind_charge")); + + /** + * {@code minecraft:wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER = create(key("wither")); + + /** + * {@code minecraft:wither_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKULL = create(key("wither_skull")); + + private DamageTypeKeys() { + } + + /** + * Creates a key for {@link DamageType} in the registry {@code minecraft:damage_type}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.DAMAGE_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java new file mode 100644 index 000000000000..33743dd4fb35 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java @@ -0,0 +1,337 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.enchantments.Enchantment; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#ENCHANTMENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class EnchantmentKeys { + /** + * {@code minecraft:aqua_affinity} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AQUA_AFFINITY = create(key("aqua_affinity")); + + /** + * {@code minecraft:bane_of_arthropods} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANE_OF_ARTHROPODS = create(key("bane_of_arthropods")); + + /** + * {@code minecraft:binding_curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BINDING_CURSE = create(key("binding_curse")); + + /** + * {@code minecraft:blast_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAST_PROTECTION = create(key("blast_protection")); + + /** + * {@code minecraft:breach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREACH = create(key("breach")); + + /** + * {@code minecraft:channeling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHANNELING = create(key("channeling")); + + /** + * {@code minecraft:density} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DENSITY = create(key("density")); + + /** + * {@code minecraft:depth_strider} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEPTH_STRIDER = create(key("depth_strider")); + + /** + * {@code minecraft:efficiency} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EFFICIENCY = create(key("efficiency")); + + /** + * {@code minecraft:feather_falling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FEATHER_FALLING = create(key("feather_falling")); + + /** + * {@code minecraft:fire_aspect} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_ASPECT = create(key("fire_aspect")); + + /** + * {@code minecraft:fire_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_PROTECTION = create(key("fire_protection")); + + /** + * {@code minecraft:flame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLAME = create(key("flame")); + + /** + * {@code minecraft:fortune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FORTUNE = create(key("fortune")); + + /** + * {@code minecraft:frost_walker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROST_WALKER = create(key("frost_walker")); + + /** + * {@code minecraft:impaling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IMPALING = create(key("impaling")); + + /** + * {@code minecraft:infinity} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFINITY = create(key("infinity")); + + /** + * {@code minecraft:knockback} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KNOCKBACK = create(key("knockback")); + + /** + * {@code minecraft:looting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOOTING = create(key("looting")); + + /** + * {@code minecraft:loyalty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOYALTY = create(key("loyalty")); + + /** + * {@code minecraft:luck_of_the_sea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUCK_OF_THE_SEA = create(key("luck_of_the_sea")); + + /** + * {@code minecraft:lure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LURE = create(key("lure")); + + /** + * {@code minecraft:mending} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MENDING = create(key("mending")); + + /** + * {@code minecraft:multishot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MULTISHOT = create(key("multishot")); + + /** + * {@code minecraft:piercing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIERCING = create(key("piercing")); + + /** + * {@code minecraft:power} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWER = create(key("power")); + + /** + * {@code minecraft:projectile_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_PROTECTION = create(key("projectile_protection")); + + /** + * {@code minecraft:protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROTECTION = create(key("protection")); + + /** + * {@code minecraft:punch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUNCH = create(key("punch")); + + /** + * {@code minecraft:quick_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUICK_CHARGE = create(key("quick_charge")); + + /** + * {@code minecraft:respiration} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESPIRATION = create(key("respiration")); + + /** + * {@code minecraft:riptide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIPTIDE = create(key("riptide")); + + /** + * {@code minecraft:sharpness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHARPNESS = create(key("sharpness")); + + /** + * {@code minecraft:silk_touch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILK_TOUCH = create(key("silk_touch")); + + /** + * {@code minecraft:smite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMITE = create(key("smite")); + + /** + * {@code minecraft:soul_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SPEED = create(key("soul_speed")); + + /** + * {@code minecraft:sweeping_edge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEEPING_EDGE = create(key("sweeping_edge")); + + /** + * {@code minecraft:swift_sneak} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWIFT_SNEAK = create(key("swift_sneak")); + + /** + * {@code minecraft:thorns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THORNS = create(key("thorns")); + + /** + * {@code minecraft:unbreaking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNBREAKING = create(key("unbreaking")); + + /** + * {@code minecraft:vanishing_curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VANISHING_CURSE = create(key("vanishing_curse")); + + /** + * {@code minecraft:wind_burst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WIND_BURST = create(key("wind_burst")); + + private EnchantmentKeys() { + } + + /** + * Creates a key for {@link Enchantment} in the registry {@code minecraft:enchantment}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.ENCHANTMENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/FluidKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/FluidKeys.java new file mode 100644 index 000000000000..53b32d9897dc --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/FluidKeys.java @@ -0,0 +1,71 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.Fluid; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#FLUID}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class FluidKeys { + /** + * {@code minecraft:empty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMPTY = create(key("empty")); + + /** + * {@code minecraft:flowing_lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWING_LAVA = create(key("flowing_lava")); + + /** + * {@code minecraft:flowing_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWING_WATER = create(key("flowing_water")); + + /** + * {@code minecraft:lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA = create(key("lava")); + + /** + * {@code minecraft:water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER = create(key("water")); + + private FluidKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.FLUID, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/FrogVariantKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/FrogVariantKeys.java new file mode 100644 index 000000000000..0a07c027823c --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/FrogVariantKeys.java @@ -0,0 +1,57 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Frog; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#FROG_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class FrogVariantKeys { + /** + * {@code minecraft:cold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COLD = create(key("cold")); + + /** + * {@code minecraft:temperate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TEMPERATE = create(key("temperate")); + + /** + * {@code minecraft:warm} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARM = create(key("warm")); + + private FrogVariantKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.FROG_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java new file mode 100644 index 000000000000..954f46e8d84e --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java @@ -0,0 +1,463 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.GameEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#GAME_EVENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class GameEventKeys { + /** + * {@code minecraft:block_activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ACTIVATE = create(key("block_activate")); + + /** + * {@code minecraft:block_attach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ATTACH = create(key("block_attach")); + + /** + * {@code minecraft:block_change} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHANGE = create(key("block_change")); + + /** + * {@code minecraft:block_close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CLOSE = create(key("block_close")); + + /** + * {@code minecraft:block_deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEACTIVATE = create(key("block_deactivate")); + + /** + * {@code minecraft:block_destroy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DESTROY = create(key("block_destroy")); + + /** + * {@code minecraft:block_detach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DETACH = create(key("block_detach")); + + /** + * {@code minecraft:block_open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_OPEN = create(key("block_open")); + + /** + * {@code minecraft:block_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PLACE = create(key("block_place")); + + /** + * {@code minecraft:container_close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONTAINER_CLOSE = create(key("container_close")); + + /** + * {@code minecraft:container_open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONTAINER_OPEN = create(key("container_open")); + + /** + * {@code minecraft:drink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRINK = create(key("drink")); + + /** + * {@code minecraft:eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EAT = create(key("eat")); + + /** + * {@code minecraft:elytra_glide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ELYTRA_GLIDE = create(key("elytra_glide")); + + /** + * {@code minecraft:entity_action} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ACTION = create(key("entity_action")); + + /** + * {@code minecraft:entity_damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DAMAGE = create(key("entity_damage")); + + /** + * {@code minecraft:entity_die} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DIE = create(key("entity_die")); + + /** + * {@code minecraft:entity_dismount} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DISMOUNT = create(key("entity_dismount")); + + /** + * {@code minecraft:entity_interact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_INTERACT = create(key("entity_interact")); + + /** + * {@code minecraft:entity_mount} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOUNT = create(key("entity_mount")); + + /** + * {@code minecraft:entity_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLACE = create(key("entity_place")); + + /** + * {@code minecraft:equip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EQUIP = create(key("equip")); + + /** + * {@code minecraft:explode} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLODE = create(key("explode")); + + /** + * {@code minecraft:flap} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLAP = create(key("flap")); + + /** + * {@code minecraft:fluid_pickup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLUID_PICKUP = create(key("fluid_pickup")); + + /** + * {@code minecraft:fluid_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLUID_PLACE = create(key("fluid_place")); + + /** + * {@code minecraft:hit_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HIT_GROUND = create(key("hit_ground")); + + /** + * {@code minecraft:instrument_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTRUMENT_PLAY = create(key("instrument_play")); + + /** + * {@code minecraft:item_interact_finish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_INTERACT_FINISH = create(key("item_interact_finish")); + + /** + * {@code minecraft:item_interact_start} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_INTERACT_START = create(key("item_interact_start")); + + /** + * {@code minecraft:jukebox_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX_PLAY = create(key("jukebox_play")); + + /** + * {@code minecraft:jukebox_stop_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX_STOP_PLAY = create(key("jukebox_stop_play")); + + /** + * {@code minecraft:lightning_strike} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_STRIKE = create(key("lightning_strike")); + + /** + * {@code minecraft:note_block_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NOTE_BLOCK_PLAY = create(key("note_block_play")); + + /** + * {@code minecraft:prime_fuse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRIME_FUSE = create(key("prime_fuse")); + + /** + * {@code minecraft:projectile_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_LAND = create(key("projectile_land")); + + /** + * {@code minecraft:projectile_shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_SHOOT = create(key("projectile_shoot")); + + /** + * {@code minecraft:resonate_1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_1 = create(key("resonate_1")); + + /** + * {@code minecraft:resonate_2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_2 = create(key("resonate_2")); + + /** + * {@code minecraft:resonate_3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_3 = create(key("resonate_3")); + + /** + * {@code minecraft:resonate_4} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_4 = create(key("resonate_4")); + + /** + * {@code minecraft:resonate_5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_5 = create(key("resonate_5")); + + /** + * {@code minecraft:resonate_6} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_6 = create(key("resonate_6")); + + /** + * {@code minecraft:resonate_7} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_7 = create(key("resonate_7")); + + /** + * {@code minecraft:resonate_8} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_8 = create(key("resonate_8")); + + /** + * {@code minecraft:resonate_9} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_9 = create(key("resonate_9")); + + /** + * {@code minecraft:resonate_10} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_10 = create(key("resonate_10")); + + /** + * {@code minecraft:resonate_11} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_11 = create(key("resonate_11")); + + /** + * {@code minecraft:resonate_12} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_12 = create(key("resonate_12")); + + /** + * {@code minecraft:resonate_13} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_13 = create(key("resonate_13")); + + /** + * {@code minecraft:resonate_14} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_14 = create(key("resonate_14")); + + /** + * {@code minecraft:resonate_15} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_15 = create(key("resonate_15")); + + /** + * {@code minecraft:sculk_sensor_tendrils_clicking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SENSOR_TENDRILS_CLICKING = create(key("sculk_sensor_tendrils_clicking")); + + /** + * {@code minecraft:shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEAR = create(key("shear")); + + /** + * {@code minecraft:shriek} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHRIEK = create(key("shriek")); + + /** + * {@code minecraft:splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPLASH = create(key("splash")); + + /** + * {@code minecraft:step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STEP = create(key("step")); + + /** + * {@code minecraft:swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWIM = create(key("swim")); + + /** + * {@code minecraft:teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TELEPORT = create(key("teleport")); + + /** + * {@code minecraft:unequip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNEQUIP = create(key("unequip")); + + private GameEventKeys() { + } + + /** + * Creates a key for {@link GameEvent} in the registry {@code minecraft:game_event}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.GAME_EVENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/InstrumentKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/InstrumentKeys.java new file mode 100644 index 000000000000..4daa2fac52fa --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/InstrumentKeys.java @@ -0,0 +1,99 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.MusicInstrument; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#INSTRUMENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class InstrumentKeys { + /** + * {@code minecraft:admire_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ADMIRE_GOAT_HORN = create(key("admire_goat_horn")); + + /** + * {@code minecraft:call_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALL_GOAT_HORN = create(key("call_goat_horn")); + + /** + * {@code minecraft:dream_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DREAM_GOAT_HORN = create(key("dream_goat_horn")); + + /** + * {@code minecraft:feel_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FEEL_GOAT_HORN = create(key("feel_goat_horn")); + + /** + * {@code minecraft:ponder_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PONDER_GOAT_HORN = create(key("ponder_goat_horn")); + + /** + * {@code minecraft:seek_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEEK_GOAT_HORN = create(key("seek_goat_horn")); + + /** + * {@code minecraft:sing_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SING_GOAT_HORN = create(key("sing_goat_horn")); + + /** + * {@code minecraft:yearn_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YEARN_GOAT_HORN = create(key("yearn_goat_horn")); + + private InstrumentKeys() { + } + + /** + * Creates a key for {@link MusicInstrument} in the registry {@code minecraft:instrument}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.INSTRUMENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/ItemTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/ItemTypeKeys.java new file mode 100644 index 000000000000..d13da7a453c1 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/ItemTypeKeys.java @@ -0,0 +1,9731 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.ItemType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#ITEM}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class ItemTypeKeys { + /** + * {@code minecraft:acacia_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_BOAT = create(key("acacia_boat")); + + /** + * {@code minecraft:acacia_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_BUTTON = create(key("acacia_button")); + + /** + * {@code minecraft:acacia_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_CHEST_BOAT = create(key("acacia_chest_boat")); + + /** + * {@code minecraft:acacia_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_DOOR = create(key("acacia_door")); + + /** + * {@code minecraft:acacia_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_FENCE = create(key("acacia_fence")); + + /** + * {@code minecraft:acacia_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_FENCE_GATE = create(key("acacia_fence_gate")); + + /** + * {@code minecraft:acacia_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_HANGING_SIGN = create(key("acacia_hanging_sign")); + + /** + * {@code minecraft:acacia_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_LEAVES = create(key("acacia_leaves")); + + /** + * {@code minecraft:acacia_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_LOG = create(key("acacia_log")); + + /** + * {@code minecraft:acacia_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_PLANKS = create(key("acacia_planks")); + + /** + * {@code minecraft:acacia_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_PRESSURE_PLATE = create(key("acacia_pressure_plate")); + + /** + * {@code minecraft:acacia_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SAPLING = create(key("acacia_sapling")); + + /** + * {@code minecraft:acacia_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SIGN = create(key("acacia_sign")); + + /** + * {@code minecraft:acacia_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_SLAB = create(key("acacia_slab")); + + /** + * {@code minecraft:acacia_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_STAIRS = create(key("acacia_stairs")); + + /** + * {@code minecraft:acacia_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_TRAPDOOR = create(key("acacia_trapdoor")); + + /** + * {@code minecraft:acacia_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACACIA_WOOD = create(key("acacia_wood")); + + /** + * {@code minecraft:activator_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ACTIVATOR_RAIL = create(key("activator_rail")); + + /** + * {@code minecraft:air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AIR = create(key("air")); + + /** + * {@code minecraft:allay_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ALLAY_SPAWN_EGG = create(key("allay_spawn_egg")); + + /** + * {@code minecraft:allium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ALLIUM = create(key("allium")); + + /** + * {@code minecraft:amethyst_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST_BLOCK = create(key("amethyst_block")); + + /** + * {@code minecraft:amethyst_cluster} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST_CLUSTER = create(key("amethyst_cluster")); + + /** + * {@code minecraft:amethyst_shard} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST_SHARD = create(key("amethyst_shard")); + + /** + * {@code minecraft:ancient_debris} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANCIENT_DEBRIS = create(key("ancient_debris")); + + /** + * {@code minecraft:andesite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE = create(key("andesite")); + + /** + * {@code minecraft:andesite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_SLAB = create(key("andesite_slab")); + + /** + * {@code minecraft:andesite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_STAIRS = create(key("andesite_stairs")); + + /** + * {@code minecraft:andesite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANDESITE_WALL = create(key("andesite_wall")); + + /** + * {@code minecraft:angler_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANGLER_POTTERY_SHERD = create(key("angler_pottery_sherd")); + + /** + * {@code minecraft:anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANVIL = create(key("anvil")); + + /** + * {@code minecraft:apple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey APPLE = create(key("apple")); + + /** + * {@code minecraft:archer_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARCHER_POTTERY_SHERD = create(key("archer_pottery_sherd")); + + /** + * {@code minecraft:armadillo_scute} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMADILLO_SCUTE = create(key("armadillo_scute")); + + /** + * {@code minecraft:armadillo_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMADILLO_SPAWN_EGG = create(key("armadillo_spawn_egg")); + + /** + * {@code minecraft:armor_stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMOR_STAND = create(key("armor_stand")); + + /** + * {@code minecraft:arms_up_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMS_UP_POTTERY_SHERD = create(key("arms_up_pottery_sherd")); + + /** + * {@code minecraft:arrow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARROW = create(key("arrow")); + + /** + * {@code minecraft:axolotl_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AXOLOTL_BUCKET = create(key("axolotl_bucket")); + + /** + * {@code minecraft:axolotl_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AXOLOTL_SPAWN_EGG = create(key("axolotl_spawn_egg")); + + /** + * {@code minecraft:azalea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZALEA = create(key("azalea")); + + /** + * {@code minecraft:azalea_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZALEA_LEAVES = create(key("azalea_leaves")); + + /** + * {@code minecraft:azure_bluet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZURE_BLUET = create(key("azure_bluet")); + + /** + * {@code minecraft:baked_potato} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAKED_POTATO = create(key("baked_potato")); + + /** + * {@code minecraft:bamboo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO = create(key("bamboo")); + + /** + * {@code minecraft:bamboo_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_BLOCK = create(key("bamboo_block")); + + /** + * {@code minecraft:bamboo_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_BUTTON = create(key("bamboo_button")); + + /** + * {@code minecraft:bamboo_chest_raft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_CHEST_RAFT = create(key("bamboo_chest_raft")); + + /** + * {@code minecraft:bamboo_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_DOOR = create(key("bamboo_door")); + + /** + * {@code minecraft:bamboo_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_FENCE = create(key("bamboo_fence")); + + /** + * {@code minecraft:bamboo_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_FENCE_GATE = create(key("bamboo_fence_gate")); + + /** + * {@code minecraft:bamboo_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_HANGING_SIGN = create(key("bamboo_hanging_sign")); + + /** + * {@code minecraft:bamboo_mosaic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC = create(key("bamboo_mosaic")); + + /** + * {@code minecraft:bamboo_mosaic_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC_SLAB = create(key("bamboo_mosaic_slab")); + + /** + * {@code minecraft:bamboo_mosaic_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_MOSAIC_STAIRS = create(key("bamboo_mosaic_stairs")); + + /** + * {@code minecraft:bamboo_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_PLANKS = create(key("bamboo_planks")); + + /** + * {@code minecraft:bamboo_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_PRESSURE_PLATE = create(key("bamboo_pressure_plate")); + + /** + * {@code minecraft:bamboo_raft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_RAFT = create(key("bamboo_raft")); + + /** + * {@code minecraft:bamboo_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_SIGN = create(key("bamboo_sign")); + + /** + * {@code minecraft:bamboo_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_SLAB = create(key("bamboo_slab")); + + /** + * {@code minecraft:bamboo_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_STAIRS = create(key("bamboo_stairs")); + + /** + * {@code minecraft:bamboo_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_TRAPDOOR = create(key("bamboo_trapdoor")); + + /** + * {@code minecraft:barrel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BARREL = create(key("barrel")); + + /** + * {@code minecraft:barrier} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BARRIER = create(key("barrier")); + + /** + * {@code minecraft:basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASALT = create(key("basalt")); + + /** + * {@code minecraft:bat_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAT_SPAWN_EGG = create(key("bat_spawn_egg")); + + /** + * {@code minecraft:beacon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEACON = create(key("beacon")); + + /** + * {@code minecraft:bedrock} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEDROCK = create(key("bedrock")); + + /** + * {@code minecraft:bee_nest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEE_NEST = create(key("bee_nest")); + + /** + * {@code minecraft:bee_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEE_SPAWN_EGG = create(key("bee_spawn_egg")); + + /** + * {@code minecraft:beef} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEEF = create(key("beef")); + + /** + * {@code minecraft:beehive} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEEHIVE = create(key("beehive")); + + /** + * {@code minecraft:beetroot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEETROOT = create(key("beetroot")); + + /** + * {@code minecraft:beetroot_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEETROOT_SEEDS = create(key("beetroot_seeds")); + + /** + * {@code minecraft:beetroot_soup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEETROOT_SOUP = create(key("beetroot_soup")); + + /** + * {@code minecraft:bell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BELL = create(key("bell")); + + /** + * {@code minecraft:big_dripleaf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIG_DRIPLEAF = create(key("big_dripleaf")); + + /** + * {@code minecraft:birch_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_BOAT = create(key("birch_boat")); + + /** + * {@code minecraft:birch_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_BUTTON = create(key("birch_button")); + + /** + * {@code minecraft:birch_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_CHEST_BOAT = create(key("birch_chest_boat")); + + /** + * {@code minecraft:birch_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_DOOR = create(key("birch_door")); + + /** + * {@code minecraft:birch_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FENCE = create(key("birch_fence")); + + /** + * {@code minecraft:birch_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FENCE_GATE = create(key("birch_fence_gate")); + + /** + * {@code minecraft:birch_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_HANGING_SIGN = create(key("birch_hanging_sign")); + + /** + * {@code minecraft:birch_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_LEAVES = create(key("birch_leaves")); + + /** + * {@code minecraft:birch_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_LOG = create(key("birch_log")); + + /** + * {@code minecraft:birch_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_PLANKS = create(key("birch_planks")); + + /** + * {@code minecraft:birch_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_PRESSURE_PLATE = create(key("birch_pressure_plate")); + + /** + * {@code minecraft:birch_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SAPLING = create(key("birch_sapling")); + + /** + * {@code minecraft:birch_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SIGN = create(key("birch_sign")); + + /** + * {@code minecraft:birch_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_SLAB = create(key("birch_slab")); + + /** + * {@code minecraft:birch_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_STAIRS = create(key("birch_stairs")); + + /** + * {@code minecraft:birch_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_TRAPDOOR = create(key("birch_trapdoor")); + + /** + * {@code minecraft:birch_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_WOOD = create(key("birch_wood")); + + /** + * {@code minecraft:black_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_BANNER = create(key("black_banner")); + + /** + * {@code minecraft:black_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_BED = create(key("black_bed")); + + /** + * {@code minecraft:black_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_BUNDLE = create(key("black_bundle")); + + /** + * {@code minecraft:black_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CANDLE = create(key("black_candle")); + + /** + * {@code minecraft:black_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CARPET = create(key("black_carpet")); + + /** + * {@code minecraft:black_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CONCRETE = create(key("black_concrete")); + + /** + * {@code minecraft:black_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_CONCRETE_POWDER = create(key("black_concrete_powder")); + + /** + * {@code minecraft:black_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_DYE = create(key("black_dye")); + + /** + * {@code minecraft:black_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_GLAZED_TERRACOTTA = create(key("black_glazed_terracotta")); + + /** + * {@code minecraft:black_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_SHULKER_BOX = create(key("black_shulker_box")); + + /** + * {@code minecraft:black_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_STAINED_GLASS = create(key("black_stained_glass")); + + /** + * {@code minecraft:black_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_STAINED_GLASS_PANE = create(key("black_stained_glass_pane")); + + /** + * {@code minecraft:black_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_TERRACOTTA = create(key("black_terracotta")); + + /** + * {@code minecraft:black_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK_WOOL = create(key("black_wool")); + + /** + * {@code minecraft:blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE = create(key("blackstone")); + + /** + * {@code minecraft:blackstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_SLAB = create(key("blackstone_slab")); + + /** + * {@code minecraft:blackstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_STAIRS = create(key("blackstone_stairs")); + + /** + * {@code minecraft:blackstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACKSTONE_WALL = create(key("blackstone_wall")); + + /** + * {@code minecraft:blade_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLADE_POTTERY_SHERD = create(key("blade_pottery_sherd")); + + /** + * {@code minecraft:blast_furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAST_FURNACE = create(key("blast_furnace")); + + /** + * {@code minecraft:blaze_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAZE_POWDER = create(key("blaze_powder")); + + /** + * {@code minecraft:blaze_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAZE_ROD = create(key("blaze_rod")); + + /** + * {@code minecraft:blaze_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAZE_SPAWN_EGG = create(key("blaze_spawn_egg")); + + /** + * {@code minecraft:blue_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_BANNER = create(key("blue_banner")); + + /** + * {@code minecraft:blue_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_BED = create(key("blue_bed")); + + /** + * {@code minecraft:blue_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_BUNDLE = create(key("blue_bundle")); + + /** + * {@code minecraft:blue_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CANDLE = create(key("blue_candle")); + + /** + * {@code minecraft:blue_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CARPET = create(key("blue_carpet")); + + /** + * {@code minecraft:blue_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CONCRETE = create(key("blue_concrete")); + + /** + * {@code minecraft:blue_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_CONCRETE_POWDER = create(key("blue_concrete_powder")); + + /** + * {@code minecraft:blue_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_DYE = create(key("blue_dye")); + + /** + * {@code minecraft:blue_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_GLAZED_TERRACOTTA = create(key("blue_glazed_terracotta")); + + /** + * {@code minecraft:blue_ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_ICE = create(key("blue_ice")); + + /** + * {@code minecraft:blue_orchid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_ORCHID = create(key("blue_orchid")); + + /** + * {@code minecraft:blue_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_SHULKER_BOX = create(key("blue_shulker_box")); + + /** + * {@code minecraft:blue_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_STAINED_GLASS = create(key("blue_stained_glass")); + + /** + * {@code minecraft:blue_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_STAINED_GLASS_PANE = create(key("blue_stained_glass_pane")); + + /** + * {@code minecraft:blue_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_TERRACOTTA = create(key("blue_terracotta")); + + /** + * {@code minecraft:blue_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_WOOL = create(key("blue_wool")); + + /** + * {@code minecraft:bogged_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOGGED_SPAWN_EGG = create(key("bogged_spawn_egg")); + + /** + * {@code minecraft:bolt_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOLT_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("bolt_armor_trim_smithing_template")); + + /** + * {@code minecraft:bone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BONE = create(key("bone")); + + /** + * {@code minecraft:bone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BONE_BLOCK = create(key("bone_block")); + + /** + * {@code minecraft:bone_meal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BONE_MEAL = create(key("bone_meal")); + + /** + * {@code minecraft:book} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOOK = create(key("book")); + + /** + * {@code minecraft:bookshelf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOOKSHELF = create(key("bookshelf")); + + /** + * {@code minecraft:bordure_indented_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BORDURE_INDENTED_BANNER_PATTERN = create(key("bordure_indented_banner_pattern")); + + /** + * {@code minecraft:bow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOW = create(key("bow")); + + /** + * {@code minecraft:bowl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOWL = create(key("bowl")); + + /** + * {@code minecraft:brain_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL = create(key("brain_coral")); + + /** + * {@code minecraft:brain_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL_BLOCK = create(key("brain_coral_block")); + + /** + * {@code minecraft:brain_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRAIN_CORAL_FAN = create(key("brain_coral_fan")); + + /** + * {@code minecraft:bread} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREAD = create(key("bread")); + + /** + * {@code minecraft:breeze_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREEZE_ROD = create(key("breeze_rod")); + + /** + * {@code minecraft:breeze_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREEZE_SPAWN_EGG = create(key("breeze_spawn_egg")); + + /** + * {@code minecraft:brewer_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREWER_POTTERY_SHERD = create(key("brewer_pottery_sherd")); + + /** + * {@code minecraft:brewing_stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREWING_STAND = create(key("brewing_stand")); + + /** + * {@code minecraft:brick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK = create(key("brick")); + + /** + * {@code minecraft:brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_SLAB = create(key("brick_slab")); + + /** + * {@code minecraft:brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_STAIRS = create(key("brick_stairs")); + + /** + * {@code minecraft:brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICK_WALL = create(key("brick_wall")); + + /** + * {@code minecraft:bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRICKS = create(key("bricks")); + + /** + * {@code minecraft:brown_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_BANNER = create(key("brown_banner")); + + /** + * {@code minecraft:brown_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_BED = create(key("brown_bed")); + + /** + * {@code minecraft:brown_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_BUNDLE = create(key("brown_bundle")); + + /** + * {@code minecraft:brown_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CANDLE = create(key("brown_candle")); + + /** + * {@code minecraft:brown_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CARPET = create(key("brown_carpet")); + + /** + * {@code minecraft:brown_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CONCRETE = create(key("brown_concrete")); + + /** + * {@code minecraft:brown_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_CONCRETE_POWDER = create(key("brown_concrete_powder")); + + /** + * {@code minecraft:brown_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_DYE = create(key("brown_dye")); + + /** + * {@code minecraft:brown_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_GLAZED_TERRACOTTA = create(key("brown_glazed_terracotta")); + + /** + * {@code minecraft:brown_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_MUSHROOM = create(key("brown_mushroom")); + + /** + * {@code minecraft:brown_mushroom_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_MUSHROOM_BLOCK = create(key("brown_mushroom_block")); + + /** + * {@code minecraft:brown_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_SHULKER_BOX = create(key("brown_shulker_box")); + + /** + * {@code minecraft:brown_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_STAINED_GLASS = create(key("brown_stained_glass")); + + /** + * {@code minecraft:brown_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_STAINED_GLASS_PANE = create(key("brown_stained_glass_pane")); + + /** + * {@code minecraft:brown_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_TERRACOTTA = create(key("brown_terracotta")); + + /** + * {@code minecraft:brown_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BROWN_WOOL = create(key("brown_wool")); + + /** + * {@code minecraft:brush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BRUSH = create(key("brush")); + + /** + * {@code minecraft:bubble_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL = create(key("bubble_coral")); + + /** + * {@code minecraft:bubble_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL_BLOCK = create(key("bubble_coral_block")); + + /** + * {@code minecraft:bubble_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUBBLE_CORAL_FAN = create(key("bubble_coral_fan")); + + /** + * {@code minecraft:bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUCKET = create(key("bucket")); + + /** + * {@code minecraft:budding_amethyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUDDING_AMETHYST = create(key("budding_amethyst")); + + /** + * {@code minecraft:bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUNDLE = create(key("bundle")); + + /** + * {@code minecraft:burn_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURN_POTTERY_SHERD = create(key("burn_pottery_sherd")); + + /** + * {@code minecraft:cactus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CACTUS = create(key("cactus")); + + /** + * {@code minecraft:cake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAKE = create(key("cake")); + + /** + * {@code minecraft:calcite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALCITE = create(key("calcite")); + + /** + * {@code minecraft:calibrated_sculk_sensor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALIBRATED_SCULK_SENSOR = create(key("calibrated_sculk_sensor")); + + /** + * {@code minecraft:camel_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAMEL_SPAWN_EGG = create(key("camel_spawn_egg")); + + /** + * {@code minecraft:campfire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAMPFIRE = create(key("campfire")); + + /** + * {@code minecraft:candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CANDLE = create(key("candle")); + + /** + * {@code minecraft:carrot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARROT = create(key("carrot")); + + /** + * {@code minecraft:carrot_on_a_stick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARROT_ON_A_STICK = create(key("carrot_on_a_stick")); + + /** + * {@code minecraft:cartography_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARTOGRAPHY_TABLE = create(key("cartography_table")); + + /** + * {@code minecraft:carved_pumpkin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARVED_PUMPKIN = create(key("carved_pumpkin")); + + /** + * {@code minecraft:cat_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAT_SPAWN_EGG = create(key("cat_spawn_egg")); + + /** + * {@code minecraft:cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAULDRON = create(key("cauldron")); + + /** + * {@code minecraft:cave_spider_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAVE_SPIDER_SPAWN_EGG = create(key("cave_spider_spawn_egg")); + + /** + * {@code minecraft:chain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAIN = create(key("chain")); + + /** + * {@code minecraft:chain_command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAIN_COMMAND_BLOCK = create(key("chain_command_block")); + + /** + * {@code minecraft:chainmail_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAINMAIL_BOOTS = create(key("chainmail_boots")); + + /** + * {@code minecraft:chainmail_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAINMAIL_CHESTPLATE = create(key("chainmail_chestplate")); + + /** + * {@code minecraft:chainmail_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAINMAIL_HELMET = create(key("chainmail_helmet")); + + /** + * {@code minecraft:chainmail_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHAINMAIL_LEGGINGS = create(key("chainmail_leggings")); + + /** + * {@code minecraft:charcoal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHARCOAL = create(key("charcoal")); + + /** + * {@code minecraft:cherry_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_BOAT = create(key("cherry_boat")); + + /** + * {@code minecraft:cherry_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_BUTTON = create(key("cherry_button")); + + /** + * {@code minecraft:cherry_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_CHEST_BOAT = create(key("cherry_chest_boat")); + + /** + * {@code minecraft:cherry_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_DOOR = create(key("cherry_door")); + + /** + * {@code minecraft:cherry_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_FENCE = create(key("cherry_fence")); + + /** + * {@code minecraft:cherry_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_FENCE_GATE = create(key("cherry_fence_gate")); + + /** + * {@code minecraft:cherry_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_HANGING_SIGN = create(key("cherry_hanging_sign")); + + /** + * {@code minecraft:cherry_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_LEAVES = create(key("cherry_leaves")); + + /** + * {@code minecraft:cherry_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_LOG = create(key("cherry_log")); + + /** + * {@code minecraft:cherry_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_PLANKS = create(key("cherry_planks")); + + /** + * {@code minecraft:cherry_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_PRESSURE_PLATE = create(key("cherry_pressure_plate")); + + /** + * {@code minecraft:cherry_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SAPLING = create(key("cherry_sapling")); + + /** + * {@code minecraft:cherry_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SIGN = create(key("cherry_sign")); + + /** + * {@code minecraft:cherry_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_SLAB = create(key("cherry_slab")); + + /** + * {@code minecraft:cherry_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_STAIRS = create(key("cherry_stairs")); + + /** + * {@code minecraft:cherry_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_TRAPDOOR = create(key("cherry_trapdoor")); + + /** + * {@code minecraft:cherry_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_WOOD = create(key("cherry_wood")); + + /** + * {@code minecraft:chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHEST = create(key("chest")); + + /** + * {@code minecraft:chest_minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHEST_MINECART = create(key("chest_minecart")); + + /** + * {@code minecraft:chicken} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHICKEN = create(key("chicken")); + + /** + * {@code minecraft:chicken_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHICKEN_SPAWN_EGG = create(key("chicken_spawn_egg")); + + /** + * {@code minecraft:chipped_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHIPPED_ANVIL = create(key("chipped_anvil")); + + /** + * {@code minecraft:chiseled_bookshelf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_BOOKSHELF = create(key("chiseled_bookshelf")); + + /** + * {@code minecraft:chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_COPPER = create(key("chiseled_copper")); + + /** + * {@code minecraft:chiseled_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_DEEPSLATE = create(key("chiseled_deepslate")); + + /** + * {@code minecraft:chiseled_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_NETHER_BRICKS = create(key("chiseled_nether_bricks")); + + /** + * {@code minecraft:chiseled_polished_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_POLISHED_BLACKSTONE = create(key("chiseled_polished_blackstone")); + + /** + * {@code minecraft:chiseled_quartz_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_QUARTZ_BLOCK = create(key("chiseled_quartz_block")); + + /** + * {@code minecraft:chiseled_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_RED_SANDSTONE = create(key("chiseled_red_sandstone")); + + /** + * {@code minecraft:chiseled_resin_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_RESIN_BRICKS = create(key("chiseled_resin_bricks")); + + /** + * {@code minecraft:chiseled_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_SANDSTONE = create(key("chiseled_sandstone")); + + /** + * {@code minecraft:chiseled_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_STONE_BRICKS = create(key("chiseled_stone_bricks")); + + /** + * {@code minecraft:chiseled_tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_TUFF = create(key("chiseled_tuff")); + + /** + * {@code minecraft:chiseled_tuff_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHISELED_TUFF_BRICKS = create(key("chiseled_tuff_bricks")); + + /** + * {@code minecraft:chorus_flower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHORUS_FLOWER = create(key("chorus_flower")); + + /** + * {@code minecraft:chorus_fruit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHORUS_FRUIT = create(key("chorus_fruit")); + + /** + * {@code minecraft:chorus_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHORUS_PLANT = create(key("chorus_plant")); + + /** + * {@code minecraft:clay} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLAY = create(key("clay")); + + /** + * {@code minecraft:clay_ball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLAY_BALL = create(key("clay_ball")); + + /** + * {@code minecraft:clock} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLOCK = create(key("clock")); + + /** + * {@code minecraft:closed_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLOSED_EYEBLOSSOM = create(key("closed_eyeblossom")); + + /** + * {@code minecraft:coal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAL = create(key("coal")); + + /** + * {@code minecraft:coal_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAL_BLOCK = create(key("coal_block")); + + /** + * {@code minecraft:coal_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAL_ORE = create(key("coal_ore")); + + /** + * {@code minecraft:coarse_dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COARSE_DIRT = create(key("coarse_dirt")); + + /** + * {@code minecraft:coast_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAST_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("coast_armor_trim_smithing_template")); + + /** + * {@code minecraft:cobbled_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE = create(key("cobbled_deepslate")); + + /** + * {@code minecraft:cobbled_deepslate_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_SLAB = create(key("cobbled_deepslate_slab")); + + /** + * {@code minecraft:cobbled_deepslate_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_STAIRS = create(key("cobbled_deepslate_stairs")); + + /** + * {@code minecraft:cobbled_deepslate_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLED_DEEPSLATE_WALL = create(key("cobbled_deepslate_wall")); + + /** + * {@code minecraft:cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE = create(key("cobblestone")); + + /** + * {@code minecraft:cobblestone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_SLAB = create(key("cobblestone_slab")); + + /** + * {@code minecraft:cobblestone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_STAIRS = create(key("cobblestone_stairs")); + + /** + * {@code minecraft:cobblestone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBBLESTONE_WALL = create(key("cobblestone_wall")); + + /** + * {@code minecraft:cobweb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COBWEB = create(key("cobweb")); + + /** + * {@code minecraft:cocoa_beans} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COCOA_BEANS = create(key("cocoa_beans")); + + /** + * {@code minecraft:cod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COD = create(key("cod")); + + /** + * {@code minecraft:cod_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COD_BUCKET = create(key("cod_bucket")); + + /** + * {@code minecraft:cod_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COD_SPAWN_EGG = create(key("cod_spawn_egg")); + + /** + * {@code minecraft:command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMMAND_BLOCK = create(key("command_block")); + + /** + * {@code minecraft:command_block_minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMMAND_BLOCK_MINECART = create(key("command_block_minecart")); + + /** + * {@code minecraft:comparator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMPARATOR = create(key("comparator")); + + /** + * {@code minecraft:compass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMPASS = create(key("compass")); + + /** + * {@code minecraft:composter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COMPOSTER = create(key("composter")); + + /** + * {@code minecraft:conduit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONDUIT = create(key("conduit")); + + /** + * {@code minecraft:cooked_beef} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_BEEF = create(key("cooked_beef")); + + /** + * {@code minecraft:cooked_chicken} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_CHICKEN = create(key("cooked_chicken")); + + /** + * {@code minecraft:cooked_cod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_COD = create(key("cooked_cod")); + + /** + * {@code minecraft:cooked_mutton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_MUTTON = create(key("cooked_mutton")); + + /** + * {@code minecraft:cooked_porkchop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_PORKCHOP = create(key("cooked_porkchop")); + + /** + * {@code minecraft:cooked_rabbit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_RABBIT = create(key("cooked_rabbit")); + + /** + * {@code minecraft:cooked_salmon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKED_SALMON = create(key("cooked_salmon")); + + /** + * {@code minecraft:cookie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COOKIE = create(key("cookie")); + + /** + * {@code minecraft:copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_BLOCK = create(key("copper_block")); + + /** + * {@code minecraft:copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_BULB = create(key("copper_bulb")); + + /** + * {@code minecraft:copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_DOOR = create(key("copper_door")); + + /** + * {@code minecraft:copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_GRATE = create(key("copper_grate")); + + /** + * {@code minecraft:copper_ingot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_INGOT = create(key("copper_ingot")); + + /** + * {@code minecraft:copper_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_ORE = create(key("copper_ore")); + + /** + * {@code minecraft:copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER_TRAPDOOR = create(key("copper_trapdoor")); + + /** + * {@code minecraft:cornflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CORNFLOWER = create(key("cornflower")); + + /** + * {@code minecraft:cow_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COW_SPAWN_EGG = create(key("cow_spawn_egg")); + + /** + * {@code minecraft:cracked_deepslate_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_DEEPSLATE_BRICKS = create(key("cracked_deepslate_bricks")); + + /** + * {@code minecraft:cracked_deepslate_tiles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_DEEPSLATE_TILES = create(key("cracked_deepslate_tiles")); + + /** + * {@code minecraft:cracked_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_NETHER_BRICKS = create(key("cracked_nether_bricks")); + + /** + * {@code minecraft:cracked_polished_blackstone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_POLISHED_BLACKSTONE_BRICKS = create(key("cracked_polished_blackstone_bricks")); + + /** + * {@code minecraft:cracked_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRACKED_STONE_BRICKS = create(key("cracked_stone_bricks")); + + /** + * {@code minecraft:crafter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTER = create(key("crafter")); + + /** + * {@code minecraft:crafting_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTING_TABLE = create(key("crafting_table")); + + /** + * {@code minecraft:creaking_heart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREAKING_HEART = create(key("creaking_heart")); + + /** + * {@code minecraft:creaking_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREAKING_SPAWN_EGG = create(key("creaking_spawn_egg")); + + /** + * {@code minecraft:creeper_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER_BANNER_PATTERN = create(key("creeper_banner_pattern")); + + /** + * {@code minecraft:creeper_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER_HEAD = create(key("creeper_head")); + + /** + * {@code minecraft:creeper_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEPER_SPAWN_EGG = create(key("creeper_spawn_egg")); + + /** + * {@code minecraft:crimson_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_BUTTON = create(key("crimson_button")); + + /** + * {@code minecraft:crimson_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_DOOR = create(key("crimson_door")); + + /** + * {@code minecraft:crimson_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FENCE = create(key("crimson_fence")); + + /** + * {@code minecraft:crimson_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FENCE_GATE = create(key("crimson_fence_gate")); + + /** + * {@code minecraft:crimson_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FUNGUS = create(key("crimson_fungus")); + + /** + * {@code minecraft:crimson_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_HANGING_SIGN = create(key("crimson_hanging_sign")); + + /** + * {@code minecraft:crimson_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_HYPHAE = create(key("crimson_hyphae")); + + /** + * {@code minecraft:crimson_nylium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_NYLIUM = create(key("crimson_nylium")); + + /** + * {@code minecraft:crimson_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_PLANKS = create(key("crimson_planks")); + + /** + * {@code minecraft:crimson_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_PRESSURE_PLATE = create(key("crimson_pressure_plate")); + + /** + * {@code minecraft:crimson_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_ROOTS = create(key("crimson_roots")); + + /** + * {@code minecraft:crimson_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_SIGN = create(key("crimson_sign")); + + /** + * {@code minecraft:crimson_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_SLAB = create(key("crimson_slab")); + + /** + * {@code minecraft:crimson_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_STAIRS = create(key("crimson_stairs")); + + /** + * {@code minecraft:crimson_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_STEM = create(key("crimson_stem")); + + /** + * {@code minecraft:crimson_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_TRAPDOOR = create(key("crimson_trapdoor")); + + /** + * {@code minecraft:crossbow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CROSSBOW = create(key("crossbow")); + + /** + * {@code minecraft:crying_obsidian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRYING_OBSIDIAN = create(key("crying_obsidian")); + + /** + * {@code minecraft:cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER = create(key("cut_copper")); + + /** + * {@code minecraft:cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER_SLAB = create(key("cut_copper_slab")); + + /** + * {@code minecraft:cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_COPPER_STAIRS = create(key("cut_copper_stairs")); + + /** + * {@code minecraft:cut_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_RED_SANDSTONE = create(key("cut_red_sandstone")); + + /** + * {@code minecraft:cut_red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_RED_SANDSTONE_SLAB = create(key("cut_red_sandstone_slab")); + + /** + * {@code minecraft:cut_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_SANDSTONE = create(key("cut_sandstone")); + + /** + * {@code minecraft:cut_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CUT_SANDSTONE_SLAB = create(key("cut_sandstone_slab")); + + /** + * {@code minecraft:cyan_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_BANNER = create(key("cyan_banner")); + + /** + * {@code minecraft:cyan_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_BED = create(key("cyan_bed")); + + /** + * {@code minecraft:cyan_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_BUNDLE = create(key("cyan_bundle")); + + /** + * {@code minecraft:cyan_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CANDLE = create(key("cyan_candle")); + + /** + * {@code minecraft:cyan_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CARPET = create(key("cyan_carpet")); + + /** + * {@code minecraft:cyan_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CONCRETE = create(key("cyan_concrete")); + + /** + * {@code minecraft:cyan_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_CONCRETE_POWDER = create(key("cyan_concrete_powder")); + + /** + * {@code minecraft:cyan_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_DYE = create(key("cyan_dye")); + + /** + * {@code minecraft:cyan_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_GLAZED_TERRACOTTA = create(key("cyan_glazed_terracotta")); + + /** + * {@code minecraft:cyan_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_SHULKER_BOX = create(key("cyan_shulker_box")); + + /** + * {@code minecraft:cyan_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_STAINED_GLASS = create(key("cyan_stained_glass")); + + /** + * {@code minecraft:cyan_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_STAINED_GLASS_PANE = create(key("cyan_stained_glass_pane")); + + /** + * {@code minecraft:cyan_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_TERRACOTTA = create(key("cyan_terracotta")); + + /** + * {@code minecraft:cyan_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CYAN_WOOL = create(key("cyan_wool")); + + /** + * {@code minecraft:damaged_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DAMAGED_ANVIL = create(key("damaged_anvil")); + + /** + * {@code minecraft:dandelion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DANDELION = create(key("dandelion")); + + /** + * {@code minecraft:danger_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DANGER_POTTERY_SHERD = create(key("danger_pottery_sherd")); + + /** + * {@code minecraft:dark_oak_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_BOAT = create(key("dark_oak_boat")); + + /** + * {@code minecraft:dark_oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_BUTTON = create(key("dark_oak_button")); + + /** + * {@code minecraft:dark_oak_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_CHEST_BOAT = create(key("dark_oak_chest_boat")); + + /** + * {@code minecraft:dark_oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_DOOR = create(key("dark_oak_door")); + + /** + * {@code minecraft:dark_oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_FENCE = create(key("dark_oak_fence")); + + /** + * {@code minecraft:dark_oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_FENCE_GATE = create(key("dark_oak_fence_gate")); + + /** + * {@code minecraft:dark_oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_HANGING_SIGN = create(key("dark_oak_hanging_sign")); + + /** + * {@code minecraft:dark_oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_LEAVES = create(key("dark_oak_leaves")); + + /** + * {@code minecraft:dark_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_LOG = create(key("dark_oak_log")); + + /** + * {@code minecraft:dark_oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_PLANKS = create(key("dark_oak_planks")); + + /** + * {@code minecraft:dark_oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_PRESSURE_PLATE = create(key("dark_oak_pressure_plate")); + + /** + * {@code minecraft:dark_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SAPLING = create(key("dark_oak_sapling")); + + /** + * {@code minecraft:dark_oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SIGN = create(key("dark_oak_sign")); + + /** + * {@code minecraft:dark_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_SLAB = create(key("dark_oak_slab")); + + /** + * {@code minecraft:dark_oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_STAIRS = create(key("dark_oak_stairs")); + + /** + * {@code minecraft:dark_oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_TRAPDOOR = create(key("dark_oak_trapdoor")); + + /** + * {@code minecraft:dark_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_OAK_WOOD = create(key("dark_oak_wood")); + + /** + * {@code minecraft:dark_prismarine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE = create(key("dark_prismarine")); + + /** + * {@code minecraft:dark_prismarine_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE_SLAB = create(key("dark_prismarine_slab")); + + /** + * {@code minecraft:dark_prismarine_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_PRISMARINE_STAIRS = create(key("dark_prismarine_stairs")); + + /** + * {@code minecraft:daylight_detector} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DAYLIGHT_DETECTOR = create(key("daylight_detector")); + + /** + * {@code minecraft:dead_brain_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL = create(key("dead_brain_coral")); + + /** + * {@code minecraft:dead_brain_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL_BLOCK = create(key("dead_brain_coral_block")); + + /** + * {@code minecraft:dead_brain_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BRAIN_CORAL_FAN = create(key("dead_brain_coral_fan")); + + /** + * {@code minecraft:dead_bubble_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL = create(key("dead_bubble_coral")); + + /** + * {@code minecraft:dead_bubble_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL_BLOCK = create(key("dead_bubble_coral_block")); + + /** + * {@code minecraft:dead_bubble_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUBBLE_CORAL_FAN = create(key("dead_bubble_coral_fan")); + + /** + * {@code minecraft:dead_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_BUSH = create(key("dead_bush")); + + /** + * {@code minecraft:dead_fire_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL = create(key("dead_fire_coral")); + + /** + * {@code minecraft:dead_fire_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL_BLOCK = create(key("dead_fire_coral_block")); + + /** + * {@code minecraft:dead_fire_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_FIRE_CORAL_FAN = create(key("dead_fire_coral_fan")); + + /** + * {@code minecraft:dead_horn_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL = create(key("dead_horn_coral")); + + /** + * {@code minecraft:dead_horn_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL_BLOCK = create(key("dead_horn_coral_block")); + + /** + * {@code minecraft:dead_horn_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_HORN_CORAL_FAN = create(key("dead_horn_coral_fan")); + + /** + * {@code minecraft:dead_tube_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL = create(key("dead_tube_coral")); + + /** + * {@code minecraft:dead_tube_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL_BLOCK = create(key("dead_tube_coral_block")); + + /** + * {@code minecraft:dead_tube_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEAD_TUBE_CORAL_FAN = create(key("dead_tube_coral_fan")); + + /** + * {@code minecraft:debug_stick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEBUG_STICK = create(key("debug_stick")); + + /** + * {@code minecraft:decorated_pot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DECORATED_POT = create(key("decorated_pot")); + + /** + * {@code minecraft:deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE = create(key("deepslate")); + + /** + * {@code minecraft:deepslate_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_SLAB = create(key("deepslate_brick_slab")); + + /** + * {@code minecraft:deepslate_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_STAIRS = create(key("deepslate_brick_stairs")); + + /** + * {@code minecraft:deepslate_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICK_WALL = create(key("deepslate_brick_wall")); + + /** + * {@code minecraft:deepslate_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_BRICKS = create(key("deepslate_bricks")); + + /** + * {@code minecraft:deepslate_coal_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_COAL_ORE = create(key("deepslate_coal_ore")); + + /** + * {@code minecraft:deepslate_copper_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_COPPER_ORE = create(key("deepslate_copper_ore")); + + /** + * {@code minecraft:deepslate_diamond_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_DIAMOND_ORE = create(key("deepslate_diamond_ore")); + + /** + * {@code minecraft:deepslate_emerald_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_EMERALD_ORE = create(key("deepslate_emerald_ore")); + + /** + * {@code minecraft:deepslate_gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_GOLD_ORE = create(key("deepslate_gold_ore")); + + /** + * {@code minecraft:deepslate_iron_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_IRON_ORE = create(key("deepslate_iron_ore")); + + /** + * {@code minecraft:deepslate_lapis_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_LAPIS_ORE = create(key("deepslate_lapis_ore")); + + /** + * {@code minecraft:deepslate_redstone_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_REDSTONE_ORE = create(key("deepslate_redstone_ore")); + + /** + * {@code minecraft:deepslate_tile_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_SLAB = create(key("deepslate_tile_slab")); + + /** + * {@code minecraft:deepslate_tile_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_STAIRS = create(key("deepslate_tile_stairs")); + + /** + * {@code minecraft:deepslate_tile_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILE_WALL = create(key("deepslate_tile_wall")); + + /** + * {@code minecraft:deepslate_tiles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEPSLATE_TILES = create(key("deepslate_tiles")); + + /** + * {@code minecraft:detector_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DETECTOR_RAIL = create(key("detector_rail")); + + /** + * {@code minecraft:diamond} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND = create(key("diamond")); + + /** + * {@code minecraft:diamond_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_AXE = create(key("diamond_axe")); + + /** + * {@code minecraft:diamond_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_BLOCK = create(key("diamond_block")); + + /** + * {@code minecraft:diamond_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_BOOTS = create(key("diamond_boots")); + + /** + * {@code minecraft:diamond_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_CHESTPLATE = create(key("diamond_chestplate")); + + /** + * {@code minecraft:diamond_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_HELMET = create(key("diamond_helmet")); + + /** + * {@code minecraft:diamond_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_HOE = create(key("diamond_hoe")); + + /** + * {@code minecraft:diamond_horse_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_HORSE_ARMOR = create(key("diamond_horse_armor")); + + /** + * {@code minecraft:diamond_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_LEGGINGS = create(key("diamond_leggings")); + + /** + * {@code minecraft:diamond_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_ORE = create(key("diamond_ore")); + + /** + * {@code minecraft:diamond_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_PICKAXE = create(key("diamond_pickaxe")); + + /** + * {@code minecraft:diamond_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_SHOVEL = create(key("diamond_shovel")); + + /** + * {@code minecraft:diamond_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND_SWORD = create(key("diamond_sword")); + + /** + * {@code minecraft:diorite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE = create(key("diorite")); + + /** + * {@code minecraft:diorite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_SLAB = create(key("diorite_slab")); + + /** + * {@code minecraft:diorite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_STAIRS = create(key("diorite_stairs")); + + /** + * {@code minecraft:diorite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIORITE_WALL = create(key("diorite_wall")); + + /** + * {@code minecraft:dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIRT = create(key("dirt")); + + /** + * {@code minecraft:dirt_path} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIRT_PATH = create(key("dirt_path")); + + /** + * {@code minecraft:field_masoned_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIELD_MASONED_BANNER_PATTERN = create(key("field_masoned_banner_pattern")); + + /** + * {@code minecraft:fletching_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLETCHING_TABLE = create(key("fletching_table")); + + /** + * {@code minecraft:flow_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOW_BANNER_PATTERN = create(key("flow_banner_pattern")); + + /** + * {@code minecraft:flower_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER_BANNER_PATTERN = create(key("flower_banner_pattern")); + + /** + * {@code minecraft:glow_berries} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_BERRIES = create(key("glow_berries")); + + /** + * {@code minecraft:goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOAT_HORN = create(key("goat_horn")); + + /** + * {@code minecraft:grindstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRINDSTONE = create(key("grindstone")); + + /** + * {@code minecraft:honeycomb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEYCOMB = create(key("honeycomb")); + + /** + * {@code minecraft:lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LANTERN = create(key("lantern")); + + /** + * {@code minecraft:music_disc_5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_5 = create(key("music_disc_5")); + + /** + * {@code minecraft:disc_fragment_5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DISC_FRAGMENT_5 = create(key("disc_fragment_5")); + + /** + * {@code minecraft:dispenser} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DISPENSER = create(key("dispenser")); + + /** + * {@code minecraft:dolphin_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DOLPHIN_SPAWN_EGG = create(key("dolphin_spawn_egg")); + + /** + * {@code minecraft:donkey_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DONKEY_SPAWN_EGG = create(key("donkey_spawn_egg")); + + /** + * {@code minecraft:dragon_breath} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_BREATH = create(key("dragon_breath")); + + /** + * {@code minecraft:dragon_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_EGG = create(key("dragon_egg")); + + /** + * {@code minecraft:dragon_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_HEAD = create(key("dragon_head")); + + /** + * {@code minecraft:dried_kelp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIED_KELP = create(key("dried_kelp")); + + /** + * {@code minecraft:dried_kelp_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIED_KELP_BLOCK = create(key("dried_kelp_block")); + + /** + * {@code minecraft:dripstone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIPSTONE_BLOCK = create(key("dripstone_block")); + + /** + * {@code minecraft:dropper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DROPPER = create(key("dropper")); + + /** + * {@code minecraft:drowned_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DROWNED_SPAWN_EGG = create(key("drowned_spawn_egg")); + + /** + * {@code minecraft:dune_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("dune_armor_trim_smithing_template")); + + /** + * {@code minecraft:echo_shard} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ECHO_SHARD = create(key("echo_shard")); + + /** + * {@code minecraft:egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EGG = create(key("egg")); + + /** + * {@code minecraft:elder_guardian_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ELDER_GUARDIAN_SPAWN_EGG = create(key("elder_guardian_spawn_egg")); + + /** + * {@code minecraft:elytra} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ELYTRA = create(key("elytra")); + + /** + * {@code minecraft:emerald} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD = create(key("emerald")); + + /** + * {@code minecraft:emerald_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD_BLOCK = create(key("emerald_block")); + + /** + * {@code minecraft:emerald_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD_ORE = create(key("emerald_ore")); + + /** + * {@code minecraft:enchanted_book} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANTED_BOOK = create(key("enchanted_book")); + + /** + * {@code minecraft:enchanted_golden_apple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANTED_GOLDEN_APPLE = create(key("enchanted_golden_apple")); + + /** + * {@code minecraft:enchanting_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANTING_TABLE = create(key("enchanting_table")); + + /** + * {@code minecraft:end_crystal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_CRYSTAL = create(key("end_crystal")); + + /** + * {@code minecraft:end_portal_frame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_PORTAL_FRAME = create(key("end_portal_frame")); + + /** + * {@code minecraft:end_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_ROD = create(key("end_rod")); + + /** + * {@code minecraft:end_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE = create(key("end_stone")); + + /** + * {@code minecraft:end_stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_SLAB = create(key("end_stone_brick_slab")); + + /** + * {@code minecraft:end_stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_STAIRS = create(key("end_stone_brick_stairs")); + + /** + * {@code minecraft:end_stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICK_WALL = create(key("end_stone_brick_wall")); + + /** + * {@code minecraft:end_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_STONE_BRICKS = create(key("end_stone_bricks")); + + /** + * {@code minecraft:ender_chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_CHEST = create(key("ender_chest")); + + /** + * {@code minecraft:ender_dragon_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_DRAGON_SPAWN_EGG = create(key("ender_dragon_spawn_egg")); + + /** + * {@code minecraft:ender_eye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_EYE = create(key("ender_eye")); + + /** + * {@code minecraft:ender_pearl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDER_PEARL = create(key("ender_pearl")); + + /** + * {@code minecraft:enderman_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDERMAN_SPAWN_EGG = create(key("enderman_spawn_egg")); + + /** + * {@code minecraft:endermite_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDERMITE_SPAWN_EGG = create(key("endermite_spawn_egg")); + + /** + * {@code minecraft:evoker_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EVOKER_SPAWN_EGG = create(key("evoker_spawn_egg")); + + /** + * {@code minecraft:experience_bottle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPERIENCE_BOTTLE = create(key("experience_bottle")); + + /** + * {@code minecraft:explorer_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLORER_POTTERY_SHERD = create(key("explorer_pottery_sherd")); + + /** + * {@code minecraft:exposed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CHISELED_COPPER = create(key("exposed_chiseled_copper")); + + /** + * {@code minecraft:exposed_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER = create(key("exposed_copper")); + + /** + * {@code minecraft:exposed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_BULB = create(key("exposed_copper_bulb")); + + /** + * {@code minecraft:exposed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_DOOR = create(key("exposed_copper_door")); + + /** + * {@code minecraft:exposed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_GRATE = create(key("exposed_copper_grate")); + + /** + * {@code minecraft:exposed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_COPPER_TRAPDOOR = create(key("exposed_copper_trapdoor")); + + /** + * {@code minecraft:exposed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER = create(key("exposed_cut_copper")); + + /** + * {@code minecraft:exposed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER_SLAB = create(key("exposed_cut_copper_slab")); + + /** + * {@code minecraft:exposed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPOSED_CUT_COPPER_STAIRS = create(key("exposed_cut_copper_stairs")); + + /** + * {@code minecraft:eye_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EYE_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("eye_armor_trim_smithing_template")); + + /** + * {@code minecraft:farmland} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FARMLAND = create(key("farmland")); + + /** + * {@code minecraft:feather} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FEATHER = create(key("feather")); + + /** + * {@code minecraft:fermented_spider_eye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FERMENTED_SPIDER_EYE = create(key("fermented_spider_eye")); + + /** + * {@code minecraft:fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FERN = create(key("fern")); + + /** + * {@code minecraft:filled_map} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FILLED_MAP = create(key("filled_map")); + + /** + * {@code minecraft:fire_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CHARGE = create(key("fire_charge")); + + /** + * {@code minecraft:fire_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL = create(key("fire_coral")); + + /** + * {@code minecraft:fire_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL_BLOCK = create(key("fire_coral_block")); + + /** + * {@code minecraft:fire_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_CORAL_FAN = create(key("fire_coral_fan")); + + /** + * {@code minecraft:firework_rocket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREWORK_ROCKET = create(key("firework_rocket")); + + /** + * {@code minecraft:firework_star} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREWORK_STAR = create(key("firework_star")); + + /** + * {@code minecraft:fishing_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FISHING_ROD = create(key("fishing_rod")); + + /** + * {@code minecraft:flint} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLINT = create(key("flint")); + + /** + * {@code minecraft:flint_and_steel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLINT_AND_STEEL = create(key("flint_and_steel")); + + /** + * {@code minecraft:flow_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOW_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("flow_armor_trim_smithing_template")); + + /** + * {@code minecraft:flow_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOW_POTTERY_SHERD = create(key("flow_pottery_sherd")); + + /** + * {@code minecraft:flower_pot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER_POT = create(key("flower_pot")); + + /** + * {@code minecraft:flowering_azalea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWERING_AZALEA = create(key("flowering_azalea")); + + /** + * {@code minecraft:flowering_azalea_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWERING_AZALEA_LEAVES = create(key("flowering_azalea_leaves")); + + /** + * {@code minecraft:fox_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FOX_SPAWN_EGG = create(key("fox_spawn_egg")); + + /** + * {@code minecraft:friend_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FRIEND_POTTERY_SHERD = create(key("friend_pottery_sherd")); + + /** + * {@code minecraft:frog_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROG_SPAWN_EGG = create(key("frog_spawn_egg")); + + /** + * {@code minecraft:frogspawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROGSPAWN = create(key("frogspawn")); + + /** + * {@code minecraft:furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FURNACE = create(key("furnace")); + + /** + * {@code minecraft:furnace_minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FURNACE_MINECART = create(key("furnace_minecart")); + + /** + * {@code minecraft:ghast_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GHAST_SPAWN_EGG = create(key("ghast_spawn_egg")); + + /** + * {@code minecraft:ghast_tear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GHAST_TEAR = create(key("ghast_tear")); + + /** + * {@code minecraft:gilded_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GILDED_BLACKSTONE = create(key("gilded_blackstone")); + + /** + * {@code minecraft:glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLASS = create(key("glass")); + + /** + * {@code minecraft:glass_bottle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLASS_BOTTLE = create(key("glass_bottle")); + + /** + * {@code minecraft:glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLASS_PANE = create(key("glass_pane")); + + /** + * {@code minecraft:glistering_melon_slice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLISTERING_MELON_SLICE = create(key("glistering_melon_slice")); + + /** + * {@code minecraft:globe_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOBE_BANNER_PATTERN = create(key("globe_banner_pattern")); + + /** + * {@code minecraft:glow_ink_sac} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_INK_SAC = create(key("glow_ink_sac")); + + /** + * {@code minecraft:glow_item_frame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_ITEM_FRAME = create(key("glow_item_frame")); + + /** + * {@code minecraft:glow_lichen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_LICHEN = create(key("glow_lichen")); + + /** + * {@code minecraft:glow_squid_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOW_SQUID_SPAWN_EGG = create(key("glow_squid_spawn_egg")); + + /** + * {@code minecraft:glowstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOWSTONE = create(key("glowstone")); + + /** + * {@code minecraft:glowstone_dust} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOWSTONE_DUST = create(key("glowstone_dust")); + + /** + * {@code minecraft:goat_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOAT_SPAWN_EGG = create(key("goat_spawn_egg")); + + /** + * {@code minecraft:gold_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_BLOCK = create(key("gold_block")); + + /** + * {@code minecraft:gold_ingot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_INGOT = create(key("gold_ingot")); + + /** + * {@code minecraft:gold_nugget} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_NUGGET = create(key("gold_nugget")); + + /** + * {@code minecraft:gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD_ORE = create(key("gold_ore")); + + /** + * {@code minecraft:golden_apple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_APPLE = create(key("golden_apple")); + + /** + * {@code minecraft:golden_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_AXE = create(key("golden_axe")); + + /** + * {@code minecraft:golden_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_BOOTS = create(key("golden_boots")); + + /** + * {@code minecraft:golden_carrot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_CARROT = create(key("golden_carrot")); + + /** + * {@code minecraft:golden_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_CHESTPLATE = create(key("golden_chestplate")); + + /** + * {@code minecraft:golden_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_HELMET = create(key("golden_helmet")); + + /** + * {@code minecraft:golden_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_HOE = create(key("golden_hoe")); + + /** + * {@code minecraft:golden_horse_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_HORSE_ARMOR = create(key("golden_horse_armor")); + + /** + * {@code minecraft:golden_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_LEGGINGS = create(key("golden_leggings")); + + /** + * {@code minecraft:golden_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_PICKAXE = create(key("golden_pickaxe")); + + /** + * {@code minecraft:golden_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_SHOVEL = create(key("golden_shovel")); + + /** + * {@code minecraft:golden_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLDEN_SWORD = create(key("golden_sword")); + + /** + * {@code minecraft:granite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE = create(key("granite")); + + /** + * {@code minecraft:granite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_SLAB = create(key("granite_slab")); + + /** + * {@code minecraft:granite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_STAIRS = create(key("granite_stairs")); + + /** + * {@code minecraft:granite_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRANITE_WALL = create(key("granite_wall")); + + /** + * {@code minecraft:grass_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRASS_BLOCK = create(key("grass_block")); + + /** + * {@code minecraft:gravel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAVEL = create(key("gravel")); + + /** + * {@code minecraft:gray_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_BANNER = create(key("gray_banner")); + + /** + * {@code minecraft:gray_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_BED = create(key("gray_bed")); + + /** + * {@code minecraft:gray_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_BUNDLE = create(key("gray_bundle")); + + /** + * {@code minecraft:gray_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CANDLE = create(key("gray_candle")); + + /** + * {@code minecraft:gray_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CARPET = create(key("gray_carpet")); + + /** + * {@code minecraft:gray_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CONCRETE = create(key("gray_concrete")); + + /** + * {@code minecraft:gray_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_CONCRETE_POWDER = create(key("gray_concrete_powder")); + + /** + * {@code minecraft:gray_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_DYE = create(key("gray_dye")); + + /** + * {@code minecraft:gray_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_GLAZED_TERRACOTTA = create(key("gray_glazed_terracotta")); + + /** + * {@code minecraft:gray_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_SHULKER_BOX = create(key("gray_shulker_box")); + + /** + * {@code minecraft:gray_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_STAINED_GLASS = create(key("gray_stained_glass")); + + /** + * {@code minecraft:gray_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_STAINED_GLASS_PANE = create(key("gray_stained_glass_pane")); + + /** + * {@code minecraft:gray_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_TERRACOTTA = create(key("gray_terracotta")); + + /** + * {@code minecraft:gray_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAY_WOOL = create(key("gray_wool")); + + /** + * {@code minecraft:green_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_BANNER = create(key("green_banner")); + + /** + * {@code minecraft:green_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_BED = create(key("green_bed")); + + /** + * {@code minecraft:green_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_BUNDLE = create(key("green_bundle")); + + /** + * {@code minecraft:green_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CANDLE = create(key("green_candle")); + + /** + * {@code minecraft:green_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CARPET = create(key("green_carpet")); + + /** + * {@code minecraft:green_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CONCRETE = create(key("green_concrete")); + + /** + * {@code minecraft:green_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_CONCRETE_POWDER = create(key("green_concrete_powder")); + + /** + * {@code minecraft:green_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_DYE = create(key("green_dye")); + + /** + * {@code minecraft:green_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_GLAZED_TERRACOTTA = create(key("green_glazed_terracotta")); + + /** + * {@code minecraft:green_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_SHULKER_BOX = create(key("green_shulker_box")); + + /** + * {@code minecraft:green_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_STAINED_GLASS = create(key("green_stained_glass")); + + /** + * {@code minecraft:green_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_STAINED_GLASS_PANE = create(key("green_stained_glass_pane")); + + /** + * {@code minecraft:green_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_TERRACOTTA = create(key("green_terracotta")); + + /** + * {@code minecraft:green_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GREEN_WOOL = create(key("green_wool")); + + /** + * {@code minecraft:guardian_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GUARDIAN_SPAWN_EGG = create(key("guardian_spawn_egg")); + + /** + * {@code minecraft:gunpowder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GUNPOWDER = create(key("gunpowder")); + + /** + * {@code minecraft:guster_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GUSTER_BANNER_PATTERN = create(key("guster_banner_pattern")); + + /** + * {@code minecraft:guster_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GUSTER_POTTERY_SHERD = create(key("guster_pottery_sherd")); + + /** + * {@code minecraft:hanging_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HANGING_ROOTS = create(key("hanging_roots")); + + /** + * {@code minecraft:hay_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HAY_BLOCK = create(key("hay_block")); + + /** + * {@code minecraft:heart_of_the_sea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEART_OF_THE_SEA = create(key("heart_of_the_sea")); + + /** + * {@code minecraft:heart_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEART_POTTERY_SHERD = create(key("heart_pottery_sherd")); + + /** + * {@code minecraft:heartbreak_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEARTBREAK_POTTERY_SHERD = create(key("heartbreak_pottery_sherd")); + + /** + * {@code minecraft:heavy_core} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEAVY_CORE = create(key("heavy_core")); + + /** + * {@code minecraft:heavy_weighted_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEAVY_WEIGHTED_PRESSURE_PLATE = create(key("heavy_weighted_pressure_plate")); + + /** + * {@code minecraft:hoglin_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOGLIN_SPAWN_EGG = create(key("hoglin_spawn_egg")); + + /** + * {@code minecraft:honey_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEY_BLOCK = create(key("honey_block")); + + /** + * {@code minecraft:honey_bottle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEY_BOTTLE = create(key("honey_bottle")); + + /** + * {@code minecraft:honeycomb_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HONEYCOMB_BLOCK = create(key("honeycomb_block")); + + /** + * {@code minecraft:hopper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOPPER = create(key("hopper")); + + /** + * {@code minecraft:hopper_minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOPPER_MINECART = create(key("hopper_minecart")); + + /** + * {@code minecraft:horn_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL = create(key("horn_coral")); + + /** + * {@code minecraft:horn_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL_BLOCK = create(key("horn_coral_block")); + + /** + * {@code minecraft:horn_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORN_CORAL_FAN = create(key("horn_coral_fan")); + + /** + * {@code minecraft:horse_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HORSE_SPAWN_EGG = create(key("horse_spawn_egg")); + + /** + * {@code minecraft:host_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOST_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("host_armor_trim_smithing_template")); + + /** + * {@code minecraft:howl_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOWL_POTTERY_SHERD = create(key("howl_pottery_sherd")); + + /** + * {@code minecraft:husk_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HUSK_SPAWN_EGG = create(key("husk_spawn_egg")); + + /** + * {@code minecraft:ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ICE = create(key("ice")); + + /** + * {@code minecraft:infested_chiseled_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_CHISELED_STONE_BRICKS = create(key("infested_chiseled_stone_bricks")); + + /** + * {@code minecraft:infested_cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_COBBLESTONE = create(key("infested_cobblestone")); + + /** + * {@code minecraft:infested_cracked_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_CRACKED_STONE_BRICKS = create(key("infested_cracked_stone_bricks")); + + /** + * {@code minecraft:infested_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_DEEPSLATE = create(key("infested_deepslate")); + + /** + * {@code minecraft:infested_mossy_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_MOSSY_STONE_BRICKS = create(key("infested_mossy_stone_bricks")); + + /** + * {@code minecraft:infested_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_STONE = create(key("infested_stone")); + + /** + * {@code minecraft:infested_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED_STONE_BRICKS = create(key("infested_stone_bricks")); + + /** + * {@code minecraft:ink_sac} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INK_SAC = create(key("ink_sac")); + + /** + * {@code minecraft:iron_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_AXE = create(key("iron_axe")); + + /** + * {@code minecraft:iron_bars} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_BARS = create(key("iron_bars")); + + /** + * {@code minecraft:iron_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_BLOCK = create(key("iron_block")); + + /** + * {@code minecraft:iron_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_BOOTS = create(key("iron_boots")); + + /** + * {@code minecraft:iron_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_CHESTPLATE = create(key("iron_chestplate")); + + /** + * {@code minecraft:iron_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_DOOR = create(key("iron_door")); + + /** + * {@code minecraft:iron_golem_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_GOLEM_SPAWN_EGG = create(key("iron_golem_spawn_egg")); + + /** + * {@code minecraft:iron_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_HELMET = create(key("iron_helmet")); + + /** + * {@code minecraft:iron_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_HOE = create(key("iron_hoe")); + + /** + * {@code minecraft:iron_horse_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_HORSE_ARMOR = create(key("iron_horse_armor")); + + /** + * {@code minecraft:iron_ingot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_INGOT = create(key("iron_ingot")); + + /** + * {@code minecraft:iron_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_LEGGINGS = create(key("iron_leggings")); + + /** + * {@code minecraft:iron_nugget} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_NUGGET = create(key("iron_nugget")); + + /** + * {@code minecraft:iron_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_ORE = create(key("iron_ore")); + + /** + * {@code minecraft:iron_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_PICKAXE = create(key("iron_pickaxe")); + + /** + * {@code minecraft:iron_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_SHOVEL = create(key("iron_shovel")); + + /** + * {@code minecraft:iron_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_SWORD = create(key("iron_sword")); + + /** + * {@code minecraft:iron_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON_TRAPDOOR = create(key("iron_trapdoor")); + + /** + * {@code minecraft:item_frame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_FRAME = create(key("item_frame")); + + /** + * {@code minecraft:jack_o_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JACK_O_LANTERN = create(key("jack_o_lantern")); + + /** + * {@code minecraft:jigsaw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JIGSAW = create(key("jigsaw")); + + /** + * {@code minecraft:jukebox} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX = create(key("jukebox")); + + /** + * {@code minecraft:jungle_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_BOAT = create(key("jungle_boat")); + + /** + * {@code minecraft:jungle_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_BUTTON = create(key("jungle_button")); + + /** + * {@code minecraft:jungle_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_CHEST_BOAT = create(key("jungle_chest_boat")); + + /** + * {@code minecraft:jungle_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_DOOR = create(key("jungle_door")); + + /** + * {@code minecraft:jungle_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_FENCE = create(key("jungle_fence")); + + /** + * {@code minecraft:jungle_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_FENCE_GATE = create(key("jungle_fence_gate")); + + /** + * {@code minecraft:jungle_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_HANGING_SIGN = create(key("jungle_hanging_sign")); + + /** + * {@code minecraft:jungle_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_LEAVES = create(key("jungle_leaves")); + + /** + * {@code minecraft:jungle_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_LOG = create(key("jungle_log")); + + /** + * {@code minecraft:jungle_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_PLANKS = create(key("jungle_planks")); + + /** + * {@code minecraft:jungle_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_PRESSURE_PLATE = create(key("jungle_pressure_plate")); + + /** + * {@code minecraft:jungle_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SAPLING = create(key("jungle_sapling")); + + /** + * {@code minecraft:jungle_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SIGN = create(key("jungle_sign")); + + /** + * {@code minecraft:jungle_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_SLAB = create(key("jungle_slab")); + + /** + * {@code minecraft:jungle_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_STAIRS = create(key("jungle_stairs")); + + /** + * {@code minecraft:jungle_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_TRAPDOOR = create(key("jungle_trapdoor")); + + /** + * {@code minecraft:jungle_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_WOOD = create(key("jungle_wood")); + + /** + * {@code minecraft:kelp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KELP = create(key("kelp")); + + /** + * {@code minecraft:knowledge_book} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KNOWLEDGE_BOOK = create(key("knowledge_book")); + + /** + * {@code minecraft:ladder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LADDER = create(key("ladder")); + + /** + * {@code minecraft:lapis_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS_BLOCK = create(key("lapis_block")); + + /** + * {@code minecraft:lapis_lazuli} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS_LAZULI = create(key("lapis_lazuli")); + + /** + * {@code minecraft:lapis_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS_ORE = create(key("lapis_ore")); + + /** + * {@code minecraft:large_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LARGE_AMETHYST_BUD = create(key("large_amethyst_bud")); + + /** + * {@code minecraft:large_fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LARGE_FERN = create(key("large_fern")); + + /** + * {@code minecraft:lava_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA_BUCKET = create(key("lava_bucket")); + + /** + * {@code minecraft:lead} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEAD = create(key("lead")); + + /** + * {@code minecraft:leather} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER = create(key("leather")); + + /** + * {@code minecraft:leather_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER_BOOTS = create(key("leather_boots")); + + /** + * {@code minecraft:leather_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER_CHESTPLATE = create(key("leather_chestplate")); + + /** + * {@code minecraft:leather_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER_HELMET = create(key("leather_helmet")); + + /** + * {@code minecraft:leather_horse_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER_HORSE_ARMOR = create(key("leather_horse_armor")); + + /** + * {@code minecraft:leather_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHER_LEGGINGS = create(key("leather_leggings")); + + /** + * {@code minecraft:lectern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LECTERN = create(key("lectern")); + + /** + * {@code minecraft:lever} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEVER = create(key("lever")); + + /** + * {@code minecraft:light} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT = create(key("light")); + + /** + * {@code minecraft:light_blue_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_BANNER = create(key("light_blue_banner")); + + /** + * {@code minecraft:light_blue_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_BED = create(key("light_blue_bed")); + + /** + * {@code minecraft:light_blue_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_BUNDLE = create(key("light_blue_bundle")); + + /** + * {@code minecraft:light_blue_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CANDLE = create(key("light_blue_candle")); + + /** + * {@code minecraft:light_blue_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CARPET = create(key("light_blue_carpet")); + + /** + * {@code minecraft:light_blue_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CONCRETE = create(key("light_blue_concrete")); + + /** + * {@code minecraft:light_blue_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_CONCRETE_POWDER = create(key("light_blue_concrete_powder")); + + /** + * {@code minecraft:light_blue_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_DYE = create(key("light_blue_dye")); + + /** + * {@code minecraft:light_blue_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_GLAZED_TERRACOTTA = create(key("light_blue_glazed_terracotta")); + + /** + * {@code minecraft:light_blue_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_SHULKER_BOX = create(key("light_blue_shulker_box")); + + /** + * {@code minecraft:light_blue_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_STAINED_GLASS = create(key("light_blue_stained_glass")); + + /** + * {@code minecraft:light_blue_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_STAINED_GLASS_PANE = create(key("light_blue_stained_glass_pane")); + + /** + * {@code minecraft:light_blue_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_TERRACOTTA = create(key("light_blue_terracotta")); + + /** + * {@code minecraft:light_blue_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_BLUE_WOOL = create(key("light_blue_wool")); + + /** + * {@code minecraft:light_gray_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_BANNER = create(key("light_gray_banner")); + + /** + * {@code minecraft:light_gray_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_BED = create(key("light_gray_bed")); + + /** + * {@code minecraft:light_gray_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_BUNDLE = create(key("light_gray_bundle")); + + /** + * {@code minecraft:light_gray_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CANDLE = create(key("light_gray_candle")); + + /** + * {@code minecraft:light_gray_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CARPET = create(key("light_gray_carpet")); + + /** + * {@code minecraft:light_gray_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CONCRETE = create(key("light_gray_concrete")); + + /** + * {@code minecraft:light_gray_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_CONCRETE_POWDER = create(key("light_gray_concrete_powder")); + + /** + * {@code minecraft:light_gray_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_DYE = create(key("light_gray_dye")); + + /** + * {@code minecraft:light_gray_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_GLAZED_TERRACOTTA = create(key("light_gray_glazed_terracotta")); + + /** + * {@code minecraft:light_gray_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_SHULKER_BOX = create(key("light_gray_shulker_box")); + + /** + * {@code minecraft:light_gray_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_STAINED_GLASS = create(key("light_gray_stained_glass")); + + /** + * {@code minecraft:light_gray_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_STAINED_GLASS_PANE = create(key("light_gray_stained_glass_pane")); + + /** + * {@code minecraft:light_gray_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_TERRACOTTA = create(key("light_gray_terracotta")); + + /** + * {@code minecraft:light_gray_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_GRAY_WOOL = create(key("light_gray_wool")); + + /** + * {@code minecraft:light_weighted_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHT_WEIGHTED_PRESSURE_PLATE = create(key("light_weighted_pressure_plate")); + + /** + * {@code minecraft:lightning_rod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_ROD = create(key("lightning_rod")); + + /** + * {@code minecraft:lilac} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILAC = create(key("lilac")); + + /** + * {@code minecraft:lily_of_the_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILY_OF_THE_VALLEY = create(key("lily_of_the_valley")); + + /** + * {@code minecraft:lily_pad} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LILY_PAD = create(key("lily_pad")); + + /** + * {@code minecraft:lime_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_BANNER = create(key("lime_banner")); + + /** + * {@code minecraft:lime_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_BED = create(key("lime_bed")); + + /** + * {@code minecraft:lime_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_BUNDLE = create(key("lime_bundle")); + + /** + * {@code minecraft:lime_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CANDLE = create(key("lime_candle")); + + /** + * {@code minecraft:lime_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CARPET = create(key("lime_carpet")); + + /** + * {@code minecraft:lime_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CONCRETE = create(key("lime_concrete")); + + /** + * {@code minecraft:lime_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_CONCRETE_POWDER = create(key("lime_concrete_powder")); + + /** + * {@code minecraft:lime_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_DYE = create(key("lime_dye")); + + /** + * {@code minecraft:lime_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_GLAZED_TERRACOTTA = create(key("lime_glazed_terracotta")); + + /** + * {@code minecraft:lime_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_SHULKER_BOX = create(key("lime_shulker_box")); + + /** + * {@code minecraft:lime_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_STAINED_GLASS = create(key("lime_stained_glass")); + + /** + * {@code minecraft:lime_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_STAINED_GLASS_PANE = create(key("lime_stained_glass_pane")); + + /** + * {@code minecraft:lime_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_TERRACOTTA = create(key("lime_terracotta")); + + /** + * {@code minecraft:lime_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIME_WOOL = create(key("lime_wool")); + + /** + * {@code minecraft:lingering_potion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LINGERING_POTION = create(key("lingering_potion")); + + /** + * {@code minecraft:llama_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LLAMA_SPAWN_EGG = create(key("llama_spawn_egg")); + + /** + * {@code minecraft:lodestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LODESTONE = create(key("lodestone")); + + /** + * {@code minecraft:loom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOOM = create(key("loom")); + + /** + * {@code minecraft:mace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MACE = create(key("mace")); + + /** + * {@code minecraft:magenta_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_BANNER = create(key("magenta_banner")); + + /** + * {@code minecraft:magenta_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_BED = create(key("magenta_bed")); + + /** + * {@code minecraft:magenta_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_BUNDLE = create(key("magenta_bundle")); + + /** + * {@code minecraft:magenta_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CANDLE = create(key("magenta_candle")); + + /** + * {@code minecraft:magenta_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CARPET = create(key("magenta_carpet")); + + /** + * {@code minecraft:magenta_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CONCRETE = create(key("magenta_concrete")); + + /** + * {@code minecraft:magenta_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_CONCRETE_POWDER = create(key("magenta_concrete_powder")); + + /** + * {@code minecraft:magenta_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_DYE = create(key("magenta_dye")); + + /** + * {@code minecraft:magenta_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_GLAZED_TERRACOTTA = create(key("magenta_glazed_terracotta")); + + /** + * {@code minecraft:magenta_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_SHULKER_BOX = create(key("magenta_shulker_box")); + + /** + * {@code minecraft:magenta_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_STAINED_GLASS = create(key("magenta_stained_glass")); + + /** + * {@code minecraft:magenta_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_STAINED_GLASS_PANE = create(key("magenta_stained_glass_pane")); + + /** + * {@code minecraft:magenta_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_TERRACOTTA = create(key("magenta_terracotta")); + + /** + * {@code minecraft:magenta_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGENTA_WOOL = create(key("magenta_wool")); + + /** + * {@code minecraft:magma_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGMA_BLOCK = create(key("magma_block")); + + /** + * {@code minecraft:magma_cream} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGMA_CREAM = create(key("magma_cream")); + + /** + * {@code minecraft:magma_cube_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGMA_CUBE_SPAWN_EGG = create(key("magma_cube_spawn_egg")); + + /** + * {@code minecraft:mangrove_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_BOAT = create(key("mangrove_boat")); + + /** + * {@code minecraft:mangrove_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_BUTTON = create(key("mangrove_button")); + + /** + * {@code minecraft:mangrove_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_CHEST_BOAT = create(key("mangrove_chest_boat")); + + /** + * {@code minecraft:mangrove_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_DOOR = create(key("mangrove_door")); + + /** + * {@code minecraft:mangrove_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_FENCE = create(key("mangrove_fence")); + + /** + * {@code minecraft:mangrove_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_FENCE_GATE = create(key("mangrove_fence_gate")); + + /** + * {@code minecraft:mangrove_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_HANGING_SIGN = create(key("mangrove_hanging_sign")); + + /** + * {@code minecraft:mangrove_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_LEAVES = create(key("mangrove_leaves")); + + /** + * {@code minecraft:mangrove_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_LOG = create(key("mangrove_log")); + + /** + * {@code minecraft:mangrove_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PLANKS = create(key("mangrove_planks")); + + /** + * {@code minecraft:mangrove_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PRESSURE_PLATE = create(key("mangrove_pressure_plate")); + + /** + * {@code minecraft:mangrove_propagule} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_PROPAGULE = create(key("mangrove_propagule")); + + /** + * {@code minecraft:mangrove_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_ROOTS = create(key("mangrove_roots")); + + /** + * {@code minecraft:mangrove_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SIGN = create(key("mangrove_sign")); + + /** + * {@code minecraft:mangrove_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SLAB = create(key("mangrove_slab")); + + /** + * {@code minecraft:mangrove_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_STAIRS = create(key("mangrove_stairs")); + + /** + * {@code minecraft:mangrove_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_TRAPDOOR = create(key("mangrove_trapdoor")); + + /** + * {@code minecraft:mangrove_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_WOOD = create(key("mangrove_wood")); + + /** + * {@code minecraft:map} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAP = create(key("map")); + + /** + * {@code minecraft:medium_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MEDIUM_AMETHYST_BUD = create(key("medium_amethyst_bud")); + + /** + * {@code minecraft:melon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELON = create(key("melon")); + + /** + * {@code minecraft:melon_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELON_SEEDS = create(key("melon_seeds")); + + /** + * {@code minecraft:melon_slice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELON_SLICE = create(key("melon_slice")); + + /** + * {@code minecraft:milk_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MILK_BUCKET = create(key("milk_bucket")); + + /** + * {@code minecraft:minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINECART = create(key("minecart")); + + /** + * {@code minecraft:miner_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINER_POTTERY_SHERD = create(key("miner_pottery_sherd")); + + /** + * {@code minecraft:mojang_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOJANG_BANNER_PATTERN = create(key("mojang_banner_pattern")); + + /** + * {@code minecraft:mooshroom_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOOSHROOM_SPAWN_EGG = create(key("mooshroom_spawn_egg")); + + /** + * {@code minecraft:moss_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSS_BLOCK = create(key("moss_block")); + + /** + * {@code minecraft:moss_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSS_CARPET = create(key("moss_carpet")); + + /** + * {@code minecraft:mossy_cobblestone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE = create(key("mossy_cobblestone")); + + /** + * {@code minecraft:mossy_cobblestone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_SLAB = create(key("mossy_cobblestone_slab")); + + /** + * {@code minecraft:mossy_cobblestone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_STAIRS = create(key("mossy_cobblestone_stairs")); + + /** + * {@code minecraft:mossy_cobblestone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_COBBLESTONE_WALL = create(key("mossy_cobblestone_wall")); + + /** + * {@code minecraft:mossy_stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_SLAB = create(key("mossy_stone_brick_slab")); + + /** + * {@code minecraft:mossy_stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_STAIRS = create(key("mossy_stone_brick_stairs")); + + /** + * {@code minecraft:mossy_stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICK_WALL = create(key("mossy_stone_brick_wall")); + + /** + * {@code minecraft:mossy_stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOSSY_STONE_BRICKS = create(key("mossy_stone_bricks")); + + /** + * {@code minecraft:mourner_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOURNER_POTTERY_SHERD = create(key("mourner_pottery_sherd")); + + /** + * {@code minecraft:mud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD = create(key("mud")); + + /** + * {@code minecraft:mud_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_SLAB = create(key("mud_brick_slab")); + + /** + * {@code minecraft:mud_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_STAIRS = create(key("mud_brick_stairs")); + + /** + * {@code minecraft:mud_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICK_WALL = create(key("mud_brick_wall")); + + /** + * {@code minecraft:mud_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUD_BRICKS = create(key("mud_bricks")); + + /** + * {@code minecraft:muddy_mangrove_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUDDY_MANGROVE_ROOTS = create(key("muddy_mangrove_roots")); + + /** + * {@code minecraft:mule_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MULE_SPAWN_EGG = create(key("mule_spawn_egg")); + + /** + * {@code minecraft:mushroom_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSHROOM_STEM = create(key("mushroom_stem")); + + /** + * {@code minecraft:mushroom_stew} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSHROOM_STEW = create(key("mushroom_stew")); + + /** + * {@code minecraft:music_disc_11} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_11 = create(key("music_disc_11")); + + /** + * {@code minecraft:music_disc_13} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_13 = create(key("music_disc_13")); + + /** + * {@code minecraft:music_disc_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_BLOCKS = create(key("music_disc_blocks")); + + /** + * {@code minecraft:music_disc_cat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CAT = create(key("music_disc_cat")); + + /** + * {@code minecraft:music_disc_chirp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CHIRP = create(key("music_disc_chirp")); + + /** + * {@code minecraft:music_disc_creator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CREATOR = create(key("music_disc_creator")); + + /** + * {@code minecraft:music_disc_creator_music_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CREATOR_MUSIC_BOX = create(key("music_disc_creator_music_box")); + + /** + * {@code minecraft:music_disc_far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_FAR = create(key("music_disc_far")); + + /** + * {@code minecraft:music_disc_mall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_MALL = create(key("music_disc_mall")); + + /** + * {@code minecraft:music_disc_mellohi} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_MELLOHI = create(key("music_disc_mellohi")); + + /** + * {@code minecraft:music_disc_otherside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_OTHERSIDE = create(key("music_disc_otherside")); + + /** + * {@code minecraft:music_disc_pigstep} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_PIGSTEP = create(key("music_disc_pigstep")); + + /** + * {@code minecraft:music_disc_precipice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_PRECIPICE = create(key("music_disc_precipice")); + + /** + * {@code minecraft:music_disc_relic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_RELIC = create(key("music_disc_relic")); + + /** + * {@code minecraft:music_disc_stal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_STAL = create(key("music_disc_stal")); + + /** + * {@code minecraft:music_disc_strad} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_STRAD = create(key("music_disc_strad")); + + /** + * {@code minecraft:music_disc_wait} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_WAIT = create(key("music_disc_wait")); + + /** + * {@code minecraft:music_disc_ward} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_WARD = create(key("music_disc_ward")); + + /** + * {@code minecraft:mutton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUTTON = create(key("mutton")); + + /** + * {@code minecraft:mycelium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MYCELIUM = create(key("mycelium")); + + /** + * {@code minecraft:name_tag} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NAME_TAG = create(key("name_tag")); + + /** + * {@code minecraft:nautilus_shell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NAUTILUS_SHELL = create(key("nautilus_shell")); + + /** + * {@code minecraft:nether_brick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK = create(key("nether_brick")); + + /** + * {@code minecraft:nether_brick_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_FENCE = create(key("nether_brick_fence")); + + /** + * {@code minecraft:nether_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_SLAB = create(key("nether_brick_slab")); + + /** + * {@code minecraft:nether_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_STAIRS = create(key("nether_brick_stairs")); + + /** + * {@code minecraft:nether_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICK_WALL = create(key("nether_brick_wall")); + + /** + * {@code minecraft:nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_BRICKS = create(key("nether_bricks")); + + /** + * {@code minecraft:nether_gold_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_GOLD_ORE = create(key("nether_gold_ore")); + + /** + * {@code minecraft:nether_quartz_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_QUARTZ_ORE = create(key("nether_quartz_ore")); + + /** + * {@code minecraft:nether_sprouts} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_SPROUTS = create(key("nether_sprouts")); + + /** + * {@code minecraft:nether_star} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_STAR = create(key("nether_star")); + + /** + * {@code minecraft:nether_wart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WART = create(key("nether_wart")); + + /** + * {@code minecraft:nether_wart_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WART_BLOCK = create(key("nether_wart_block")); + + /** + * {@code minecraft:netherite_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_AXE = create(key("netherite_axe")); + + /** + * {@code minecraft:netherite_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_BLOCK = create(key("netherite_block")); + + /** + * {@code minecraft:netherite_boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_BOOTS = create(key("netherite_boots")); + + /** + * {@code minecraft:netherite_chestplate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_CHESTPLATE = create(key("netherite_chestplate")); + + /** + * {@code minecraft:netherite_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_HELMET = create(key("netherite_helmet")); + + /** + * {@code minecraft:netherite_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_HOE = create(key("netherite_hoe")); + + /** + * {@code minecraft:netherite_ingot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_INGOT = create(key("netherite_ingot")); + + /** + * {@code minecraft:netherite_leggings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_LEGGINGS = create(key("netherite_leggings")); + + /** + * {@code minecraft:netherite_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_PICKAXE = create(key("netherite_pickaxe")); + + /** + * {@code minecraft:netherite_scrap} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_SCRAP = create(key("netherite_scrap")); + + /** + * {@code minecraft:netherite_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_SHOVEL = create(key("netherite_shovel")); + + /** + * {@code minecraft:netherite_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_SWORD = create(key("netherite_sword")); + + /** + * {@code minecraft:netherite_upgrade_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE_UPGRADE_SMITHING_TEMPLATE = create(key("netherite_upgrade_smithing_template")); + + /** + * {@code minecraft:netherrack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERRACK = create(key("netherrack")); + + /** + * {@code minecraft:note_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NOTE_BLOCK = create(key("note_block")); + + /** + * {@code minecraft:oak_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_BOAT = create(key("oak_boat")); + + /** + * {@code minecraft:oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_BUTTON = create(key("oak_button")); + + /** + * {@code minecraft:oak_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_CHEST_BOAT = create(key("oak_chest_boat")); + + /** + * {@code minecraft:oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_DOOR = create(key("oak_door")); + + /** + * {@code minecraft:oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_FENCE = create(key("oak_fence")); + + /** + * {@code minecraft:oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_FENCE_GATE = create(key("oak_fence_gate")); + + /** + * {@code minecraft:oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_HANGING_SIGN = create(key("oak_hanging_sign")); + + /** + * {@code minecraft:oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_LEAVES = create(key("oak_leaves")); + + /** + * {@code minecraft:oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_LOG = create(key("oak_log")); + + /** + * {@code minecraft:oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_PLANKS = create(key("oak_planks")); + + /** + * {@code minecraft:oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_PRESSURE_PLATE = create(key("oak_pressure_plate")); + + /** + * {@code minecraft:oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SAPLING = create(key("oak_sapling")); + + /** + * {@code minecraft:oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SIGN = create(key("oak_sign")); + + /** + * {@code minecraft:oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_SLAB = create(key("oak_slab")); + + /** + * {@code minecraft:oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_STAIRS = create(key("oak_stairs")); + + /** + * {@code minecraft:oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_TRAPDOOR = create(key("oak_trapdoor")); + + /** + * {@code minecraft:oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OAK_WOOD = create(key("oak_wood")); + + /** + * {@code minecraft:observer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OBSERVER = create(key("observer")); + + /** + * {@code minecraft:obsidian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OBSIDIAN = create(key("obsidian")); + + /** + * {@code minecraft:ocelot_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCELOT_SPAWN_EGG = create(key("ocelot_spawn_egg")); + + /** + * {@code minecraft:ochre_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCHRE_FROGLIGHT = create(key("ochre_froglight")); + + /** + * {@code minecraft:ominous_bottle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OMINOUS_BOTTLE = create(key("ominous_bottle")); + + /** + * {@code minecraft:ominous_trial_key} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OMINOUS_TRIAL_KEY = create(key("ominous_trial_key")); + + /** + * {@code minecraft:open_eyeblossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OPEN_EYEBLOSSOM = create(key("open_eyeblossom")); + + /** + * {@code minecraft:orange_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_BANNER = create(key("orange_banner")); + + /** + * {@code minecraft:orange_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_BED = create(key("orange_bed")); + + /** + * {@code minecraft:orange_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_BUNDLE = create(key("orange_bundle")); + + /** + * {@code minecraft:orange_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CANDLE = create(key("orange_candle")); + + /** + * {@code minecraft:orange_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CARPET = create(key("orange_carpet")); + + /** + * {@code minecraft:orange_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CONCRETE = create(key("orange_concrete")); + + /** + * {@code minecraft:orange_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_CONCRETE_POWDER = create(key("orange_concrete_powder")); + + /** + * {@code minecraft:orange_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_DYE = create(key("orange_dye")); + + /** + * {@code minecraft:orange_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_GLAZED_TERRACOTTA = create(key("orange_glazed_terracotta")); + + /** + * {@code minecraft:orange_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_SHULKER_BOX = create(key("orange_shulker_box")); + + /** + * {@code minecraft:orange_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_STAINED_GLASS = create(key("orange_stained_glass")); + + /** + * {@code minecraft:orange_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_STAINED_GLASS_PANE = create(key("orange_stained_glass_pane")); + + /** + * {@code minecraft:orange_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_TERRACOTTA = create(key("orange_terracotta")); + + /** + * {@code minecraft:orange_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_TULIP = create(key("orange_tulip")); + + /** + * {@code minecraft:orange_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORANGE_WOOL = create(key("orange_wool")); + + /** + * {@code minecraft:oxeye_daisy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXEYE_DAISY = create(key("oxeye_daisy")); + + /** + * {@code minecraft:oxidized_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CHISELED_COPPER = create(key("oxidized_chiseled_copper")); + + /** + * {@code minecraft:oxidized_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER = create(key("oxidized_copper")); + + /** + * {@code minecraft:oxidized_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_BULB = create(key("oxidized_copper_bulb")); + + /** + * {@code minecraft:oxidized_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_DOOR = create(key("oxidized_copper_door")); + + /** + * {@code minecraft:oxidized_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_GRATE = create(key("oxidized_copper_grate")); + + /** + * {@code minecraft:oxidized_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_COPPER_TRAPDOOR = create(key("oxidized_copper_trapdoor")); + + /** + * {@code minecraft:oxidized_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER = create(key("oxidized_cut_copper")); + + /** + * {@code minecraft:oxidized_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER_SLAB = create(key("oxidized_cut_copper_slab")); + + /** + * {@code minecraft:oxidized_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OXIDIZED_CUT_COPPER_STAIRS = create(key("oxidized_cut_copper_stairs")); + + /** + * {@code minecraft:packed_ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PACKED_ICE = create(key("packed_ice")); + + /** + * {@code minecraft:packed_mud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PACKED_MUD = create(key("packed_mud")); + + /** + * {@code minecraft:painting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PAINTING = create(key("painting")); + + /** + * {@code minecraft:pale_hanging_moss} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_HANGING_MOSS = create(key("pale_hanging_moss")); + + /** + * {@code minecraft:pale_moss_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_MOSS_BLOCK = create(key("pale_moss_block")); + + /** + * {@code minecraft:pale_moss_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_MOSS_CARPET = create(key("pale_moss_carpet")); + + /** + * {@code minecraft:pale_oak_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_BOAT = create(key("pale_oak_boat")); + + /** + * {@code minecraft:pale_oak_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_BUTTON = create(key("pale_oak_button")); + + /** + * {@code minecraft:pale_oak_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_CHEST_BOAT = create(key("pale_oak_chest_boat")); + + /** + * {@code minecraft:pale_oak_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_DOOR = create(key("pale_oak_door")); + + /** + * {@code minecraft:pale_oak_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_FENCE = create(key("pale_oak_fence")); + + /** + * {@code minecraft:pale_oak_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_FENCE_GATE = create(key("pale_oak_fence_gate")); + + /** + * {@code minecraft:pale_oak_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_HANGING_SIGN = create(key("pale_oak_hanging_sign")); + + /** + * {@code minecraft:pale_oak_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_LEAVES = create(key("pale_oak_leaves")); + + /** + * {@code minecraft:pale_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_LOG = create(key("pale_oak_log")); + + /** + * {@code minecraft:pale_oak_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_PLANKS = create(key("pale_oak_planks")); + + /** + * {@code minecraft:pale_oak_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_PRESSURE_PLATE = create(key("pale_oak_pressure_plate")); + + /** + * {@code minecraft:pale_oak_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SAPLING = create(key("pale_oak_sapling")); + + /** + * {@code minecraft:pale_oak_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SIGN = create(key("pale_oak_sign")); + + /** + * {@code minecraft:pale_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_SLAB = create(key("pale_oak_slab")); + + /** + * {@code minecraft:pale_oak_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_STAIRS = create(key("pale_oak_stairs")); + + /** + * {@code minecraft:pale_oak_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_TRAPDOOR = create(key("pale_oak_trapdoor")); + + /** + * {@code minecraft:pale_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE_OAK_WOOD = create(key("pale_oak_wood")); + + /** + * {@code minecraft:panda_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PANDA_SPAWN_EGG = create(key("panda_spawn_egg")); + + /** + * {@code minecraft:paper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PAPER = create(key("paper")); + + /** + * {@code minecraft:parrot_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PARROT_SPAWN_EGG = create(key("parrot_spawn_egg")); + + /** + * {@code minecraft:pearlescent_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PEARLESCENT_FROGLIGHT = create(key("pearlescent_froglight")); + + /** + * {@code minecraft:peony} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PEONY = create(key("peony")); + + /** + * {@code minecraft:petrified_oak_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PETRIFIED_OAK_SLAB = create(key("petrified_oak_slab")); + + /** + * {@code minecraft:phantom_membrane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PHANTOM_MEMBRANE = create(key("phantom_membrane")); + + /** + * {@code minecraft:phantom_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PHANTOM_SPAWN_EGG = create(key("phantom_spawn_egg")); + + /** + * {@code minecraft:pig_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIG_SPAWN_EGG = create(key("pig_spawn_egg")); + + /** + * {@code minecraft:piglin_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_BANNER_PATTERN = create(key("piglin_banner_pattern")); + + /** + * {@code minecraft:piglin_brute_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_BRUTE_SPAWN_EGG = create(key("piglin_brute_spawn_egg")); + + /** + * {@code minecraft:piglin_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_HEAD = create(key("piglin_head")); + + /** + * {@code minecraft:piglin_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGLIN_SPAWN_EGG = create(key("piglin_spawn_egg")); + + /** + * {@code minecraft:pillager_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PILLAGER_SPAWN_EGG = create(key("pillager_spawn_egg")); + + /** + * {@code minecraft:pink_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_BANNER = create(key("pink_banner")); + + /** + * {@code minecraft:pink_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_BED = create(key("pink_bed")); + + /** + * {@code minecraft:pink_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_BUNDLE = create(key("pink_bundle")); + + /** + * {@code minecraft:pink_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CANDLE = create(key("pink_candle")); + + /** + * {@code minecraft:pink_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CARPET = create(key("pink_carpet")); + + /** + * {@code minecraft:pink_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CONCRETE = create(key("pink_concrete")); + + /** + * {@code minecraft:pink_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_CONCRETE_POWDER = create(key("pink_concrete_powder")); + + /** + * {@code minecraft:pink_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_DYE = create(key("pink_dye")); + + /** + * {@code minecraft:pink_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_GLAZED_TERRACOTTA = create(key("pink_glazed_terracotta")); + + /** + * {@code minecraft:pink_petals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_PETALS = create(key("pink_petals")); + + /** + * {@code minecraft:pink_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_SHULKER_BOX = create(key("pink_shulker_box")); + + /** + * {@code minecraft:pink_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_STAINED_GLASS = create(key("pink_stained_glass")); + + /** + * {@code minecraft:pink_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_STAINED_GLASS_PANE = create(key("pink_stained_glass_pane")); + + /** + * {@code minecraft:pink_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_TERRACOTTA = create(key("pink_terracotta")); + + /** + * {@code minecraft:pink_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_TULIP = create(key("pink_tulip")); + + /** + * {@code minecraft:pink_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PINK_WOOL = create(key("pink_wool")); + + /** + * {@code minecraft:piston} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PISTON = create(key("piston")); + + /** + * {@code minecraft:pitcher_plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PITCHER_PLANT = create(key("pitcher_plant")); + + /** + * {@code minecraft:pitcher_pod} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PITCHER_POD = create(key("pitcher_pod")); + + /** + * {@code minecraft:player_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_HEAD = create(key("player_head")); + + /** + * {@code minecraft:plenty_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLENTY_POTTERY_SHERD = create(key("plenty_pottery_sherd")); + + /** + * {@code minecraft:podzol} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PODZOL = create(key("podzol")); + + /** + * {@code minecraft:pointed_dripstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POINTED_DRIPSTONE = create(key("pointed_dripstone")); + + /** + * {@code minecraft:poisonous_potato} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POISONOUS_POTATO = create(key("poisonous_potato")); + + /** + * {@code minecraft:polar_bear_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLAR_BEAR_SPAWN_EGG = create(key("polar_bear_spawn_egg")); + + /** + * {@code minecraft:polished_andesite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE = create(key("polished_andesite")); + + /** + * {@code minecraft:polished_andesite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE_SLAB = create(key("polished_andesite_slab")); + + /** + * {@code minecraft:polished_andesite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_ANDESITE_STAIRS = create(key("polished_andesite_stairs")); + + /** + * {@code minecraft:polished_basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BASALT = create(key("polished_basalt")); + + /** + * {@code minecraft:polished_blackstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE = create(key("polished_blackstone")); + + /** + * {@code minecraft:polished_blackstone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_SLAB = create(key("polished_blackstone_brick_slab")); + + /** + * {@code minecraft:polished_blackstone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_STAIRS = create(key("polished_blackstone_brick_stairs")); + + /** + * {@code minecraft:polished_blackstone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICK_WALL = create(key("polished_blackstone_brick_wall")); + + /** + * {@code minecraft:polished_blackstone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BRICKS = create(key("polished_blackstone_bricks")); + + /** + * {@code minecraft:polished_blackstone_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_BUTTON = create(key("polished_blackstone_button")); + + /** + * {@code minecraft:polished_blackstone_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_PRESSURE_PLATE = create(key("polished_blackstone_pressure_plate")); + + /** + * {@code minecraft:polished_blackstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_SLAB = create(key("polished_blackstone_slab")); + + /** + * {@code minecraft:polished_blackstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_STAIRS = create(key("polished_blackstone_stairs")); + + /** + * {@code minecraft:polished_blackstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_BLACKSTONE_WALL = create(key("polished_blackstone_wall")); + + /** + * {@code minecraft:polished_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE = create(key("polished_deepslate")); + + /** + * {@code minecraft:polished_deepslate_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_SLAB = create(key("polished_deepslate_slab")); + + /** + * {@code minecraft:polished_deepslate_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_STAIRS = create(key("polished_deepslate_stairs")); + + /** + * {@code minecraft:polished_deepslate_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DEEPSLATE_WALL = create(key("polished_deepslate_wall")); + + /** + * {@code minecraft:polished_diorite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE = create(key("polished_diorite")); + + /** + * {@code minecraft:polished_diorite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE_SLAB = create(key("polished_diorite_slab")); + + /** + * {@code minecraft:polished_diorite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_DIORITE_STAIRS = create(key("polished_diorite_stairs")); + + /** + * {@code minecraft:polished_granite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE = create(key("polished_granite")); + + /** + * {@code minecraft:polished_granite_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE_SLAB = create(key("polished_granite_slab")); + + /** + * {@code minecraft:polished_granite_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_GRANITE_STAIRS = create(key("polished_granite_stairs")); + + /** + * {@code minecraft:polished_tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF = create(key("polished_tuff")); + + /** + * {@code minecraft:polished_tuff_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_SLAB = create(key("polished_tuff_slab")); + + /** + * {@code minecraft:polished_tuff_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_STAIRS = create(key("polished_tuff_stairs")); + + /** + * {@code minecraft:polished_tuff_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POLISHED_TUFF_WALL = create(key("polished_tuff_wall")); + + /** + * {@code minecraft:popped_chorus_fruit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POPPED_CHORUS_FRUIT = create(key("popped_chorus_fruit")); + + /** + * {@code minecraft:poppy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POPPY = create(key("poppy")); + + /** + * {@code minecraft:porkchop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PORKCHOP = create(key("porkchop")); + + /** + * {@code minecraft:potato} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTATO = create(key("potato")); + + /** + * {@code minecraft:potion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POTION = create(key("potion")); + + /** + * {@code minecraft:powder_snow_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWDER_SNOW_BUCKET = create(key("powder_snow_bucket")); + + /** + * {@code minecraft:powered_rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWERED_RAIL = create(key("powered_rail")); + + /** + * {@code minecraft:prismarine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE = create(key("prismarine")); + + /** + * {@code minecraft:prismarine_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICK_SLAB = create(key("prismarine_brick_slab")); + + /** + * {@code minecraft:prismarine_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICK_STAIRS = create(key("prismarine_brick_stairs")); + + /** + * {@code minecraft:prismarine_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_BRICKS = create(key("prismarine_bricks")); + + /** + * {@code minecraft:prismarine_crystals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_CRYSTALS = create(key("prismarine_crystals")); + + /** + * {@code minecraft:prismarine_shard} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_SHARD = create(key("prismarine_shard")); + + /** + * {@code minecraft:prismarine_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_SLAB = create(key("prismarine_slab")); + + /** + * {@code minecraft:prismarine_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_STAIRS = create(key("prismarine_stairs")); + + /** + * {@code minecraft:prismarine_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRISMARINE_WALL = create(key("prismarine_wall")); + + /** + * {@code minecraft:prize_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRIZE_POTTERY_SHERD = create(key("prize_pottery_sherd")); + + /** + * {@code minecraft:pufferfish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUFFERFISH = create(key("pufferfish")); + + /** + * {@code minecraft:pufferfish_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUFFERFISH_BUCKET = create(key("pufferfish_bucket")); + + /** + * {@code minecraft:pufferfish_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUFFERFISH_SPAWN_EGG = create(key("pufferfish_spawn_egg")); + + /** + * {@code minecraft:pumpkin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUMPKIN = create(key("pumpkin")); + + /** + * {@code minecraft:pumpkin_pie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUMPKIN_PIE = create(key("pumpkin_pie")); + + /** + * {@code minecraft:pumpkin_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUMPKIN_SEEDS = create(key("pumpkin_seeds")); + + /** + * {@code minecraft:purple_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_BANNER = create(key("purple_banner")); + + /** + * {@code minecraft:purple_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_BED = create(key("purple_bed")); + + /** + * {@code minecraft:purple_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_BUNDLE = create(key("purple_bundle")); + + /** + * {@code minecraft:purple_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CANDLE = create(key("purple_candle")); + + /** + * {@code minecraft:purple_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CARPET = create(key("purple_carpet")); + + /** + * {@code minecraft:purple_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CONCRETE = create(key("purple_concrete")); + + /** + * {@code minecraft:purple_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_CONCRETE_POWDER = create(key("purple_concrete_powder")); + + /** + * {@code minecraft:purple_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_DYE = create(key("purple_dye")); + + /** + * {@code minecraft:purple_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_GLAZED_TERRACOTTA = create(key("purple_glazed_terracotta")); + + /** + * {@code minecraft:purple_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_SHULKER_BOX = create(key("purple_shulker_box")); + + /** + * {@code minecraft:purple_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_STAINED_GLASS = create(key("purple_stained_glass")); + + /** + * {@code minecraft:purple_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_STAINED_GLASS_PANE = create(key("purple_stained_glass_pane")); + + /** + * {@code minecraft:purple_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_TERRACOTTA = create(key("purple_terracotta")); + + /** + * {@code minecraft:purple_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPLE_WOOL = create(key("purple_wool")); + + /** + * {@code minecraft:purpur_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_BLOCK = create(key("purpur_block")); + + /** + * {@code minecraft:purpur_pillar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_PILLAR = create(key("purpur_pillar")); + + /** + * {@code minecraft:purpur_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_SLAB = create(key("purpur_slab")); + + /** + * {@code minecraft:purpur_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PURPUR_STAIRS = create(key("purpur_stairs")); + + /** + * {@code minecraft:quartz} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ = create(key("quartz")); + + /** + * {@code minecraft:quartz_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_BLOCK = create(key("quartz_block")); + + /** + * {@code minecraft:quartz_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_BRICKS = create(key("quartz_bricks")); + + /** + * {@code minecraft:quartz_pillar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_PILLAR = create(key("quartz_pillar")); + + /** + * {@code minecraft:quartz_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_SLAB = create(key("quartz_slab")); + + /** + * {@code minecraft:quartz_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ_STAIRS = create(key("quartz_stairs")); + + /** + * {@code minecraft:rabbit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RABBIT = create(key("rabbit")); + + /** + * {@code minecraft:rabbit_foot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RABBIT_FOOT = create(key("rabbit_foot")); + + /** + * {@code minecraft:rabbit_hide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RABBIT_HIDE = create(key("rabbit_hide")); + + /** + * {@code minecraft:rabbit_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RABBIT_SPAWN_EGG = create(key("rabbit_spawn_egg")); + + /** + * {@code minecraft:rabbit_stew} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RABBIT_STEW = create(key("rabbit_stew")); + + /** + * {@code minecraft:rail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAIL = create(key("rail")); + + /** + * {@code minecraft:raiser_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("raiser_armor_trim_smithing_template")); + + /** + * {@code minecraft:ravager_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAVAGER_SPAWN_EGG = create(key("ravager_spawn_egg")); + + /** + * {@code minecraft:raw_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_COPPER = create(key("raw_copper")); + + /** + * {@code minecraft:raw_copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_COPPER_BLOCK = create(key("raw_copper_block")); + + /** + * {@code minecraft:raw_gold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_GOLD = create(key("raw_gold")); + + /** + * {@code minecraft:raw_gold_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_GOLD_BLOCK = create(key("raw_gold_block")); + + /** + * {@code minecraft:raw_iron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_IRON = create(key("raw_iron")); + + /** + * {@code minecraft:raw_iron_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAW_IRON_BLOCK = create(key("raw_iron_block")); + + /** + * {@code minecraft:recovery_compass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RECOVERY_COMPASS = create(key("recovery_compass")); + + /** + * {@code minecraft:red_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_BANNER = create(key("red_banner")); + + /** + * {@code minecraft:red_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_BED = create(key("red_bed")); + + /** + * {@code minecraft:red_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_BUNDLE = create(key("red_bundle")); + + /** + * {@code minecraft:red_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CANDLE = create(key("red_candle")); + + /** + * {@code minecraft:red_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CARPET = create(key("red_carpet")); + + /** + * {@code minecraft:red_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CONCRETE = create(key("red_concrete")); + + /** + * {@code minecraft:red_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_CONCRETE_POWDER = create(key("red_concrete_powder")); + + /** + * {@code minecraft:red_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_DYE = create(key("red_dye")); + + /** + * {@code minecraft:red_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_GLAZED_TERRACOTTA = create(key("red_glazed_terracotta")); + + /** + * {@code minecraft:red_mushroom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_MUSHROOM = create(key("red_mushroom")); + + /** + * {@code minecraft:red_mushroom_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_MUSHROOM_BLOCK = create(key("red_mushroom_block")); + + /** + * {@code minecraft:red_nether_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_SLAB = create(key("red_nether_brick_slab")); + + /** + * {@code minecraft:red_nether_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_STAIRS = create(key("red_nether_brick_stairs")); + + /** + * {@code minecraft:red_nether_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICK_WALL = create(key("red_nether_brick_wall")); + + /** + * {@code minecraft:red_nether_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_NETHER_BRICKS = create(key("red_nether_bricks")); + + /** + * {@code minecraft:red_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SAND = create(key("red_sand")); + + /** + * {@code minecraft:red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE = create(key("red_sandstone")); + + /** + * {@code minecraft:red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_SLAB = create(key("red_sandstone_slab")); + + /** + * {@code minecraft:red_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_STAIRS = create(key("red_sandstone_stairs")); + + /** + * {@code minecraft:red_sandstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SANDSTONE_WALL = create(key("red_sandstone_wall")); + + /** + * {@code minecraft:red_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_SHULKER_BOX = create(key("red_shulker_box")); + + /** + * {@code minecraft:red_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_STAINED_GLASS = create(key("red_stained_glass")); + + /** + * {@code minecraft:red_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_STAINED_GLASS_PANE = create(key("red_stained_glass_pane")); + + /** + * {@code minecraft:red_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_TERRACOTTA = create(key("red_terracotta")); + + /** + * {@code minecraft:red_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_TULIP = create(key("red_tulip")); + + /** + * {@code minecraft:red_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_WOOL = create(key("red_wool")); + + /** + * {@code minecraft:redstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE = create(key("redstone")); + + /** + * {@code minecraft:redstone_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_BLOCK = create(key("redstone_block")); + + /** + * {@code minecraft:redstone_lamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_LAMP = create(key("redstone_lamp")); + + /** + * {@code minecraft:redstone_ore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_ORE = create(key("redstone_ore")); + + /** + * {@code minecraft:redstone_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE_TORCH = create(key("redstone_torch")); + + /** + * {@code minecraft:reinforced_deepslate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REINFORCED_DEEPSLATE = create(key("reinforced_deepslate")); + + /** + * {@code minecraft:repeater} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REPEATER = create(key("repeater")); + + /** + * {@code minecraft:repeating_command_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REPEATING_COMMAND_BLOCK = create(key("repeating_command_block")); + + /** + * {@code minecraft:resin_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BLOCK = create(key("resin_block")); + + /** + * {@code minecraft:resin_brick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK = create(key("resin_brick")); + + /** + * {@code minecraft:resin_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_SLAB = create(key("resin_brick_slab")); + + /** + * {@code minecraft:resin_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_STAIRS = create(key("resin_brick_stairs")); + + /** + * {@code minecraft:resin_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICK_WALL = create(key("resin_brick_wall")); + + /** + * {@code minecraft:resin_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_BRICKS = create(key("resin_bricks")); + + /** + * {@code minecraft:resin_clump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN_CLUMP = create(key("resin_clump")); + + /** + * {@code minecraft:respawn_anchor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESPAWN_ANCHOR = create(key("respawn_anchor")); + + /** + * {@code minecraft:rib_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIB_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("rib_armor_trim_smithing_template")); + + /** + * {@code minecraft:rooted_dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ROOTED_DIRT = create(key("rooted_dirt")); + + /** + * {@code minecraft:rose_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ROSE_BUSH = create(key("rose_bush")); + + /** + * {@code minecraft:rotten_flesh} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ROTTEN_FLESH = create(key("rotten_flesh")); + + /** + * {@code minecraft:saddle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SADDLE = create(key("saddle")); + + /** + * {@code minecraft:salmon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SALMON = create(key("salmon")); + + /** + * {@code minecraft:salmon_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SALMON_BUCKET = create(key("salmon_bucket")); + + /** + * {@code minecraft:salmon_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SALMON_SPAWN_EGG = create(key("salmon_spawn_egg")); + + /** + * {@code minecraft:sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAND = create(key("sand")); + + /** + * {@code minecraft:sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE = create(key("sandstone")); + + /** + * {@code minecraft:sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_SLAB = create(key("sandstone_slab")); + + /** + * {@code minecraft:sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_STAIRS = create(key("sandstone_stairs")); + + /** + * {@code minecraft:sandstone_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SANDSTONE_WALL = create(key("sandstone_wall")); + + /** + * {@code minecraft:scaffolding} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCAFFOLDING = create(key("scaffolding")); + + /** + * {@code minecraft:scrape_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCRAPE_POTTERY_SHERD = create(key("scrape_pottery_sherd")); + + /** + * {@code minecraft:sculk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK = create(key("sculk")); + + /** + * {@code minecraft:sculk_catalyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_CATALYST = create(key("sculk_catalyst")); + + /** + * {@code minecraft:sculk_sensor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SENSOR = create(key("sculk_sensor")); + + /** + * {@code minecraft:sculk_shrieker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SHRIEKER = create(key("sculk_shrieker")); + + /** + * {@code minecraft:sculk_vein} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_VEIN = create(key("sculk_vein")); + + /** + * {@code minecraft:sea_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEA_LANTERN = create(key("sea_lantern")); + + /** + * {@code minecraft:sea_pickle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEA_PICKLE = create(key("sea_pickle")); + + /** + * {@code minecraft:seagrass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEAGRASS = create(key("seagrass")); + + /** + * {@code minecraft:sentry_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("sentry_armor_trim_smithing_template")); + + /** + * {@code minecraft:shaper_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("shaper_armor_trim_smithing_template")); + + /** + * {@code minecraft:sheaf_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEAF_POTTERY_SHERD = create(key("sheaf_pottery_sherd")); + + /** + * {@code minecraft:shears} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEARS = create(key("shears")); + + /** + * {@code minecraft:sheep_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEEP_SPAWN_EGG = create(key("sheep_spawn_egg")); + + /** + * {@code minecraft:shelter_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHELTER_POTTERY_SHERD = create(key("shelter_pottery_sherd")); + + /** + * {@code minecraft:shield} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHIELD = create(key("shield")); + + /** + * {@code minecraft:short_grass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHORT_GRASS = create(key("short_grass")); + + /** + * {@code minecraft:shroomlight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHROOMLIGHT = create(key("shroomlight")); + + /** + * {@code minecraft:shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHULKER_BOX = create(key("shulker_box")); + + /** + * {@code minecraft:shulker_shell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHULKER_SHELL = create(key("shulker_shell")); + + /** + * {@code minecraft:shulker_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHULKER_SPAWN_EGG = create(key("shulker_spawn_egg")); + + /** + * {@code minecraft:silence_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("silence_armor_trim_smithing_template")); + + /** + * {@code minecraft:silverfish_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILVERFISH_SPAWN_EGG = create(key("silverfish_spawn_egg")); + + /** + * {@code minecraft:skeleton_horse_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON_HORSE_SPAWN_EGG = create(key("skeleton_horse_spawn_egg")); + + /** + * {@code minecraft:skeleton_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON_SKULL = create(key("skeleton_skull")); + + /** + * {@code minecraft:skeleton_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON_SPAWN_EGG = create(key("skeleton_spawn_egg")); + + /** + * {@code minecraft:skull_banner_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKULL_BANNER_PATTERN = create(key("skull_banner_pattern")); + + /** + * {@code minecraft:skull_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKULL_POTTERY_SHERD = create(key("skull_pottery_sherd")); + + /** + * {@code minecraft:slime_ball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLIME_BALL = create(key("slime_ball")); + + /** + * {@code minecraft:slime_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLIME_BLOCK = create(key("slime_block")); + + /** + * {@code minecraft:slime_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLIME_SPAWN_EGG = create(key("slime_spawn_egg")); + + /** + * {@code minecraft:small_amethyst_bud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_AMETHYST_BUD = create(key("small_amethyst_bud")); + + /** + * {@code minecraft:small_dripleaf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_DRIPLEAF = create(key("small_dripleaf")); + + /** + * {@code minecraft:smithing_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMITHING_TABLE = create(key("smithing_table")); + + /** + * {@code minecraft:smoker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOKER = create(key("smoker")); + + /** + * {@code minecraft:smooth_basalt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_BASALT = create(key("smooth_basalt")); + + /** + * {@code minecraft:smooth_quartz} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ = create(key("smooth_quartz")); + + /** + * {@code minecraft:smooth_quartz_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ_SLAB = create(key("smooth_quartz_slab")); + + /** + * {@code minecraft:smooth_quartz_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_QUARTZ_STAIRS = create(key("smooth_quartz_stairs")); + + /** + * {@code minecraft:smooth_red_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE = create(key("smooth_red_sandstone")); + + /** + * {@code minecraft:smooth_red_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE_SLAB = create(key("smooth_red_sandstone_slab")); + + /** + * {@code minecraft:smooth_red_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_RED_SANDSTONE_STAIRS = create(key("smooth_red_sandstone_stairs")); + + /** + * {@code minecraft:smooth_sandstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE = create(key("smooth_sandstone")); + + /** + * {@code minecraft:smooth_sandstone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE_SLAB = create(key("smooth_sandstone_slab")); + + /** + * {@code minecraft:smooth_sandstone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_SANDSTONE_STAIRS = create(key("smooth_sandstone_stairs")); + + /** + * {@code minecraft:smooth_stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_STONE = create(key("smooth_stone")); + + /** + * {@code minecraft:smooth_stone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOOTH_STONE_SLAB = create(key("smooth_stone_slab")); + + /** + * {@code minecraft:sniffer_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNIFFER_EGG = create(key("sniffer_egg")); + + /** + * {@code minecraft:sniffer_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNIFFER_SPAWN_EGG = create(key("sniffer_spawn_egg")); + + /** + * {@code minecraft:snort_pottery_sherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNORT_POTTERY_SHERD = create(key("snort_pottery_sherd")); + + /** + * {@code minecraft:snout_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("snout_armor_trim_smithing_template")); + + /** + * {@code minecraft:snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW = create(key("snow")); + + /** + * {@code minecraft:snow_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW_BLOCK = create(key("snow_block")); + + /** + * {@code minecraft:snow_golem_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW_GOLEM_SPAWN_EGG = create(key("snow_golem_spawn_egg")); + + /** + * {@code minecraft:snowball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWBALL = create(key("snowball")); + + /** + * {@code minecraft:soul_campfire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_CAMPFIRE = create(key("soul_campfire")); + + /** + * {@code minecraft:soul_lantern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_LANTERN = create(key("soul_lantern")); + + /** + * {@code minecraft:soul_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SAND = create(key("soul_sand")); + + /** + * {@code minecraft:soul_soil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SOIL = create(key("soul_soil")); + + /** + * {@code minecraft:soul_torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_TORCH = create(key("soul_torch")); + + /** + * {@code minecraft:spawner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPAWNER = create(key("spawner")); + + /** + * {@code minecraft:spectral_arrow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPECTRAL_ARROW = create(key("spectral_arrow")); + + /** + * {@code minecraft:spider_eye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIDER_EYE = create(key("spider_eye")); + + /** + * {@code minecraft:spider_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIDER_SPAWN_EGG = create(key("spider_spawn_egg")); + + /** + * {@code minecraft:spire_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("spire_armor_trim_smithing_template")); + + /** + * {@code minecraft:splash_potion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPLASH_POTION = create(key("splash_potion")); + + /** + * {@code minecraft:sponge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPONGE = create(key("sponge")); + + /** + * {@code minecraft:spore_blossom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPORE_BLOSSOM = create(key("spore_blossom")); + + /** + * {@code minecraft:spruce_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_BOAT = create(key("spruce_boat")); + + /** + * {@code minecraft:spruce_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_BUTTON = create(key("spruce_button")); + + /** + * {@code minecraft:spruce_chest_boat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_CHEST_BOAT = create(key("spruce_chest_boat")); + + /** + * {@code minecraft:spruce_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_DOOR = create(key("spruce_door")); + + /** + * {@code minecraft:spruce_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_FENCE = create(key("spruce_fence")); + + /** + * {@code minecraft:spruce_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_FENCE_GATE = create(key("spruce_fence_gate")); + + /** + * {@code minecraft:spruce_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_HANGING_SIGN = create(key("spruce_hanging_sign")); + + /** + * {@code minecraft:spruce_leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_LEAVES = create(key("spruce_leaves")); + + /** + * {@code minecraft:spruce_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_LOG = create(key("spruce_log")); + + /** + * {@code minecraft:spruce_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_PLANKS = create(key("spruce_planks")); + + /** + * {@code minecraft:spruce_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_PRESSURE_PLATE = create(key("spruce_pressure_plate")); + + /** + * {@code minecraft:spruce_sapling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SAPLING = create(key("spruce_sapling")); + + /** + * {@code minecraft:spruce_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SIGN = create(key("spruce_sign")); + + /** + * {@code minecraft:spruce_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_SLAB = create(key("spruce_slab")); + + /** + * {@code minecraft:spruce_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_STAIRS = create(key("spruce_stairs")); + + /** + * {@code minecraft:spruce_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_TRAPDOOR = create(key("spruce_trapdoor")); + + /** + * {@code minecraft:spruce_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPRUCE_WOOD = create(key("spruce_wood")); + + /** + * {@code minecraft:spyglass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPYGLASS = create(key("spyglass")); + + /** + * {@code minecraft:squid_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SQUID_SPAWN_EGG = create(key("squid_spawn_egg")); + + /** + * {@code minecraft:stick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STICK = create(key("stick")); + + /** + * {@code minecraft:sticky_piston} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STICKY_PISTON = create(key("sticky_piston")); + + /** + * {@code minecraft:stone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE = create(key("stone")); + + /** + * {@code minecraft:stone_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_AXE = create(key("stone_axe")); + + /** + * {@code minecraft:stone_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_SLAB = create(key("stone_brick_slab")); + + /** + * {@code minecraft:stone_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_STAIRS = create(key("stone_brick_stairs")); + + /** + * {@code minecraft:stone_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICK_WALL = create(key("stone_brick_wall")); + + /** + * {@code minecraft:stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BRICKS = create(key("stone_bricks")); + + /** + * {@code minecraft:stone_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_BUTTON = create(key("stone_button")); + + /** + * {@code minecraft:stone_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_HOE = create(key("stone_hoe")); + + /** + * {@code minecraft:stone_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_PICKAXE = create(key("stone_pickaxe")); + + /** + * {@code minecraft:stone_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_PRESSURE_PLATE = create(key("stone_pressure_plate")); + + /** + * {@code minecraft:stone_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_SHOVEL = create(key("stone_shovel")); + + /** + * {@code minecraft:stone_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_SLAB = create(key("stone_slab")); + + /** + * {@code minecraft:stone_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_STAIRS = create(key("stone_stairs")); + + /** + * {@code minecraft:stone_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONE_SWORD = create(key("stone_sword")); + + /** + * {@code minecraft:stonecutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONECUTTER = create(key("stonecutter")); + + /** + * {@code minecraft:stray_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRAY_SPAWN_EGG = create(key("stray_spawn_egg")); + + /** + * {@code minecraft:strider_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIDER_SPAWN_EGG = create(key("strider_spawn_egg")); + + /** + * {@code minecraft:string} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRING = create(key("string")); + + /** + * {@code minecraft:stripped_acacia_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_ACACIA_LOG = create(key("stripped_acacia_log")); + + /** + * {@code minecraft:stripped_acacia_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_ACACIA_WOOD = create(key("stripped_acacia_wood")); + + /** + * {@code minecraft:stripped_bamboo_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BAMBOO_BLOCK = create(key("stripped_bamboo_block")); + + /** + * {@code minecraft:stripped_birch_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BIRCH_LOG = create(key("stripped_birch_log")); + + /** + * {@code minecraft:stripped_birch_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_BIRCH_WOOD = create(key("stripped_birch_wood")); + + /** + * {@code minecraft:stripped_cherry_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CHERRY_LOG = create(key("stripped_cherry_log")); + + /** + * {@code minecraft:stripped_cherry_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CHERRY_WOOD = create(key("stripped_cherry_wood")); + + /** + * {@code minecraft:stripped_crimson_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CRIMSON_HYPHAE = create(key("stripped_crimson_hyphae")); + + /** + * {@code minecraft:stripped_crimson_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_CRIMSON_STEM = create(key("stripped_crimson_stem")); + + /** + * {@code minecraft:stripped_dark_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_DARK_OAK_LOG = create(key("stripped_dark_oak_log")); + + /** + * {@code minecraft:stripped_dark_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_DARK_OAK_WOOD = create(key("stripped_dark_oak_wood")); + + /** + * {@code minecraft:stripped_jungle_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_JUNGLE_LOG = create(key("stripped_jungle_log")); + + /** + * {@code minecraft:stripped_jungle_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_JUNGLE_WOOD = create(key("stripped_jungle_wood")); + + /** + * {@code minecraft:stripped_mangrove_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_MANGROVE_LOG = create(key("stripped_mangrove_log")); + + /** + * {@code minecraft:stripped_mangrove_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_MANGROVE_WOOD = create(key("stripped_mangrove_wood")); + + /** + * {@code minecraft:stripped_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_OAK_LOG = create(key("stripped_oak_log")); + + /** + * {@code minecraft:stripped_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_OAK_WOOD = create(key("stripped_oak_wood")); + + /** + * {@code minecraft:stripped_pale_oak_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_PALE_OAK_LOG = create(key("stripped_pale_oak_log")); + + /** + * {@code minecraft:stripped_pale_oak_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_PALE_OAK_WOOD = create(key("stripped_pale_oak_wood")); + + /** + * {@code minecraft:stripped_spruce_log} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_SPRUCE_LOG = create(key("stripped_spruce_log")); + + /** + * {@code minecraft:stripped_spruce_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_SPRUCE_WOOD = create(key("stripped_spruce_wood")); + + /** + * {@code minecraft:stripped_warped_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_WARPED_HYPHAE = create(key("stripped_warped_hyphae")); + + /** + * {@code minecraft:stripped_warped_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPPED_WARPED_STEM = create(key("stripped_warped_stem")); + + /** + * {@code minecraft:structure_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRUCTURE_BLOCK = create(key("structure_block")); + + /** + * {@code minecraft:structure_void} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRUCTURE_VOID = create(key("structure_void")); + + /** + * {@code minecraft:sugar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUGAR = create(key("sugar")); + + /** + * {@code minecraft:sugar_cane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUGAR_CANE = create(key("sugar_cane")); + + /** + * {@code minecraft:sunflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNFLOWER = create(key("sunflower")); + + /** + * {@code minecraft:suspicious_gravel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUSPICIOUS_GRAVEL = create(key("suspicious_gravel")); + + /** + * {@code minecraft:suspicious_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUSPICIOUS_SAND = create(key("suspicious_sand")); + + /** + * {@code minecraft:suspicious_stew} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUSPICIOUS_STEW = create(key("suspicious_stew")); + + /** + * {@code minecraft:sweet_berries} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEET_BERRIES = create(key("sweet_berries")); + + /** + * {@code minecraft:tadpole_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TADPOLE_BUCKET = create(key("tadpole_bucket")); + + /** + * {@code minecraft:tadpole_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TADPOLE_SPAWN_EGG = create(key("tadpole_spawn_egg")); + + /** + * {@code minecraft:tall_grass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TALL_GRASS = create(key("tall_grass")); + + /** + * {@code minecraft:target} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TARGET = create(key("target")); + + /** + * {@code minecraft:terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TERRACOTTA = create(key("terracotta")); + + /** + * {@code minecraft:tide_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TIDE_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("tide_armor_trim_smithing_template")); + + /** + * {@code minecraft:tinted_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TINTED_GLASS = create(key("tinted_glass")); + + /** + * {@code minecraft:tipped_arrow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TIPPED_ARROW = create(key("tipped_arrow")); + + /** + * {@code minecraft:tnt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TNT = create(key("tnt")); + + /** + * {@code minecraft:tnt_minecart} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TNT_MINECART = create(key("tnt_minecart")); + + /** + * {@code minecraft:torch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCH = create(key("torch")); + + /** + * {@code minecraft:torchflower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCHFLOWER = create(key("torchflower")); + + /** + * {@code minecraft:torchflower_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TORCHFLOWER_SEEDS = create(key("torchflower_seeds")); + + /** + * {@code minecraft:totem_of_undying} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TOTEM_OF_UNDYING = create(key("totem_of_undying")); + + /** + * {@code minecraft:trader_llama_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRADER_LLAMA_SPAWN_EGG = create(key("trader_llama_spawn_egg")); + + /** + * {@code minecraft:trapped_chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRAPPED_CHEST = create(key("trapped_chest")); + + /** + * {@code minecraft:trial_key} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_KEY = create(key("trial_key")); + + /** + * {@code minecraft:trial_spawner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_SPAWNER = create(key("trial_spawner")); + + /** + * {@code minecraft:trident} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIDENT = create(key("trident")); + + /** + * {@code minecraft:tripwire_hook} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIPWIRE_HOOK = create(key("tripwire_hook")); + + /** + * {@code minecraft:tropical_fish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TROPICAL_FISH = create(key("tropical_fish")); + + /** + * {@code minecraft:tropical_fish_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TROPICAL_FISH_BUCKET = create(key("tropical_fish_bucket")); + + /** + * {@code minecraft:tropical_fish_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TROPICAL_FISH_SPAWN_EGG = create(key("tropical_fish_spawn_egg")); + + /** + * {@code minecraft:tube_coral} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL = create(key("tube_coral")); + + /** + * {@code minecraft:tube_coral_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL_BLOCK = create(key("tube_coral_block")); + + /** + * {@code minecraft:tube_coral_fan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUBE_CORAL_FAN = create(key("tube_coral_fan")); + + /** + * {@code minecraft:tuff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF = create(key("tuff")); + + /** + * {@code minecraft:tuff_brick_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_SLAB = create(key("tuff_brick_slab")); + + /** + * {@code minecraft:tuff_brick_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_STAIRS = create(key("tuff_brick_stairs")); + + /** + * {@code minecraft:tuff_brick_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICK_WALL = create(key("tuff_brick_wall")); + + /** + * {@code minecraft:tuff_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_BRICKS = create(key("tuff_bricks")); + + /** + * {@code minecraft:tuff_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_SLAB = create(key("tuff_slab")); + + /** + * {@code minecraft:tuff_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_STAIRS = create(key("tuff_stairs")); + + /** + * {@code minecraft:tuff_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TUFF_WALL = create(key("tuff_wall")); + + /** + * {@code minecraft:turtle_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TURTLE_EGG = create(key("turtle_egg")); + + /** + * {@code minecraft:turtle_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TURTLE_HELMET = create(key("turtle_helmet")); + + /** + * {@code minecraft:turtle_scute} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TURTLE_SCUTE = create(key("turtle_scute")); + + /** + * {@code minecraft:turtle_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TURTLE_SPAWN_EGG = create(key("turtle_spawn_egg")); + + /** + * {@code minecraft:twisting_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TWISTING_VINES = create(key("twisting_vines")); + + /** + * {@code minecraft:vault} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VAULT = create(key("vault")); + + /** + * {@code minecraft:verdant_froglight} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VERDANT_FROGLIGHT = create(key("verdant_froglight")); + + /** + * {@code minecraft:vex_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VEX_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("vex_armor_trim_smithing_template")); + + /** + * {@code minecraft:vex_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VEX_SPAWN_EGG = create(key("vex_spawn_egg")); + + /** + * {@code minecraft:villager_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGER_SPAWN_EGG = create(key("villager_spawn_egg")); + + /** + * {@code minecraft:vindicator_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VINDICATOR_SPAWN_EGG = create(key("vindicator_spawn_egg")); + + /** + * {@code minecraft:vine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VINE = create(key("vine")); + + /** + * {@code minecraft:wandering_trader_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WANDERING_TRADER_SPAWN_EGG = create(key("wandering_trader_spawn_egg")); + + /** + * {@code minecraft:ward_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARD_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("ward_armor_trim_smithing_template")); + + /** + * {@code minecraft:warden_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARDEN_SPAWN_EGG = create(key("warden_spawn_egg")); + + /** + * {@code minecraft:warped_button} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_BUTTON = create(key("warped_button")); + + /** + * {@code minecraft:warped_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_DOOR = create(key("warped_door")); + + /** + * {@code minecraft:warped_fence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FENCE = create(key("warped_fence")); + + /** + * {@code minecraft:warped_fence_gate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FENCE_GATE = create(key("warped_fence_gate")); + + /** + * {@code minecraft:warped_fungus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FUNGUS = create(key("warped_fungus")); + + /** + * {@code minecraft:warped_fungus_on_a_stick} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FUNGUS_ON_A_STICK = create(key("warped_fungus_on_a_stick")); + + /** + * {@code minecraft:warped_hanging_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_HANGING_SIGN = create(key("warped_hanging_sign")); + + /** + * {@code minecraft:warped_hyphae} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_HYPHAE = create(key("warped_hyphae")); + + /** + * {@code minecraft:warped_nylium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_NYLIUM = create(key("warped_nylium")); + + /** + * {@code minecraft:warped_planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_PLANKS = create(key("warped_planks")); + + /** + * {@code minecraft:warped_pressure_plate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_PRESSURE_PLATE = create(key("warped_pressure_plate")); + + /** + * {@code minecraft:warped_roots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_ROOTS = create(key("warped_roots")); + + /** + * {@code minecraft:warped_sign} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_SIGN = create(key("warped_sign")); + + /** + * {@code minecraft:warped_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_SLAB = create(key("warped_slab")); + + /** + * {@code minecraft:warped_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_STAIRS = create(key("warped_stairs")); + + /** + * {@code minecraft:warped_stem} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_STEM = create(key("warped_stem")); + + /** + * {@code minecraft:warped_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_TRAPDOOR = create(key("warped_trapdoor")); + + /** + * {@code minecraft:warped_wart_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_WART_BLOCK = create(key("warped_wart_block")); + + /** + * {@code minecraft:water_bucket} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER_BUCKET = create(key("water_bucket")); + + /** + * {@code minecraft:waxed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CHISELED_COPPER = create(key("waxed_chiseled_copper")); + + /** + * {@code minecraft:waxed_copper_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_BLOCK = create(key("waxed_copper_block")); + + /** + * {@code minecraft:waxed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_BULB = create(key("waxed_copper_bulb")); + + /** + * {@code minecraft:waxed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_DOOR = create(key("waxed_copper_door")); + + /** + * {@code minecraft:waxed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_GRATE = create(key("waxed_copper_grate")); + + /** + * {@code minecraft:waxed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_COPPER_TRAPDOOR = create(key("waxed_copper_trapdoor")); + + /** + * {@code minecraft:waxed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER = create(key("waxed_cut_copper")); + + /** + * {@code minecraft:waxed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER_SLAB = create(key("waxed_cut_copper_slab")); + + /** + * {@code minecraft:waxed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_CUT_COPPER_STAIRS = create(key("waxed_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_exposed_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CHISELED_COPPER = create(key("waxed_exposed_chiseled_copper")); + + /** + * {@code minecraft:waxed_exposed_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER = create(key("waxed_exposed_copper")); + + /** + * {@code minecraft:waxed_exposed_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_BULB = create(key("waxed_exposed_copper_bulb")); + + /** + * {@code minecraft:waxed_exposed_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_DOOR = create(key("waxed_exposed_copper_door")); + + /** + * {@code minecraft:waxed_exposed_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_GRATE = create(key("waxed_exposed_copper_grate")); + + /** + * {@code minecraft:waxed_exposed_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_COPPER_TRAPDOOR = create(key("waxed_exposed_copper_trapdoor")); + + /** + * {@code minecraft:waxed_exposed_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER = create(key("waxed_exposed_cut_copper")); + + /** + * {@code minecraft:waxed_exposed_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER_SLAB = create(key("waxed_exposed_cut_copper_slab")); + + /** + * {@code minecraft:waxed_exposed_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_EXPOSED_CUT_COPPER_STAIRS = create(key("waxed_exposed_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_oxidized_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CHISELED_COPPER = create(key("waxed_oxidized_chiseled_copper")); + + /** + * {@code minecraft:waxed_oxidized_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER = create(key("waxed_oxidized_copper")); + + /** + * {@code minecraft:waxed_oxidized_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_BULB = create(key("waxed_oxidized_copper_bulb")); + + /** + * {@code minecraft:waxed_oxidized_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_DOOR = create(key("waxed_oxidized_copper_door")); + + /** + * {@code minecraft:waxed_oxidized_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_GRATE = create(key("waxed_oxidized_copper_grate")); + + /** + * {@code minecraft:waxed_oxidized_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_COPPER_TRAPDOOR = create(key("waxed_oxidized_copper_trapdoor")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER = create(key("waxed_oxidized_cut_copper")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER_SLAB = create(key("waxed_oxidized_cut_copper_slab")); + + /** + * {@code minecraft:waxed_oxidized_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_OXIDIZED_CUT_COPPER_STAIRS = create(key("waxed_oxidized_cut_copper_stairs")); + + /** + * {@code minecraft:waxed_weathered_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CHISELED_COPPER = create(key("waxed_weathered_chiseled_copper")); + + /** + * {@code minecraft:waxed_weathered_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER = create(key("waxed_weathered_copper")); + + /** + * {@code minecraft:waxed_weathered_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_BULB = create(key("waxed_weathered_copper_bulb")); + + /** + * {@code minecraft:waxed_weathered_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_DOOR = create(key("waxed_weathered_copper_door")); + + /** + * {@code minecraft:waxed_weathered_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_GRATE = create(key("waxed_weathered_copper_grate")); + + /** + * {@code minecraft:waxed_weathered_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_COPPER_TRAPDOOR = create(key("waxed_weathered_copper_trapdoor")); + + /** + * {@code minecraft:waxed_weathered_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER = create(key("waxed_weathered_cut_copper")); + + /** + * {@code minecraft:waxed_weathered_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER_SLAB = create(key("waxed_weathered_cut_copper_slab")); + + /** + * {@code minecraft:waxed_weathered_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAXED_WEATHERED_CUT_COPPER_STAIRS = create(key("waxed_weathered_cut_copper_stairs")); + + /** + * {@code minecraft:wayfinder_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("wayfinder_armor_trim_smithing_template")); + + /** + * {@code minecraft:weathered_chiseled_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CHISELED_COPPER = create(key("weathered_chiseled_copper")); + + /** + * {@code minecraft:weathered_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER = create(key("weathered_copper")); + + /** + * {@code minecraft:weathered_copper_bulb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_BULB = create(key("weathered_copper_bulb")); + + /** + * {@code minecraft:weathered_copper_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_DOOR = create(key("weathered_copper_door")); + + /** + * {@code minecraft:weathered_copper_grate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_GRATE = create(key("weathered_copper_grate")); + + /** + * {@code minecraft:weathered_copper_trapdoor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_COPPER_TRAPDOOR = create(key("weathered_copper_trapdoor")); + + /** + * {@code minecraft:weathered_cut_copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER = create(key("weathered_cut_copper")); + + /** + * {@code minecraft:weathered_cut_copper_slab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER_SLAB = create(key("weathered_cut_copper_slab")); + + /** + * {@code minecraft:weathered_cut_copper_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHERED_CUT_COPPER_STAIRS = create(key("weathered_cut_copper_stairs")); + + /** + * {@code minecraft:weeping_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEEPING_VINES = create(key("weeping_vines")); + + /** + * {@code minecraft:wet_sponge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WET_SPONGE = create(key("wet_sponge")); + + /** + * {@code minecraft:wheat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHEAT = create(key("wheat")); + + /** + * {@code minecraft:wheat_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHEAT_SEEDS = create(key("wheat_seeds")); + + /** + * {@code minecraft:white_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_BANNER = create(key("white_banner")); + + /** + * {@code minecraft:white_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_BED = create(key("white_bed")); + + /** + * {@code minecraft:white_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_BUNDLE = create(key("white_bundle")); + + /** + * {@code minecraft:white_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CANDLE = create(key("white_candle")); + + /** + * {@code minecraft:white_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CARPET = create(key("white_carpet")); + + /** + * {@code minecraft:white_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CONCRETE = create(key("white_concrete")); + + /** + * {@code minecraft:white_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_CONCRETE_POWDER = create(key("white_concrete_powder")); + + /** + * {@code minecraft:white_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_DYE = create(key("white_dye")); + + /** + * {@code minecraft:white_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_GLAZED_TERRACOTTA = create(key("white_glazed_terracotta")); + + /** + * {@code minecraft:white_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_SHULKER_BOX = create(key("white_shulker_box")); + + /** + * {@code minecraft:white_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_STAINED_GLASS = create(key("white_stained_glass")); + + /** + * {@code minecraft:white_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_STAINED_GLASS_PANE = create(key("white_stained_glass_pane")); + + /** + * {@code minecraft:white_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_TERRACOTTA = create(key("white_terracotta")); + + /** + * {@code minecraft:white_tulip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_TULIP = create(key("white_tulip")); + + /** + * {@code minecraft:white_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WHITE_WOOL = create(key("white_wool")); + + /** + * {@code minecraft:wild_armor_trim_smithing_template} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WILD_ARMOR_TRIM_SMITHING_TEMPLATE = create(key("wild_armor_trim_smithing_template")); + + /** + * {@code minecraft:wind_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WIND_CHARGE = create(key("wind_charge")); + + /** + * {@code minecraft:witch_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITCH_SPAWN_EGG = create(key("witch_spawn_egg")); + + /** + * {@code minecraft:wither_rose} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_ROSE = create(key("wither_rose")); + + /** + * {@code minecraft:wither_skeleton_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKELETON_SKULL = create(key("wither_skeleton_skull")); + + /** + * {@code minecraft:wither_skeleton_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKELETON_SPAWN_EGG = create(key("wither_skeleton_spawn_egg")); + + /** + * {@code minecraft:wither_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SPAWN_EGG = create(key("wither_spawn_egg")); + + /** + * {@code minecraft:wolf_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOLF_ARMOR = create(key("wolf_armor")); + + /** + * {@code minecraft:wolf_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOLF_SPAWN_EGG = create(key("wolf_spawn_egg")); + + /** + * {@code minecraft:wooden_axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODEN_AXE = create(key("wooden_axe")); + + /** + * {@code minecraft:wooden_hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODEN_HOE = create(key("wooden_hoe")); + + /** + * {@code minecraft:wooden_pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODEN_PICKAXE = create(key("wooden_pickaxe")); + + /** + * {@code minecraft:wooden_shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODEN_SHOVEL = create(key("wooden_shovel")); + + /** + * {@code minecraft:wooden_sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODEN_SWORD = create(key("wooden_sword")); + + /** + * {@code minecraft:writable_book} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WRITABLE_BOOK = create(key("writable_book")); + + /** + * {@code minecraft:written_book} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WRITTEN_BOOK = create(key("written_book")); + + /** + * {@code minecraft:yellow_banner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_BANNER = create(key("yellow_banner")); + + /** + * {@code minecraft:yellow_bed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_BED = create(key("yellow_bed")); + + /** + * {@code minecraft:yellow_bundle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_BUNDLE = create(key("yellow_bundle")); + + /** + * {@code minecraft:yellow_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CANDLE = create(key("yellow_candle")); + + /** + * {@code minecraft:yellow_carpet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CARPET = create(key("yellow_carpet")); + + /** + * {@code minecraft:yellow_concrete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CONCRETE = create(key("yellow_concrete")); + + /** + * {@code minecraft:yellow_concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_CONCRETE_POWDER = create(key("yellow_concrete_powder")); + + /** + * {@code minecraft:yellow_dye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_DYE = create(key("yellow_dye")); + + /** + * {@code minecraft:yellow_glazed_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_GLAZED_TERRACOTTA = create(key("yellow_glazed_terracotta")); + + /** + * {@code minecraft:yellow_shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_SHULKER_BOX = create(key("yellow_shulker_box")); + + /** + * {@code minecraft:yellow_stained_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_STAINED_GLASS = create(key("yellow_stained_glass")); + + /** + * {@code minecraft:yellow_stained_glass_pane} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_STAINED_GLASS_PANE = create(key("yellow_stained_glass_pane")); + + /** + * {@code minecraft:yellow_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_TERRACOTTA = create(key("yellow_terracotta")); + + /** + * {@code minecraft:yellow_wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YELLOW_WOOL = create(key("yellow_wool")); + + /** + * {@code minecraft:zoglin_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOGLIN_SPAWN_EGG = create(key("zoglin_spawn_egg")); + + /** + * {@code minecraft:zombie_head} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_HEAD = create(key("zombie_head")); + + /** + * {@code minecraft:zombie_horse_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_HORSE_SPAWN_EGG = create(key("zombie_horse_spawn_egg")); + + /** + * {@code minecraft:zombie_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_SPAWN_EGG = create(key("zombie_spawn_egg")); + + /** + * {@code minecraft:zombie_villager_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIE_VILLAGER_SPAWN_EGG = create(key("zombie_villager_spawn_egg")); + + /** + * {@code minecraft:zombified_piglin_spawn_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ZOMBIFIED_PIGLIN_SPAWN_EGG = create(key("zombified_piglin_spawn_egg")); + + private ItemTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.ITEM, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/JukeboxSongKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/JukeboxSongKeys.java new file mode 100644 index 000000000000..c2992bec9ae9 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/JukeboxSongKeys.java @@ -0,0 +1,176 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.JukeboxSong; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#JUKEBOX_SONG}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class JukeboxSongKeys { + /** + * {@code minecraft:11} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ELEVEN = create(key("11")); + + /** + * {@code minecraft:13} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THIRTEEN = create(key("13")); + + /** + * {@code minecraft:5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIVE = create(key("5")); + + /** + * {@code minecraft:blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCKS = create(key("blocks")); + + /** + * {@code minecraft:cat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAT = create(key("cat")); + + /** + * {@code minecraft:chirp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHIRP = create(key("chirp")); + + /** + * {@code minecraft:creator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREATOR = create(key("creator")); + + /** + * {@code minecraft:creator_music_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREATOR_MUSIC_BOX = create(key("creator_music_box")); + + /** + * {@code minecraft:far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FAR = create(key("far")); + + /** + * {@code minecraft:mall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MALL = create(key("mall")); + + /** + * {@code minecraft:mellohi} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MELLOHI = create(key("mellohi")); + + /** + * {@code minecraft:otherside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OTHERSIDE = create(key("otherside")); + + /** + * {@code minecraft:pigstep} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGSTEP = create(key("pigstep")); + + /** + * {@code minecraft:precipice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRECIPICE = create(key("precipice")); + + /** + * {@code minecraft:relic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RELIC = create(key("relic")); + + /** + * {@code minecraft:stal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STAL = create(key("stal")); + + /** + * {@code minecraft:strad} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRAD = create(key("strad")); + + /** + * {@code minecraft:wait} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAIT = create(key("wait")); + + /** + * {@code minecraft:ward} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARD = create(key("ward")); + + private JukeboxSongKeys() { + } + + /** + * Creates a key for {@link JukeboxSong} in the registry {@code minecraft:jukebox_song}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.JUKEBOX_SONG, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/MapDecorationTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/MapDecorationTypeKeys.java new file mode 100644 index 000000000000..f849e6602b38 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/MapDecorationTypeKeys.java @@ -0,0 +1,281 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.map.MapCursor; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#MAP_DECORATION_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class MapDecorationTypeKeys { + /** + * {@code minecraft:banner_black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_BLACK = create(key("banner_black")); + + /** + * {@code minecraft:banner_blue} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_BLUE = create(key("banner_blue")); + + /** + * {@code minecraft:banner_brown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_BROWN = create(key("banner_brown")); + + /** + * {@code minecraft:banner_cyan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_CYAN = create(key("banner_cyan")); + + /** + * {@code minecraft:banner_gray} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_GRAY = create(key("banner_gray")); + + /** + * {@code minecraft:banner_green} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_GREEN = create(key("banner_green")); + + /** + * {@code minecraft:banner_light_blue} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_LIGHT_BLUE = create(key("banner_light_blue")); + + /** + * {@code minecraft:banner_light_gray} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_LIGHT_GRAY = create(key("banner_light_gray")); + + /** + * {@code minecraft:banner_lime} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_LIME = create(key("banner_lime")); + + /** + * {@code minecraft:banner_magenta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_MAGENTA = create(key("banner_magenta")); + + /** + * {@code minecraft:banner_orange} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_ORANGE = create(key("banner_orange")); + + /** + * {@code minecraft:banner_pink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_PINK = create(key("banner_pink")); + + /** + * {@code minecraft:banner_purple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_PURPLE = create(key("banner_purple")); + + /** + * {@code minecraft:banner_red} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_RED = create(key("banner_red")); + + /** + * {@code minecraft:banner_white} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_WHITE = create(key("banner_white")); + + /** + * {@code minecraft:banner_yellow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANNER_YELLOW = create(key("banner_yellow")); + + /** + * {@code minecraft:blue_marker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLUE_MARKER = create(key("blue_marker")); + + /** + * {@code minecraft:frame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FRAME = create(key("frame")); + + /** + * {@code minecraft:jungle_temple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_TEMPLE = create(key("jungle_temple")); + + /** + * {@code minecraft:mansion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANSION = create(key("mansion")); + + /** + * {@code minecraft:monument} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MONUMENT = create(key("monument")); + + /** + * {@code minecraft:player} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER = create(key("player")); + + /** + * {@code minecraft:player_off_limits} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_OFF_LIMITS = create(key("player_off_limits")); + + /** + * {@code minecraft:player_off_map} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_OFF_MAP = create(key("player_off_map")); + + /** + * {@code minecraft:red_marker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_MARKER = create(key("red_marker")); + + /** + * {@code minecraft:red_x} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RED_X = create(key("red_x")); + + /** + * {@code minecraft:swamp_hut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP_HUT = create(key("swamp_hut")); + + /** + * {@code minecraft:target_point} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TARGET_POINT = create(key("target_point")); + + /** + * {@code minecraft:target_x} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TARGET_X = create(key("target_x")); + + /** + * {@code minecraft:trial_chambers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_CHAMBERS = create(key("trial_chambers")); + + /** + * {@code minecraft:village_desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_DESERT = create(key("village_desert")); + + /** + * {@code minecraft:village_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_PLAINS = create(key("village_plains")); + + /** + * {@code minecraft:village_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_SAVANNA = create(key("village_savanna")); + + /** + * {@code minecraft:village_snowy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_SNOWY = create(key("village_snowy")); + + /** + * {@code minecraft:village_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_TAIGA = create(key("village_taiga")); + + private MapDecorationTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.MAP_DECORATION_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/MenuTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/MenuTypeKeys.java new file mode 100644 index 000000000000..e33724921e22 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/MenuTypeKeys.java @@ -0,0 +1,211 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.MenuType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#MENU}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class MenuTypeKeys { + /** + * {@code minecraft:anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANVIL = create(key("anvil")); + + /** + * {@code minecraft:beacon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEACON = create(key("beacon")); + + /** + * {@code minecraft:blast_furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAST_FURNACE = create(key("blast_furnace")); + + /** + * {@code minecraft:brewing_stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BREWING_STAND = create(key("brewing_stand")); + + /** + * {@code minecraft:cartography_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARTOGRAPHY_TABLE = create(key("cartography_table")); + + /** + * {@code minecraft:crafter_3x3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTER_3X3 = create(key("crafter_3x3")); + + /** + * {@code minecraft:crafting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAFTING = create(key("crafting")); + + /** + * {@code minecraft:enchantment} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANTMENT = create(key("enchantment")); + + /** + * {@code minecraft:furnace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FURNACE = create(key("furnace")); + + /** + * {@code minecraft:generic_3x3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_3X3 = create(key("generic_3x3")); + + /** + * {@code minecraft:generic_9x1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X1 = create(key("generic_9x1")); + + /** + * {@code minecraft:generic_9x2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X2 = create(key("generic_9x2")); + + /** + * {@code minecraft:generic_9x3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X3 = create(key("generic_9x3")); + + /** + * {@code minecraft:generic_9x4} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X4 = create(key("generic_9x4")); + + /** + * {@code minecraft:generic_9x5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X5 = create(key("generic_9x5")); + + /** + * {@code minecraft:generic_9x6} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_9X6 = create(key("generic_9x6")); + + /** + * {@code minecraft:grindstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRINDSTONE = create(key("grindstone")); + + /** + * {@code minecraft:hopper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOPPER = create(key("hopper")); + + /** + * {@code minecraft:lectern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LECTERN = create(key("lectern")); + + /** + * {@code minecraft:loom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOOM = create(key("loom")); + + /** + * {@code minecraft:merchant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MERCHANT = create(key("merchant")); + + /** + * {@code minecraft:shulker_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHULKER_BOX = create(key("shulker_box")); + + /** + * {@code minecraft:smithing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMITHING = create(key("smithing")); + + /** + * {@code minecraft:smoker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMOKER = create(key("smoker")); + + /** + * {@code minecraft:stonecutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONECUTTER = create(key("stonecutter")); + + private MenuTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.MENU, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java new file mode 100644 index 000000000000..0ab126f652d0 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java @@ -0,0 +1,309 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#MOB_EFFECT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class MobEffectKeys { + /** + * {@code minecraft:absorption} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ABSORPTION = create(key("absorption")); + + /** + * {@code minecraft:bad_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAD_OMEN = create(key("bad_omen")); + + /** + * {@code minecraft:blindness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLINDNESS = create(key("blindness")); + + /** + * {@code minecraft:conduit_power} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONDUIT_POWER = create(key("conduit_power")); + + /** + * {@code minecraft:darkness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARKNESS = create(key("darkness")); + + /** + * {@code minecraft:dolphins_grace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DOLPHINS_GRACE = create(key("dolphins_grace")); + + /** + * {@code minecraft:fire_resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_RESISTANCE = create(key("fire_resistance")); + + /** + * {@code minecraft:glowing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOWING = create(key("glowing")); + + /** + * {@code minecraft:haste} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HASTE = create(key("haste")); + + /** + * {@code minecraft:health_boost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEALTH_BOOST = create(key("health_boost")); + + /** + * {@code minecraft:hero_of_the_village} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HERO_OF_THE_VILLAGE = create(key("hero_of_the_village")); + + /** + * {@code minecraft:hunger} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HUNGER = create(key("hunger")); + + /** + * {@code minecraft:infested} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFESTED = create(key("infested")); + + /** + * {@code minecraft:instant_damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTANT_DAMAGE = create(key("instant_damage")); + + /** + * {@code minecraft:instant_health} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTANT_HEALTH = create(key("instant_health")); + + /** + * {@code minecraft:invisibility} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INVISIBILITY = create(key("invisibility")); + + /** + * {@code minecraft:jump_boost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUMP_BOOST = create(key("jump_boost")); + + /** + * {@code minecraft:levitation} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEVITATION = create(key("levitation")); + + /** + * {@code minecraft:luck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUCK = create(key("luck")); + + /** + * {@code minecraft:mining_fatigue} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINING_FATIGUE = create(key("mining_fatigue")); + + /** + * {@code minecraft:nausea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NAUSEA = create(key("nausea")); + + /** + * {@code minecraft:night_vision} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NIGHT_VISION = create(key("night_vision")); + + /** + * {@code minecraft:oozing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OOZING = create(key("oozing")); + + /** + * {@code minecraft:poison} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POISON = create(key("poison")); + + /** + * {@code minecraft:raid_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAID_OMEN = create(key("raid_omen")); + + /** + * {@code minecraft:regeneration} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REGENERATION = create(key("regeneration")); + + /** + * {@code minecraft:resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESISTANCE = create(key("resistance")); + + /** + * {@code minecraft:saturation} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SATURATION = create(key("saturation")); + + /** + * {@code minecraft:slow_falling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLOW_FALLING = create(key("slow_falling")); + + /** + * {@code minecraft:slowness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLOWNESS = create(key("slowness")); + + /** + * {@code minecraft:speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPEED = create(key("speed")); + + /** + * {@code minecraft:strength} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRENGTH = create(key("strength")); + + /** + * {@code minecraft:trial_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_OMEN = create(key("trial_omen")); + + /** + * {@code minecraft:unluck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNLUCK = create(key("unluck")); + + /** + * {@code minecraft:water_breathing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER_BREATHING = create(key("water_breathing")); + + /** + * {@code minecraft:weakness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEAKNESS = create(key("weakness")); + + /** + * {@code minecraft:weaving} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEAVING = create(key("weaving")); + + /** + * {@code minecraft:wind_charged} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WIND_CHARGED = create(key("wind_charged")); + + /** + * {@code minecraft:wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER = create(key("wither")); + + private MobEffectKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.MOB_EFFECT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/PaintingVariantKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/PaintingVariantKeys.java new file mode 100644 index 000000000000..60c7580f0346 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/PaintingVariantKeys.java @@ -0,0 +1,393 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.Art; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#PAINTING_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class PaintingVariantKeys { + /** + * {@code minecraft:alban} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ALBAN = create(key("alban")); + + /** + * {@code minecraft:aztec} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZTEC = create(key("aztec")); + + /** + * {@code minecraft:aztec2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AZTEC2 = create(key("aztec2")); + + /** + * {@code minecraft:backyard} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BACKYARD = create(key("backyard")); + + /** + * {@code minecraft:baroque} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAROQUE = create(key("baroque")); + + /** + * {@code minecraft:bomb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOMB = create(key("bomb")); + + /** + * {@code minecraft:bouquet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOUQUET = create(key("bouquet")); + + /** + * {@code minecraft:burning_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURNING_SKULL = create(key("burning_skull")); + + /** + * {@code minecraft:bust} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUST = create(key("bust")); + + /** + * {@code minecraft:cavebird} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CAVEBIRD = create(key("cavebird")); + + /** + * {@code minecraft:changing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHANGING = create(key("changing")); + + /** + * {@code minecraft:cotan} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COTAN = create(key("cotan")); + + /** + * {@code minecraft:courbet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COURBET = create(key("courbet")); + + /** + * {@code minecraft:creebet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CREEBET = create(key("creebet")); + + /** + * {@code minecraft:donkey_kong} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DONKEY_KONG = create(key("donkey_kong")); + + /** + * {@code minecraft:earth} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EARTH = create(key("earth")); + + /** + * {@code minecraft:endboss} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENDBOSS = create(key("endboss")); + + /** + * {@code minecraft:fern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FERN = create(key("fern")); + + /** + * {@code minecraft:fighters} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIGHTERS = create(key("fighters")); + + /** + * {@code minecraft:finding} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FINDING = create(key("finding")); + + /** + * {@code minecraft:fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE = create(key("fire")); + + /** + * {@code minecraft:graham} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GRAHAM = create(key("graham")); + + /** + * {@code minecraft:humble} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HUMBLE = create(key("humble")); + + /** + * {@code minecraft:kebab} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KEBAB = create(key("kebab")); + + /** + * {@code minecraft:lowmist} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOWMIST = create(key("lowmist")); + + /** + * {@code minecraft:match} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MATCH = create(key("match")); + + /** + * {@code minecraft:meditative} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MEDITATIVE = create(key("meditative")); + + /** + * {@code minecraft:orb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ORB = create(key("orb")); + + /** + * {@code minecraft:owlemons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OWLEMONS = create(key("owlemons")); + + /** + * {@code minecraft:passage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PASSAGE = create(key("passage")); + + /** + * {@code minecraft:pigscene} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIGSCENE = create(key("pigscene")); + + /** + * {@code minecraft:plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLANT = create(key("plant")); + + /** + * {@code minecraft:pointer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POINTER = create(key("pointer")); + + /** + * {@code minecraft:pond} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POND = create(key("pond")); + + /** + * {@code minecraft:pool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POOL = create(key("pool")); + + /** + * {@code minecraft:prairie_ride} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRAIRIE_RIDE = create(key("prairie_ride")); + + /** + * {@code minecraft:sea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEA = create(key("sea")); + + /** + * {@code minecraft:skeleton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKELETON = create(key("skeleton")); + + /** + * {@code minecraft:skull_and_roses} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SKULL_AND_ROSES = create(key("skull_and_roses")); + + /** + * {@code minecraft:stage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STAGE = create(key("stage")); + + /** + * {@code minecraft:sunflowers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNFLOWERS = create(key("sunflowers")); + + /** + * {@code minecraft:sunset} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNSET = create(key("sunset")); + + /** + * {@code minecraft:tides} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TIDES = create(key("tides")); + + /** + * {@code minecraft:unpacked} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNPACKED = create(key("unpacked")); + + /** + * {@code minecraft:void} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VOID = create(key("void")); + + /** + * {@code minecraft:wanderer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WANDERER = create(key("wanderer")); + + /** + * {@code minecraft:wasteland} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WASTELAND = create(key("wasteland")); + + /** + * {@code minecraft:water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER = create(key("water")); + + /** + * {@code minecraft:wind} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WIND = create(key("wind")); + + /** + * {@code minecraft:wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER = create(key("wither")); + + private PaintingVariantKeys() { + } + + /** + * Creates a key for {@link Art} in the registry {@code minecraft:painting_variant}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.PAINTING_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/SoundEventKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/SoundEventKeys.java new file mode 100644 index 000000000000..ece998b1e083 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/SoundEventKeys.java @@ -0,0 +1,11593 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.Sound; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#SOUND_EVENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class SoundEventKeys { + /** + * {@code minecraft:ambient.basalt_deltas.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_BASALT_DELTAS_ADDITIONS = create(key("ambient.basalt_deltas.additions")); + + /** + * {@code minecraft:ambient.basalt_deltas.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_BASALT_DELTAS_LOOP = create(key("ambient.basalt_deltas.loop")); + + /** + * {@code minecraft:ambient.basalt_deltas.mood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_BASALT_DELTAS_MOOD = create(key("ambient.basalt_deltas.mood")); + + /** + * {@code minecraft:ambient.cave} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_CAVE = create(key("ambient.cave")); + + /** + * {@code minecraft:ambient.crimson_forest.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_CRIMSON_FOREST_ADDITIONS = create(key("ambient.crimson_forest.additions")); + + /** + * {@code minecraft:ambient.crimson_forest.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_CRIMSON_FOREST_LOOP = create(key("ambient.crimson_forest.loop")); + + /** + * {@code minecraft:ambient.crimson_forest.mood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_CRIMSON_FOREST_MOOD = create(key("ambient.crimson_forest.mood")); + + /** + * {@code minecraft:ambient.nether_wastes.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_NETHER_WASTES_ADDITIONS = create(key("ambient.nether_wastes.additions")); + + /** + * {@code minecraft:ambient.nether_wastes.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_NETHER_WASTES_LOOP = create(key("ambient.nether_wastes.loop")); + + /** + * {@code minecraft:ambient.nether_wastes.mood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_NETHER_WASTES_MOOD = create(key("ambient.nether_wastes.mood")); + + /** + * {@code minecraft:ambient.soul_sand_valley.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_SOUL_SAND_VALLEY_ADDITIONS = create(key("ambient.soul_sand_valley.additions")); + + /** + * {@code minecraft:ambient.soul_sand_valley.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_SOUL_SAND_VALLEY_LOOP = create(key("ambient.soul_sand_valley.loop")); + + /** + * {@code minecraft:ambient.soul_sand_valley.mood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_SOUL_SAND_VALLEY_MOOD = create(key("ambient.soul_sand_valley.mood")); + + /** + * {@code minecraft:ambient.underwater.enter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_ENTER = create(key("ambient.underwater.enter")); + + /** + * {@code minecraft:ambient.underwater.exit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_EXIT = create(key("ambient.underwater.exit")); + + /** + * {@code minecraft:ambient.underwater.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_LOOP = create(key("ambient.underwater.loop")); + + /** + * {@code minecraft:ambient.underwater.loop.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_LOOP_ADDITIONS = create(key("ambient.underwater.loop.additions")); + + /** + * {@code minecraft:ambient.underwater.loop.additions.rare} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_LOOP_ADDITIONS_RARE = create(key("ambient.underwater.loop.additions.rare")); + + /** + * {@code minecraft:ambient.underwater.loop.additions.ultra_rare} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_UNDERWATER_LOOP_ADDITIONS_ULTRA_RARE = create(key("ambient.underwater.loop.additions.ultra_rare")); + + /** + * {@code minecraft:ambient.warped_forest.additions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_WARPED_FOREST_ADDITIONS = create(key("ambient.warped_forest.additions")); + + /** + * {@code minecraft:ambient.warped_forest.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_WARPED_FOREST_LOOP = create(key("ambient.warped_forest.loop")); + + /** + * {@code minecraft:ambient.warped_forest.mood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMBIENT_WARPED_FOREST_MOOD = create(key("ambient.warped_forest.mood")); + + /** + * {@code minecraft:block.amethyst_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_BREAK = create(key("block.amethyst_block.break")); + + /** + * {@code minecraft:block.amethyst_block.chime} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_CHIME = create(key("block.amethyst_block.chime")); + + /** + * {@code minecraft:block.amethyst_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_FALL = create(key("block.amethyst_block.fall")); + + /** + * {@code minecraft:block.amethyst_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_HIT = create(key("block.amethyst_block.hit")); + + /** + * {@code minecraft:block.amethyst_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_PLACE = create(key("block.amethyst_block.place")); + + /** + * {@code minecraft:block.amethyst_block.resonate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_RESONATE = create(key("block.amethyst_block.resonate")); + + /** + * {@code minecraft:block.amethyst_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_BLOCK_STEP = create(key("block.amethyst_block.step")); + + /** + * {@code minecraft:block.amethyst_cluster.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_CLUSTER_BREAK = create(key("block.amethyst_cluster.break")); + + /** + * {@code minecraft:block.amethyst_cluster.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_CLUSTER_FALL = create(key("block.amethyst_cluster.fall")); + + /** + * {@code minecraft:block.amethyst_cluster.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_CLUSTER_HIT = create(key("block.amethyst_cluster.hit")); + + /** + * {@code minecraft:block.amethyst_cluster.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_CLUSTER_PLACE = create(key("block.amethyst_cluster.place")); + + /** + * {@code minecraft:block.amethyst_cluster.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AMETHYST_CLUSTER_STEP = create(key("block.amethyst_cluster.step")); + + /** + * {@code minecraft:block.ancient_debris.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANCIENT_DEBRIS_BREAK = create(key("block.ancient_debris.break")); + + /** + * {@code minecraft:block.ancient_debris.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANCIENT_DEBRIS_FALL = create(key("block.ancient_debris.fall")); + + /** + * {@code minecraft:block.ancient_debris.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANCIENT_DEBRIS_HIT = create(key("block.ancient_debris.hit")); + + /** + * {@code minecraft:block.ancient_debris.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANCIENT_DEBRIS_PLACE = create(key("block.ancient_debris.place")); + + /** + * {@code minecraft:block.ancient_debris.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANCIENT_DEBRIS_STEP = create(key("block.ancient_debris.step")); + + /** + * {@code minecraft:block.anvil.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_BREAK = create(key("block.anvil.break")); + + /** + * {@code minecraft:block.anvil.destroy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_DESTROY = create(key("block.anvil.destroy")); + + /** + * {@code minecraft:block.anvil.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_FALL = create(key("block.anvil.fall")); + + /** + * {@code minecraft:block.anvil.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_HIT = create(key("block.anvil.hit")); + + /** + * {@code minecraft:block.anvil.land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_LAND = create(key("block.anvil.land")); + + /** + * {@code minecraft:block.anvil.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_PLACE = create(key("block.anvil.place")); + + /** + * {@code minecraft:block.anvil.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_STEP = create(key("block.anvil.step")); + + /** + * {@code minecraft:block.anvil.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ANVIL_USE = create(key("block.anvil.use")); + + /** + * {@code minecraft:block.azalea.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_BREAK = create(key("block.azalea.break")); + + /** + * {@code minecraft:block.azalea.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_FALL = create(key("block.azalea.fall")); + + /** + * {@code minecraft:block.azalea.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_HIT = create(key("block.azalea.hit")); + + /** + * {@code minecraft:block.azalea.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_PLACE = create(key("block.azalea.place")); + + /** + * {@code minecraft:block.azalea.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_STEP = create(key("block.azalea.step")); + + /** + * {@code minecraft:block.azalea_leaves.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_LEAVES_BREAK = create(key("block.azalea_leaves.break")); + + /** + * {@code minecraft:block.azalea_leaves.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_LEAVES_FALL = create(key("block.azalea_leaves.fall")); + + /** + * {@code minecraft:block.azalea_leaves.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_LEAVES_HIT = create(key("block.azalea_leaves.hit")); + + /** + * {@code minecraft:block.azalea_leaves.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_LEAVES_PLACE = create(key("block.azalea_leaves.place")); + + /** + * {@code minecraft:block.azalea_leaves.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_AZALEA_LEAVES_STEP = create(key("block.azalea_leaves.step")); + + /** + * {@code minecraft:block.bamboo.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_BREAK = create(key("block.bamboo.break")); + + /** + * {@code minecraft:block.bamboo.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_FALL = create(key("block.bamboo.fall")); + + /** + * {@code minecraft:block.bamboo.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_HIT = create(key("block.bamboo.hit")); + + /** + * {@code minecraft:block.bamboo.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_PLACE = create(key("block.bamboo.place")); + + /** + * {@code minecraft:block.bamboo.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_STEP = create(key("block.bamboo.step")); + + /** + * {@code minecraft:block.bamboo_sapling.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_SAPLING_BREAK = create(key("block.bamboo_sapling.break")); + + /** + * {@code minecraft:block.bamboo_sapling.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_SAPLING_HIT = create(key("block.bamboo_sapling.hit")); + + /** + * {@code minecraft:block.bamboo_sapling.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_SAPLING_PLACE = create(key("block.bamboo_sapling.place")); + + /** + * {@code minecraft:block.bamboo_wood.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_BREAK = create(key("block.bamboo_wood.break")); + + /** + * {@code minecraft:block.bamboo_wood.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_FALL = create(key("block.bamboo_wood.fall")); + + /** + * {@code minecraft:block.bamboo_wood.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HIT = create(key("block.bamboo_wood.hit")); + + /** + * {@code minecraft:block.bamboo_wood.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_PLACE = create(key("block.bamboo_wood.place")); + + /** + * {@code minecraft:block.bamboo_wood.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_STEP = create(key("block.bamboo_wood.step")); + + /** + * {@code minecraft:block.bamboo_wood_button.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_BUTTON_CLICK_OFF = create(key("block.bamboo_wood_button.click_off")); + + /** + * {@code minecraft:block.bamboo_wood_button.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_BUTTON_CLICK_ON = create(key("block.bamboo_wood_button.click_on")); + + /** + * {@code minecraft:block.bamboo_wood_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_DOOR_CLOSE = create(key("block.bamboo_wood_door.close")); + + /** + * {@code minecraft:block.bamboo_wood_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_DOOR_OPEN = create(key("block.bamboo_wood_door.open")); + + /** + * {@code minecraft:block.bamboo_wood_fence_gate.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_FENCE_GATE_CLOSE = create(key("block.bamboo_wood_fence_gate.close")); + + /** + * {@code minecraft:block.bamboo_wood_fence_gate.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_FENCE_GATE_OPEN = create(key("block.bamboo_wood_fence_gate.open")); + + /** + * {@code minecraft:block.bamboo_wood_hanging_sign.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HANGING_SIGN_BREAK = create(key("block.bamboo_wood_hanging_sign.break")); + + /** + * {@code minecraft:block.bamboo_wood_hanging_sign.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HANGING_SIGN_FALL = create(key("block.bamboo_wood_hanging_sign.fall")); + + /** + * {@code minecraft:block.bamboo_wood_hanging_sign.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HANGING_SIGN_HIT = create(key("block.bamboo_wood_hanging_sign.hit")); + + /** + * {@code minecraft:block.bamboo_wood_hanging_sign.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HANGING_SIGN_PLACE = create(key("block.bamboo_wood_hanging_sign.place")); + + /** + * {@code minecraft:block.bamboo_wood_hanging_sign.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_HANGING_SIGN_STEP = create(key("block.bamboo_wood_hanging_sign.step")); + + /** + * {@code minecraft:block.bamboo_wood_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_OFF = create(key("block.bamboo_wood_pressure_plate.click_off")); + + /** + * {@code minecraft:block.bamboo_wood_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_ON = create(key("block.bamboo_wood_pressure_plate.click_on")); + + /** + * {@code minecraft:block.bamboo_wood_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_TRAPDOOR_CLOSE = create(key("block.bamboo_wood_trapdoor.close")); + + /** + * {@code minecraft:block.bamboo_wood_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BAMBOO_WOOD_TRAPDOOR_OPEN = create(key("block.bamboo_wood_trapdoor.open")); + + /** + * {@code minecraft:block.barrel.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BARREL_CLOSE = create(key("block.barrel.close")); + + /** + * {@code minecraft:block.barrel.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BARREL_OPEN = create(key("block.barrel.open")); + + /** + * {@code minecraft:block.basalt.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BASALT_BREAK = create(key("block.basalt.break")); + + /** + * {@code minecraft:block.basalt.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BASALT_FALL = create(key("block.basalt.fall")); + + /** + * {@code minecraft:block.basalt.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BASALT_HIT = create(key("block.basalt.hit")); + + /** + * {@code minecraft:block.basalt.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BASALT_PLACE = create(key("block.basalt.place")); + + /** + * {@code minecraft:block.basalt.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BASALT_STEP = create(key("block.basalt.step")); + + /** + * {@code minecraft:block.beacon.activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEACON_ACTIVATE = create(key("block.beacon.activate")); + + /** + * {@code minecraft:block.beacon.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEACON_AMBIENT = create(key("block.beacon.ambient")); + + /** + * {@code minecraft:block.beacon.deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEACON_DEACTIVATE = create(key("block.beacon.deactivate")); + + /** + * {@code minecraft:block.beacon.power_select} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEACON_POWER_SELECT = create(key("block.beacon.power_select")); + + /** + * {@code minecraft:block.beehive.drip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEEHIVE_DRIP = create(key("block.beehive.drip")); + + /** + * {@code minecraft:block.beehive.enter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEEHIVE_ENTER = create(key("block.beehive.enter")); + + /** + * {@code minecraft:block.beehive.exit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEEHIVE_EXIT = create(key("block.beehive.exit")); + + /** + * {@code minecraft:block.beehive.shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEEHIVE_SHEAR = create(key("block.beehive.shear")); + + /** + * {@code minecraft:block.beehive.work} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BEEHIVE_WORK = create(key("block.beehive.work")); + + /** + * {@code minecraft:block.bell.resonate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BELL_RESONATE = create(key("block.bell.resonate")); + + /** + * {@code minecraft:block.bell.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BELL_USE = create(key("block.bell.use")); + + /** + * {@code minecraft:block.big_dripleaf.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_BREAK = create(key("block.big_dripleaf.break")); + + /** + * {@code minecraft:block.big_dripleaf.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_FALL = create(key("block.big_dripleaf.fall")); + + /** + * {@code minecraft:block.big_dripleaf.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_HIT = create(key("block.big_dripleaf.hit")); + + /** + * {@code minecraft:block.big_dripleaf.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_PLACE = create(key("block.big_dripleaf.place")); + + /** + * {@code minecraft:block.big_dripleaf.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_STEP = create(key("block.big_dripleaf.step")); + + /** + * {@code minecraft:block.big_dripleaf.tilt_down} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_TILT_DOWN = create(key("block.big_dripleaf.tilt_down")); + + /** + * {@code minecraft:block.big_dripleaf.tilt_up} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BIG_DRIPLEAF_TILT_UP = create(key("block.big_dripleaf.tilt_up")); + + /** + * {@code minecraft:block.blastfurnace.fire_crackle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BLASTFURNACE_FIRE_CRACKLE = create(key("block.blastfurnace.fire_crackle")); + + /** + * {@code minecraft:block.bone_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BONE_BLOCK_BREAK = create(key("block.bone_block.break")); + + /** + * {@code minecraft:block.bone_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BONE_BLOCK_FALL = create(key("block.bone_block.fall")); + + /** + * {@code minecraft:block.bone_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BONE_BLOCK_HIT = create(key("block.bone_block.hit")); + + /** + * {@code minecraft:block.bone_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BONE_BLOCK_PLACE = create(key("block.bone_block.place")); + + /** + * {@code minecraft:block.bone_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BONE_BLOCK_STEP = create(key("block.bone_block.step")); + + /** + * {@code minecraft:block.brewing_stand.brew} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BREWING_STAND_BREW = create(key("block.brewing_stand.brew")); + + /** + * {@code minecraft:block.bubble_column.bubble_pop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BUBBLE_COLUMN_BUBBLE_POP = create(key("block.bubble_column.bubble_pop")); + + /** + * {@code minecraft:block.bubble_column.upwards_ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT = create(key("block.bubble_column.upwards_ambient")); + + /** + * {@code minecraft:block.bubble_column.upwards_inside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE = create(key("block.bubble_column.upwards_inside")); + + /** + * {@code minecraft:block.bubble_column.whirlpool_ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT = create(key("block.bubble_column.whirlpool_ambient")); + + /** + * {@code minecraft:block.bubble_column.whirlpool_inside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE = create(key("block.bubble_column.whirlpool_inside")); + + /** + * {@code minecraft:block.cake.add_candle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAKE_ADD_CANDLE = create(key("block.cake.add_candle")); + + /** + * {@code minecraft:block.calcite.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CALCITE_BREAK = create(key("block.calcite.break")); + + /** + * {@code minecraft:block.calcite.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CALCITE_FALL = create(key("block.calcite.fall")); + + /** + * {@code minecraft:block.calcite.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CALCITE_HIT = create(key("block.calcite.hit")); + + /** + * {@code minecraft:block.calcite.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CALCITE_PLACE = create(key("block.calcite.place")); + + /** + * {@code minecraft:block.calcite.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CALCITE_STEP = create(key("block.calcite.step")); + + /** + * {@code minecraft:block.campfire.crackle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAMPFIRE_CRACKLE = create(key("block.campfire.crackle")); + + /** + * {@code minecraft:block.candle.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_AMBIENT = create(key("block.candle.ambient")); + + /** + * {@code minecraft:block.candle.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_BREAK = create(key("block.candle.break")); + + /** + * {@code minecraft:block.candle.extinguish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_EXTINGUISH = create(key("block.candle.extinguish")); + + /** + * {@code minecraft:block.candle.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_FALL = create(key("block.candle.fall")); + + /** + * {@code minecraft:block.candle.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_HIT = create(key("block.candle.hit")); + + /** + * {@code minecraft:block.candle.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_PLACE = create(key("block.candle.place")); + + /** + * {@code minecraft:block.candle.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CANDLE_STEP = create(key("block.candle.step")); + + /** + * {@code minecraft:block.cave_vines.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_BREAK = create(key("block.cave_vines.break")); + + /** + * {@code minecraft:block.cave_vines.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_FALL = create(key("block.cave_vines.fall")); + + /** + * {@code minecraft:block.cave_vines.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_HIT = create(key("block.cave_vines.hit")); + + /** + * {@code minecraft:block.cave_vines.pick_berries} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_PICK_BERRIES = create(key("block.cave_vines.pick_berries")); + + /** + * {@code minecraft:block.cave_vines.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_PLACE = create(key("block.cave_vines.place")); + + /** + * {@code minecraft:block.cave_vines.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CAVE_VINES_STEP = create(key("block.cave_vines.step")); + + /** + * {@code minecraft:block.chain.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHAIN_BREAK = create(key("block.chain.break")); + + /** + * {@code minecraft:block.chain.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHAIN_FALL = create(key("block.chain.fall")); + + /** + * {@code minecraft:block.chain.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHAIN_HIT = create(key("block.chain.hit")); + + /** + * {@code minecraft:block.chain.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHAIN_PLACE = create(key("block.chain.place")); + + /** + * {@code minecraft:block.chain.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHAIN_STEP = create(key("block.chain.step")); + + /** + * {@code minecraft:block.cherry_leaves.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_LEAVES_BREAK = create(key("block.cherry_leaves.break")); + + /** + * {@code minecraft:block.cherry_leaves.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_LEAVES_FALL = create(key("block.cherry_leaves.fall")); + + /** + * {@code minecraft:block.cherry_leaves.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_LEAVES_HIT = create(key("block.cherry_leaves.hit")); + + /** + * {@code minecraft:block.cherry_leaves.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_LEAVES_PLACE = create(key("block.cherry_leaves.place")); + + /** + * {@code minecraft:block.cherry_leaves.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_LEAVES_STEP = create(key("block.cherry_leaves.step")); + + /** + * {@code minecraft:block.cherry_sapling.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_SAPLING_BREAK = create(key("block.cherry_sapling.break")); + + /** + * {@code minecraft:block.cherry_sapling.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_SAPLING_FALL = create(key("block.cherry_sapling.fall")); + + /** + * {@code minecraft:block.cherry_sapling.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_SAPLING_HIT = create(key("block.cherry_sapling.hit")); + + /** + * {@code minecraft:block.cherry_sapling.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_SAPLING_PLACE = create(key("block.cherry_sapling.place")); + + /** + * {@code minecraft:block.cherry_sapling.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_SAPLING_STEP = create(key("block.cherry_sapling.step")); + + /** + * {@code minecraft:block.cherry_wood.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_BREAK = create(key("block.cherry_wood.break")); + + /** + * {@code minecraft:block.cherry_wood.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_FALL = create(key("block.cherry_wood.fall")); + + /** + * {@code minecraft:block.cherry_wood.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HIT = create(key("block.cherry_wood.hit")); + + /** + * {@code minecraft:block.cherry_wood.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_PLACE = create(key("block.cherry_wood.place")); + + /** + * {@code minecraft:block.cherry_wood.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_STEP = create(key("block.cherry_wood.step")); + + /** + * {@code minecraft:block.cherry_wood_button.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_BUTTON_CLICK_OFF = create(key("block.cherry_wood_button.click_off")); + + /** + * {@code minecraft:block.cherry_wood_button.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_BUTTON_CLICK_ON = create(key("block.cherry_wood_button.click_on")); + + /** + * {@code minecraft:block.cherry_wood_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_DOOR_CLOSE = create(key("block.cherry_wood_door.close")); + + /** + * {@code minecraft:block.cherry_wood_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_DOOR_OPEN = create(key("block.cherry_wood_door.open")); + + /** + * {@code minecraft:block.cherry_wood_fence_gate.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_FENCE_GATE_CLOSE = create(key("block.cherry_wood_fence_gate.close")); + + /** + * {@code minecraft:block.cherry_wood_fence_gate.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_FENCE_GATE_OPEN = create(key("block.cherry_wood_fence_gate.open")); + + /** + * {@code minecraft:block.cherry_wood_hanging_sign.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HANGING_SIGN_BREAK = create(key("block.cherry_wood_hanging_sign.break")); + + /** + * {@code minecraft:block.cherry_wood_hanging_sign.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HANGING_SIGN_FALL = create(key("block.cherry_wood_hanging_sign.fall")); + + /** + * {@code minecraft:block.cherry_wood_hanging_sign.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HANGING_SIGN_HIT = create(key("block.cherry_wood_hanging_sign.hit")); + + /** + * {@code minecraft:block.cherry_wood_hanging_sign.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HANGING_SIGN_PLACE = create(key("block.cherry_wood_hanging_sign.place")); + + /** + * {@code minecraft:block.cherry_wood_hanging_sign.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_HANGING_SIGN_STEP = create(key("block.cherry_wood_hanging_sign.step")); + + /** + * {@code minecraft:block.cherry_wood_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_OFF = create(key("block.cherry_wood_pressure_plate.click_off")); + + /** + * {@code minecraft:block.cherry_wood_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_ON = create(key("block.cherry_wood_pressure_plate.click_on")); + + /** + * {@code minecraft:block.cherry_wood_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_TRAPDOOR_CLOSE = create(key("block.cherry_wood_trapdoor.close")); + + /** + * {@code minecraft:block.cherry_wood_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHERRY_WOOD_TRAPDOOR_OPEN = create(key("block.cherry_wood_trapdoor.open")); + + /** + * {@code minecraft:block.chest.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHEST_CLOSE = create(key("block.chest.close")); + + /** + * {@code minecraft:block.chest.locked} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHEST_LOCKED = create(key("block.chest.locked")); + + /** + * {@code minecraft:block.chest.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHEST_OPEN = create(key("block.chest.open")); + + /** + * {@code minecraft:block.chiseled_bookshelf.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_BREAK = create(key("block.chiseled_bookshelf.break")); + + /** + * {@code minecraft:block.chiseled_bookshelf.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_FALL = create(key("block.chiseled_bookshelf.fall")); + + /** + * {@code minecraft:block.chiseled_bookshelf.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_HIT = create(key("block.chiseled_bookshelf.hit")); + + /** + * {@code minecraft:block.chiseled_bookshelf.insert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_INSERT = create(key("block.chiseled_bookshelf.insert")); + + /** + * {@code minecraft:block.chiseled_bookshelf.insert.enchanted} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_INSERT_ENCHANTED = create(key("block.chiseled_bookshelf.insert.enchanted")); + + /** + * {@code minecraft:block.chiseled_bookshelf.pickup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_PICKUP = create(key("block.chiseled_bookshelf.pickup")); + + /** + * {@code minecraft:block.chiseled_bookshelf.pickup.enchanted} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_PICKUP_ENCHANTED = create(key("block.chiseled_bookshelf.pickup.enchanted")); + + /** + * {@code minecraft:block.chiseled_bookshelf.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_PLACE = create(key("block.chiseled_bookshelf.place")); + + /** + * {@code minecraft:block.chiseled_bookshelf.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHISELED_BOOKSHELF_STEP = create(key("block.chiseled_bookshelf.step")); + + /** + * {@code minecraft:block.chorus_flower.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHORUS_FLOWER_DEATH = create(key("block.chorus_flower.death")); + + /** + * {@code minecraft:block.chorus_flower.grow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHORUS_FLOWER_GROW = create(key("block.chorus_flower.grow")); + + /** + * {@code minecraft:block.cobweb.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COBWEB_BREAK = create(key("block.cobweb.break")); + + /** + * {@code minecraft:block.cobweb.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COBWEB_FALL = create(key("block.cobweb.fall")); + + /** + * {@code minecraft:block.cobweb.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COBWEB_HIT = create(key("block.cobweb.hit")); + + /** + * {@code minecraft:block.cobweb.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COBWEB_PLACE = create(key("block.cobweb.place")); + + /** + * {@code minecraft:block.cobweb.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COBWEB_STEP = create(key("block.cobweb.step")); + + /** + * {@code minecraft:block.comparator.click} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COMPARATOR_CLICK = create(key("block.comparator.click")); + + /** + * {@code minecraft:block.composter.empty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COMPOSTER_EMPTY = create(key("block.composter.empty")); + + /** + * {@code minecraft:block.composter.fill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COMPOSTER_FILL = create(key("block.composter.fill")); + + /** + * {@code minecraft:block.composter.fill_success} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COMPOSTER_FILL_SUCCESS = create(key("block.composter.fill_success")); + + /** + * {@code minecraft:block.composter.ready} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COMPOSTER_READY = create(key("block.composter.ready")); + + /** + * {@code minecraft:block.conduit.activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CONDUIT_ACTIVATE = create(key("block.conduit.activate")); + + /** + * {@code minecraft:block.conduit.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CONDUIT_AMBIENT = create(key("block.conduit.ambient")); + + /** + * {@code minecraft:block.conduit.ambient.short} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CONDUIT_AMBIENT_SHORT = create(key("block.conduit.ambient.short")); + + /** + * {@code minecraft:block.conduit.attack.target} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CONDUIT_ATTACK_TARGET = create(key("block.conduit.attack.target")); + + /** + * {@code minecraft:block.conduit.deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CONDUIT_DEACTIVATE = create(key("block.conduit.deactivate")); + + /** + * {@code minecraft:block.copper.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BREAK = create(key("block.copper.break")); + + /** + * {@code minecraft:block.copper.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_FALL = create(key("block.copper.fall")); + + /** + * {@code minecraft:block.copper.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_HIT = create(key("block.copper.hit")); + + /** + * {@code minecraft:block.copper.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_PLACE = create(key("block.copper.place")); + + /** + * {@code minecraft:block.copper.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_STEP = create(key("block.copper.step")); + + /** + * {@code minecraft:block.copper_bulb.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_BREAK = create(key("block.copper_bulb.break")); + + /** + * {@code minecraft:block.copper_bulb.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_FALL = create(key("block.copper_bulb.fall")); + + /** + * {@code minecraft:block.copper_bulb.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_HIT = create(key("block.copper_bulb.hit")); + + /** + * {@code minecraft:block.copper_bulb.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_PLACE = create(key("block.copper_bulb.place")); + + /** + * {@code minecraft:block.copper_bulb.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_STEP = create(key("block.copper_bulb.step")); + + /** + * {@code minecraft:block.copper_bulb.turn_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_TURN_OFF = create(key("block.copper_bulb.turn_off")); + + /** + * {@code minecraft:block.copper_bulb.turn_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_BULB_TURN_ON = create(key("block.copper_bulb.turn_on")); + + /** + * {@code minecraft:block.copper_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_DOOR_CLOSE = create(key("block.copper_door.close")); + + /** + * {@code minecraft:block.copper_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_DOOR_OPEN = create(key("block.copper_door.open")); + + /** + * {@code minecraft:block.copper_grate.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_GRATE_BREAK = create(key("block.copper_grate.break")); + + /** + * {@code minecraft:block.copper_grate.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_GRATE_FALL = create(key("block.copper_grate.fall")); + + /** + * {@code minecraft:block.copper_grate.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_GRATE_HIT = create(key("block.copper_grate.hit")); + + /** + * {@code minecraft:block.copper_grate.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_GRATE_PLACE = create(key("block.copper_grate.place")); + + /** + * {@code minecraft:block.copper_grate.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_GRATE_STEP = create(key("block.copper_grate.step")); + + /** + * {@code minecraft:block.copper_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_TRAPDOOR_CLOSE = create(key("block.copper_trapdoor.close")); + + /** + * {@code minecraft:block.copper_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_COPPER_TRAPDOOR_OPEN = create(key("block.copper_trapdoor.open")); + + /** + * {@code minecraft:block.coral_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CORAL_BLOCK_BREAK = create(key("block.coral_block.break")); + + /** + * {@code minecraft:block.coral_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CORAL_BLOCK_FALL = create(key("block.coral_block.fall")); + + /** + * {@code minecraft:block.coral_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CORAL_BLOCK_HIT = create(key("block.coral_block.hit")); + + /** + * {@code minecraft:block.coral_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CORAL_BLOCK_PLACE = create(key("block.coral_block.place")); + + /** + * {@code minecraft:block.coral_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CORAL_BLOCK_STEP = create(key("block.coral_block.step")); + + /** + * {@code minecraft:block.crafter.craft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CRAFTER_CRAFT = create(key("block.crafter.craft")); + + /** + * {@code minecraft:block.crafter.fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CRAFTER_FAIL = create(key("block.crafter.fail")); + + /** + * {@code minecraft:block.creaking_heart.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_BREAK = create(key("block.creaking_heart.break")); + + /** + * {@code minecraft:block.creaking_heart.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_FALL = create(key("block.creaking_heart.fall")); + + /** + * {@code minecraft:block.creaking_heart.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_HIT = create(key("block.creaking_heart.hit")); + + /** + * {@code minecraft:block.creaking_heart.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_HURT = create(key("block.creaking_heart.hurt")); + + /** + * {@code minecraft:block.creaking_heart.idle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_IDLE = create(key("block.creaking_heart.idle")); + + /** + * {@code minecraft:block.creaking_heart.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_PLACE = create(key("block.creaking_heart.place")); + + /** + * {@code minecraft:block.creaking_heart.spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_SPAWN = create(key("block.creaking_heart.spawn")); + + /** + * {@code minecraft:block.creaking_heart.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CREAKING_HEART_STEP = create(key("block.creaking_heart.step")); + + /** + * {@code minecraft:block.crop.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CROP_BREAK = create(key("block.crop.break")); + + /** + * {@code minecraft:block.decorated_pot.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_BREAK = create(key("block.decorated_pot.break")); + + /** + * {@code minecraft:block.decorated_pot.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_FALL = create(key("block.decorated_pot.fall")); + + /** + * {@code minecraft:block.decorated_pot.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_HIT = create(key("block.decorated_pot.hit")); + + /** + * {@code minecraft:block.decorated_pot.insert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_INSERT = create(key("block.decorated_pot.insert")); + + /** + * {@code minecraft:block.decorated_pot.insert_fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_INSERT_FAIL = create(key("block.decorated_pot.insert_fail")); + + /** + * {@code minecraft:block.decorated_pot.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_PLACE = create(key("block.decorated_pot.place")); + + /** + * {@code minecraft:block.decorated_pot.shatter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_SHATTER = create(key("block.decorated_pot.shatter")); + + /** + * {@code minecraft:block.decorated_pot.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DECORATED_POT_STEP = create(key("block.decorated_pot.step")); + + /** + * {@code minecraft:block.deepslate.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BREAK = create(key("block.deepslate.break")); + + /** + * {@code minecraft:block.deepslate.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_FALL = create(key("block.deepslate.fall")); + + /** + * {@code minecraft:block.deepslate.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_HIT = create(key("block.deepslate.hit")); + + /** + * {@code minecraft:block.deepslate.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_PLACE = create(key("block.deepslate.place")); + + /** + * {@code minecraft:block.deepslate.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_STEP = create(key("block.deepslate.step")); + + /** + * {@code minecraft:block.deepslate_bricks.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BRICKS_BREAK = create(key("block.deepslate_bricks.break")); + + /** + * {@code minecraft:block.deepslate_bricks.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BRICKS_FALL = create(key("block.deepslate_bricks.fall")); + + /** + * {@code minecraft:block.deepslate_bricks.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BRICKS_HIT = create(key("block.deepslate_bricks.hit")); + + /** + * {@code minecraft:block.deepslate_bricks.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BRICKS_PLACE = create(key("block.deepslate_bricks.place")); + + /** + * {@code minecraft:block.deepslate_bricks.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_BRICKS_STEP = create(key("block.deepslate_bricks.step")); + + /** + * {@code minecraft:block.deepslate_tiles.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_TILES_BREAK = create(key("block.deepslate_tiles.break")); + + /** + * {@code minecraft:block.deepslate_tiles.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_TILES_FALL = create(key("block.deepslate_tiles.fall")); + + /** + * {@code minecraft:block.deepslate_tiles.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_TILES_HIT = create(key("block.deepslate_tiles.hit")); + + /** + * {@code minecraft:block.deepslate_tiles.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_TILES_PLACE = create(key("block.deepslate_tiles.place")); + + /** + * {@code minecraft:block.deepslate_tiles.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEEPSLATE_TILES_STEP = create(key("block.deepslate_tiles.step")); + + /** + * {@code minecraft:block.dispenser.dispense} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DISPENSER_DISPENSE = create(key("block.dispenser.dispense")); + + /** + * {@code minecraft:block.dispenser.fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DISPENSER_FAIL = create(key("block.dispenser.fail")); + + /** + * {@code minecraft:block.dispenser.launch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DISPENSER_LAUNCH = create(key("block.dispenser.launch")); + + /** + * {@code minecraft:block.dripstone_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DRIPSTONE_BLOCK_BREAK = create(key("block.dripstone_block.break")); + + /** + * {@code minecraft:block.dripstone_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DRIPSTONE_BLOCK_FALL = create(key("block.dripstone_block.fall")); + + /** + * {@code minecraft:block.dripstone_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DRIPSTONE_BLOCK_HIT = create(key("block.dripstone_block.hit")); + + /** + * {@code minecraft:block.dripstone_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DRIPSTONE_BLOCK_PLACE = create(key("block.dripstone_block.place")); + + /** + * {@code minecraft:block.dripstone_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DRIPSTONE_BLOCK_STEP = create(key("block.dripstone_block.step")); + + /** + * {@code minecraft:block.enchantment_table.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ENCHANTMENT_TABLE_USE = create(key("block.enchantment_table.use")); + + /** + * {@code minecraft:block.end_gateway.spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_END_GATEWAY_SPAWN = create(key("block.end_gateway.spawn")); + + /** + * {@code minecraft:block.end_portal.spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_END_PORTAL_SPAWN = create(key("block.end_portal.spawn")); + + /** + * {@code minecraft:block.end_portal_frame.fill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_END_PORTAL_FRAME_FILL = create(key("block.end_portal_frame.fill")); + + /** + * {@code minecraft:block.ender_chest.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ENDER_CHEST_CLOSE = create(key("block.ender_chest.close")); + + /** + * {@code minecraft:block.ender_chest.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ENDER_CHEST_OPEN = create(key("block.ender_chest.open")); + + /** + * {@code minecraft:block.eyeblossom.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_EYEBLOSSOM_CLOSE = create(key("block.eyeblossom.close")); + + /** + * {@code minecraft:block.eyeblossom.close_long} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_EYEBLOSSOM_CLOSE_LONG = create(key("block.eyeblossom.close_long")); + + /** + * {@code minecraft:block.eyeblossom.idle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_EYEBLOSSOM_IDLE = create(key("block.eyeblossom.idle")); + + /** + * {@code minecraft:block.eyeblossom.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_EYEBLOSSOM_OPEN = create(key("block.eyeblossom.open")); + + /** + * {@code minecraft:block.eyeblossom.open_long} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_EYEBLOSSOM_OPEN_LONG = create(key("block.eyeblossom.open_long")); + + /** + * {@code minecraft:block.fence_gate.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FENCE_GATE_CLOSE = create(key("block.fence_gate.close")); + + /** + * {@code minecraft:block.fence_gate.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FENCE_GATE_OPEN = create(key("block.fence_gate.open")); + + /** + * {@code minecraft:block.fire.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FIRE_AMBIENT = create(key("block.fire.ambient")); + + /** + * {@code minecraft:block.fire.extinguish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FIRE_EXTINGUISH = create(key("block.fire.extinguish")); + + /** + * {@code minecraft:block.flowering_azalea.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FLOWERING_AZALEA_BREAK = create(key("block.flowering_azalea.break")); + + /** + * {@code minecraft:block.flowering_azalea.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FLOWERING_AZALEA_FALL = create(key("block.flowering_azalea.fall")); + + /** + * {@code minecraft:block.flowering_azalea.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FLOWERING_AZALEA_HIT = create(key("block.flowering_azalea.hit")); + + /** + * {@code minecraft:block.flowering_azalea.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FLOWERING_AZALEA_PLACE = create(key("block.flowering_azalea.place")); + + /** + * {@code minecraft:block.flowering_azalea.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FLOWERING_AZALEA_STEP = create(key("block.flowering_azalea.step")); + + /** + * {@code minecraft:block.froglight.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGLIGHT_BREAK = create(key("block.froglight.break")); + + /** + * {@code minecraft:block.froglight.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGLIGHT_FALL = create(key("block.froglight.fall")); + + /** + * {@code minecraft:block.froglight.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGLIGHT_HIT = create(key("block.froglight.hit")); + + /** + * {@code minecraft:block.froglight.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGLIGHT_PLACE = create(key("block.froglight.place")); + + /** + * {@code minecraft:block.froglight.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGLIGHT_STEP = create(key("block.froglight.step")); + + /** + * {@code minecraft:block.frogspawn.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_BREAK = create(key("block.frogspawn.break")); + + /** + * {@code minecraft:block.frogspawn.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_FALL = create(key("block.frogspawn.fall")); + + /** + * {@code minecraft:block.frogspawn.hatch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_HATCH = create(key("block.frogspawn.hatch")); + + /** + * {@code minecraft:block.frogspawn.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_HIT = create(key("block.frogspawn.hit")); + + /** + * {@code minecraft:block.frogspawn.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_PLACE = create(key("block.frogspawn.place")); + + /** + * {@code minecraft:block.frogspawn.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FROGSPAWN_STEP = create(key("block.frogspawn.step")); + + /** + * {@code minecraft:block.fungus.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FUNGUS_BREAK = create(key("block.fungus.break")); + + /** + * {@code minecraft:block.fungus.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FUNGUS_FALL = create(key("block.fungus.fall")); + + /** + * {@code minecraft:block.fungus.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FUNGUS_HIT = create(key("block.fungus.hit")); + + /** + * {@code minecraft:block.fungus.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FUNGUS_PLACE = create(key("block.fungus.place")); + + /** + * {@code minecraft:block.fungus.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FUNGUS_STEP = create(key("block.fungus.step")); + + /** + * {@code minecraft:block.furnace.fire_crackle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_FURNACE_FIRE_CRACKLE = create(key("block.furnace.fire_crackle")); + + /** + * {@code minecraft:block.gilded_blackstone.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GILDED_BLACKSTONE_BREAK = create(key("block.gilded_blackstone.break")); + + /** + * {@code minecraft:block.gilded_blackstone.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GILDED_BLACKSTONE_FALL = create(key("block.gilded_blackstone.fall")); + + /** + * {@code minecraft:block.gilded_blackstone.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GILDED_BLACKSTONE_HIT = create(key("block.gilded_blackstone.hit")); + + /** + * {@code minecraft:block.gilded_blackstone.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GILDED_BLACKSTONE_PLACE = create(key("block.gilded_blackstone.place")); + + /** + * {@code minecraft:block.gilded_blackstone.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GILDED_BLACKSTONE_STEP = create(key("block.gilded_blackstone.step")); + + /** + * {@code minecraft:block.glass.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GLASS_BREAK = create(key("block.glass.break")); + + /** + * {@code minecraft:block.glass.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GLASS_FALL = create(key("block.glass.fall")); + + /** + * {@code minecraft:block.glass.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GLASS_HIT = create(key("block.glass.hit")); + + /** + * {@code minecraft:block.glass.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GLASS_PLACE = create(key("block.glass.place")); + + /** + * {@code minecraft:block.glass.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GLASS_STEP = create(key("block.glass.step")); + + /** + * {@code minecraft:block.grass.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRASS_BREAK = create(key("block.grass.break")); + + /** + * {@code minecraft:block.grass.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRASS_FALL = create(key("block.grass.fall")); + + /** + * {@code minecraft:block.grass.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRASS_HIT = create(key("block.grass.hit")); + + /** + * {@code minecraft:block.grass.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRASS_PLACE = create(key("block.grass.place")); + + /** + * {@code minecraft:block.grass.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRASS_STEP = create(key("block.grass.step")); + + /** + * {@code minecraft:block.gravel.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRAVEL_BREAK = create(key("block.gravel.break")); + + /** + * {@code minecraft:block.gravel.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRAVEL_FALL = create(key("block.gravel.fall")); + + /** + * {@code minecraft:block.gravel.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRAVEL_HIT = create(key("block.gravel.hit")); + + /** + * {@code minecraft:block.gravel.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRAVEL_PLACE = create(key("block.gravel.place")); + + /** + * {@code minecraft:block.gravel.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRAVEL_STEP = create(key("block.gravel.step")); + + /** + * {@code minecraft:block.grindstone.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GRINDSTONE_USE = create(key("block.grindstone.use")); + + /** + * {@code minecraft:block.growing_plant.crop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_GROWING_PLANT_CROP = create(key("block.growing_plant.crop")); + + /** + * {@code minecraft:block.hanging_roots.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_ROOTS_BREAK = create(key("block.hanging_roots.break")); + + /** + * {@code minecraft:block.hanging_roots.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_ROOTS_FALL = create(key("block.hanging_roots.fall")); + + /** + * {@code minecraft:block.hanging_roots.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_ROOTS_HIT = create(key("block.hanging_roots.hit")); + + /** + * {@code minecraft:block.hanging_roots.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_ROOTS_PLACE = create(key("block.hanging_roots.place")); + + /** + * {@code minecraft:block.hanging_roots.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_ROOTS_STEP = create(key("block.hanging_roots.step")); + + /** + * {@code minecraft:block.hanging_sign.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_BREAK = create(key("block.hanging_sign.break")); + + /** + * {@code minecraft:block.hanging_sign.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_FALL = create(key("block.hanging_sign.fall")); + + /** + * {@code minecraft:block.hanging_sign.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_HIT = create(key("block.hanging_sign.hit")); + + /** + * {@code minecraft:block.hanging_sign.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_PLACE = create(key("block.hanging_sign.place")); + + /** + * {@code minecraft:block.hanging_sign.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_STEP = create(key("block.hanging_sign.step")); + + /** + * {@code minecraft:block.hanging_sign.waxed_interact_fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HANGING_SIGN_WAXED_INTERACT_FAIL = create(key("block.hanging_sign.waxed_interact_fail")); + + /** + * {@code minecraft:block.heavy_core.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HEAVY_CORE_BREAK = create(key("block.heavy_core.break")); + + /** + * {@code minecraft:block.heavy_core.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HEAVY_CORE_FALL = create(key("block.heavy_core.fall")); + + /** + * {@code minecraft:block.heavy_core.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HEAVY_CORE_HIT = create(key("block.heavy_core.hit")); + + /** + * {@code minecraft:block.heavy_core.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HEAVY_CORE_PLACE = create(key("block.heavy_core.place")); + + /** + * {@code minecraft:block.heavy_core.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HEAVY_CORE_STEP = create(key("block.heavy_core.step")); + + /** + * {@code minecraft:block.honey_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_BREAK = create(key("block.honey_block.break")); + + /** + * {@code minecraft:block.honey_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_FALL = create(key("block.honey_block.fall")); + + /** + * {@code minecraft:block.honey_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_HIT = create(key("block.honey_block.hit")); + + /** + * {@code minecraft:block.honey_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_PLACE = create(key("block.honey_block.place")); + + /** + * {@code minecraft:block.honey_block.slide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_SLIDE = create(key("block.honey_block.slide")); + + /** + * {@code minecraft:block.honey_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_HONEY_BLOCK_STEP = create(key("block.honey_block.step")); + + /** + * {@code minecraft:block.iron_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_IRON_DOOR_CLOSE = create(key("block.iron_door.close")); + + /** + * {@code minecraft:block.iron_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_IRON_DOOR_OPEN = create(key("block.iron_door.open")); + + /** + * {@code minecraft:block.iron_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_IRON_TRAPDOOR_CLOSE = create(key("block.iron_trapdoor.close")); + + /** + * {@code minecraft:block.iron_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_IRON_TRAPDOOR_OPEN = create(key("block.iron_trapdoor.open")); + + /** + * {@code minecraft:block.ladder.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LADDER_BREAK = create(key("block.ladder.break")); + + /** + * {@code minecraft:block.ladder.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LADDER_FALL = create(key("block.ladder.fall")); + + /** + * {@code minecraft:block.ladder.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LADDER_HIT = create(key("block.ladder.hit")); + + /** + * {@code minecraft:block.ladder.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LADDER_PLACE = create(key("block.ladder.place")); + + /** + * {@code minecraft:block.ladder.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LADDER_STEP = create(key("block.ladder.step")); + + /** + * {@code minecraft:block.lantern.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LANTERN_BREAK = create(key("block.lantern.break")); + + /** + * {@code minecraft:block.lantern.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LANTERN_FALL = create(key("block.lantern.fall")); + + /** + * {@code minecraft:block.lantern.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LANTERN_HIT = create(key("block.lantern.hit")); + + /** + * {@code minecraft:block.lantern.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LANTERN_PLACE = create(key("block.lantern.place")); + + /** + * {@code minecraft:block.lantern.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LANTERN_STEP = create(key("block.lantern.step")); + + /** + * {@code minecraft:block.large_amethyst_bud.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LARGE_AMETHYST_BUD_BREAK = create(key("block.large_amethyst_bud.break")); + + /** + * {@code minecraft:block.large_amethyst_bud.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LARGE_AMETHYST_BUD_PLACE = create(key("block.large_amethyst_bud.place")); + + /** + * {@code minecraft:block.lava.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LAVA_AMBIENT = create(key("block.lava.ambient")); + + /** + * {@code minecraft:block.lava.extinguish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LAVA_EXTINGUISH = create(key("block.lava.extinguish")); + + /** + * {@code minecraft:block.lava.pop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LAVA_POP = create(key("block.lava.pop")); + + /** + * {@code minecraft:block.lever.click} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LEVER_CLICK = create(key("block.lever.click")); + + /** + * {@code minecraft:block.lily_pad.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LILY_PAD_PLACE = create(key("block.lily_pad.place")); + + /** + * {@code minecraft:block.lodestone.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LODESTONE_BREAK = create(key("block.lodestone.break")); + + /** + * {@code minecraft:block.lodestone.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LODESTONE_FALL = create(key("block.lodestone.fall")); + + /** + * {@code minecraft:block.lodestone.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LODESTONE_HIT = create(key("block.lodestone.hit")); + + /** + * {@code minecraft:block.lodestone.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LODESTONE_PLACE = create(key("block.lodestone.place")); + + /** + * {@code minecraft:block.lodestone.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_LODESTONE_STEP = create(key("block.lodestone.step")); + + /** + * {@code minecraft:block.mangrove_roots.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MANGROVE_ROOTS_BREAK = create(key("block.mangrove_roots.break")); + + /** + * {@code minecraft:block.mangrove_roots.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MANGROVE_ROOTS_FALL = create(key("block.mangrove_roots.fall")); + + /** + * {@code minecraft:block.mangrove_roots.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MANGROVE_ROOTS_HIT = create(key("block.mangrove_roots.hit")); + + /** + * {@code minecraft:block.mangrove_roots.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MANGROVE_ROOTS_PLACE = create(key("block.mangrove_roots.place")); + + /** + * {@code minecraft:block.mangrove_roots.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MANGROVE_ROOTS_STEP = create(key("block.mangrove_roots.step")); + + /** + * {@code minecraft:block.medium_amethyst_bud.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MEDIUM_AMETHYST_BUD_BREAK = create(key("block.medium_amethyst_bud.break")); + + /** + * {@code minecraft:block.medium_amethyst_bud.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MEDIUM_AMETHYST_BUD_PLACE = create(key("block.medium_amethyst_bud.place")); + + /** + * {@code minecraft:block.metal.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_BREAK = create(key("block.metal.break")); + + /** + * {@code minecraft:block.metal.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_FALL = create(key("block.metal.fall")); + + /** + * {@code minecraft:block.metal.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_HIT = create(key("block.metal.hit")); + + /** + * {@code minecraft:block.metal.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_PLACE = create(key("block.metal.place")); + + /** + * {@code minecraft:block.metal.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_STEP = create(key("block.metal.step")); + + /** + * {@code minecraft:block.metal_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_PRESSURE_PLATE_CLICK_OFF = create(key("block.metal_pressure_plate.click_off")); + + /** + * {@code minecraft:block.metal_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_METAL_PRESSURE_PLATE_CLICK_ON = create(key("block.metal_pressure_plate.click_on")); + + /** + * {@code minecraft:block.moss.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_BREAK = create(key("block.moss.break")); + + /** + * {@code minecraft:block.moss.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_FALL = create(key("block.moss.fall")); + + /** + * {@code minecraft:block.moss.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_HIT = create(key("block.moss.hit")); + + /** + * {@code minecraft:block.moss.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_PLACE = create(key("block.moss.place")); + + /** + * {@code minecraft:block.moss.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_STEP = create(key("block.moss.step")); + + /** + * {@code minecraft:block.moss_carpet.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_CARPET_BREAK = create(key("block.moss_carpet.break")); + + /** + * {@code minecraft:block.moss_carpet.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_CARPET_FALL = create(key("block.moss_carpet.fall")); + + /** + * {@code minecraft:block.moss_carpet.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_CARPET_HIT = create(key("block.moss_carpet.hit")); + + /** + * {@code minecraft:block.moss_carpet.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_CARPET_PLACE = create(key("block.moss_carpet.place")); + + /** + * {@code minecraft:block.moss_carpet.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MOSS_CARPET_STEP = create(key("block.moss_carpet.step")); + + /** + * {@code minecraft:block.mud.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BREAK = create(key("block.mud.break")); + + /** + * {@code minecraft:block.mud.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_FALL = create(key("block.mud.fall")); + + /** + * {@code minecraft:block.mud.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_HIT = create(key("block.mud.hit")); + + /** + * {@code minecraft:block.mud.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_PLACE = create(key("block.mud.place")); + + /** + * {@code minecraft:block.mud.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_STEP = create(key("block.mud.step")); + + /** + * {@code minecraft:block.mud_bricks.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BRICKS_BREAK = create(key("block.mud_bricks.break")); + + /** + * {@code minecraft:block.mud_bricks.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BRICKS_FALL = create(key("block.mud_bricks.fall")); + + /** + * {@code minecraft:block.mud_bricks.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BRICKS_HIT = create(key("block.mud_bricks.hit")); + + /** + * {@code minecraft:block.mud_bricks.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BRICKS_PLACE = create(key("block.mud_bricks.place")); + + /** + * {@code minecraft:block.mud_bricks.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUD_BRICKS_STEP = create(key("block.mud_bricks.step")); + + /** + * {@code minecraft:block.muddy_mangrove_roots.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUDDY_MANGROVE_ROOTS_BREAK = create(key("block.muddy_mangrove_roots.break")); + + /** + * {@code minecraft:block.muddy_mangrove_roots.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUDDY_MANGROVE_ROOTS_FALL = create(key("block.muddy_mangrove_roots.fall")); + + /** + * {@code minecraft:block.muddy_mangrove_roots.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUDDY_MANGROVE_ROOTS_HIT = create(key("block.muddy_mangrove_roots.hit")); + + /** + * {@code minecraft:block.muddy_mangrove_roots.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUDDY_MANGROVE_ROOTS_PLACE = create(key("block.muddy_mangrove_roots.place")); + + /** + * {@code minecraft:block.muddy_mangrove_roots.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_MUDDY_MANGROVE_ROOTS_STEP = create(key("block.muddy_mangrove_roots.step")); + + /** + * {@code minecraft:block.nether_bricks.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_BRICKS_BREAK = create(key("block.nether_bricks.break")); + + /** + * {@code minecraft:block.nether_bricks.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_BRICKS_FALL = create(key("block.nether_bricks.fall")); + + /** + * {@code minecraft:block.nether_bricks.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_BRICKS_HIT = create(key("block.nether_bricks.hit")); + + /** + * {@code minecraft:block.nether_bricks.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_BRICKS_PLACE = create(key("block.nether_bricks.place")); + + /** + * {@code minecraft:block.nether_bricks.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_BRICKS_STEP = create(key("block.nether_bricks.step")); + + /** + * {@code minecraft:block.nether_gold_ore.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_GOLD_ORE_BREAK = create(key("block.nether_gold_ore.break")); + + /** + * {@code minecraft:block.nether_gold_ore.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_GOLD_ORE_FALL = create(key("block.nether_gold_ore.fall")); + + /** + * {@code minecraft:block.nether_gold_ore.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_GOLD_ORE_HIT = create(key("block.nether_gold_ore.hit")); + + /** + * {@code minecraft:block.nether_gold_ore.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_GOLD_ORE_PLACE = create(key("block.nether_gold_ore.place")); + + /** + * {@code minecraft:block.nether_gold_ore.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_GOLD_ORE_STEP = create(key("block.nether_gold_ore.step")); + + /** + * {@code minecraft:block.nether_ore.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_ORE_BREAK = create(key("block.nether_ore.break")); + + /** + * {@code minecraft:block.nether_ore.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_ORE_FALL = create(key("block.nether_ore.fall")); + + /** + * {@code minecraft:block.nether_ore.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_ORE_HIT = create(key("block.nether_ore.hit")); + + /** + * {@code minecraft:block.nether_ore.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_ORE_PLACE = create(key("block.nether_ore.place")); + + /** + * {@code minecraft:block.nether_ore.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_ORE_STEP = create(key("block.nether_ore.step")); + + /** + * {@code minecraft:block.nether_sprouts.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_SPROUTS_BREAK = create(key("block.nether_sprouts.break")); + + /** + * {@code minecraft:block.nether_sprouts.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_SPROUTS_FALL = create(key("block.nether_sprouts.fall")); + + /** + * {@code minecraft:block.nether_sprouts.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_SPROUTS_HIT = create(key("block.nether_sprouts.hit")); + + /** + * {@code minecraft:block.nether_sprouts.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_SPROUTS_PLACE = create(key("block.nether_sprouts.place")); + + /** + * {@code minecraft:block.nether_sprouts.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_SPROUTS_STEP = create(key("block.nether_sprouts.step")); + + /** + * {@code minecraft:block.nether_wart.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WART_BREAK = create(key("block.nether_wart.break")); + + /** + * {@code minecraft:block.nether_wood.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_BREAK = create(key("block.nether_wood.break")); + + /** + * {@code minecraft:block.nether_wood.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_FALL = create(key("block.nether_wood.fall")); + + /** + * {@code minecraft:block.nether_wood.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HIT = create(key("block.nether_wood.hit")); + + /** + * {@code minecraft:block.nether_wood.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_PLACE = create(key("block.nether_wood.place")); + + /** + * {@code minecraft:block.nether_wood.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_STEP = create(key("block.nether_wood.step")); + + /** + * {@code minecraft:block.nether_wood_button.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_BUTTON_CLICK_OFF = create(key("block.nether_wood_button.click_off")); + + /** + * {@code minecraft:block.nether_wood_button.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_BUTTON_CLICK_ON = create(key("block.nether_wood_button.click_on")); + + /** + * {@code minecraft:block.nether_wood_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_DOOR_CLOSE = create(key("block.nether_wood_door.close")); + + /** + * {@code minecraft:block.nether_wood_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_DOOR_OPEN = create(key("block.nether_wood_door.open")); + + /** + * {@code minecraft:block.nether_wood_fence_gate.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE = create(key("block.nether_wood_fence_gate.close")); + + /** + * {@code minecraft:block.nether_wood_fence_gate.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_FENCE_GATE_OPEN = create(key("block.nether_wood_fence_gate.open")); + + /** + * {@code minecraft:block.nether_wood_hanging_sign.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK = create(key("block.nether_wood_hanging_sign.break")); + + /** + * {@code minecraft:block.nether_wood_hanging_sign.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HANGING_SIGN_FALL = create(key("block.nether_wood_hanging_sign.fall")); + + /** + * {@code minecraft:block.nether_wood_hanging_sign.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HANGING_SIGN_HIT = create(key("block.nether_wood_hanging_sign.hit")); + + /** + * {@code minecraft:block.nether_wood_hanging_sign.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HANGING_SIGN_PLACE = create(key("block.nether_wood_hanging_sign.place")); + + /** + * {@code minecraft:block.nether_wood_hanging_sign.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_HANGING_SIGN_STEP = create(key("block.nether_wood_hanging_sign.step")); + + /** + * {@code minecraft:block.nether_wood_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_OFF = create(key("block.nether_wood_pressure_plate.click_off")); + + /** + * {@code minecraft:block.nether_wood_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON = create(key("block.nether_wood_pressure_plate.click_on")); + + /** + * {@code minecraft:block.nether_wood_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_TRAPDOOR_CLOSE = create(key("block.nether_wood_trapdoor.close")); + + /** + * {@code minecraft:block.nether_wood_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHER_WOOD_TRAPDOOR_OPEN = create(key("block.nether_wood_trapdoor.open")); + + /** + * {@code minecraft:block.netherite_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERITE_BLOCK_BREAK = create(key("block.netherite_block.break")); + + /** + * {@code minecraft:block.netherite_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERITE_BLOCK_FALL = create(key("block.netherite_block.fall")); + + /** + * {@code minecraft:block.netherite_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERITE_BLOCK_HIT = create(key("block.netherite_block.hit")); + + /** + * {@code minecraft:block.netherite_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERITE_BLOCK_PLACE = create(key("block.netherite_block.place")); + + /** + * {@code minecraft:block.netherite_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERITE_BLOCK_STEP = create(key("block.netherite_block.step")); + + /** + * {@code minecraft:block.netherrack.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERRACK_BREAK = create(key("block.netherrack.break")); + + /** + * {@code minecraft:block.netherrack.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERRACK_FALL = create(key("block.netherrack.fall")); + + /** + * {@code minecraft:block.netherrack.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERRACK_HIT = create(key("block.netherrack.hit")); + + /** + * {@code minecraft:block.netherrack.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERRACK_PLACE = create(key("block.netherrack.place")); + + /** + * {@code minecraft:block.netherrack.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NETHERRACK_STEP = create(key("block.netherrack.step")); + + /** + * {@code minecraft:block.note_block.banjo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_BANJO = create(key("block.note_block.banjo")); + + /** + * {@code minecraft:block.note_block.basedrum} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_BASEDRUM = create(key("block.note_block.basedrum")); + + /** + * {@code minecraft:block.note_block.bass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_BASS = create(key("block.note_block.bass")); + + /** + * {@code minecraft:block.note_block.bell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_BELL = create(key("block.note_block.bell")); + + /** + * {@code minecraft:block.note_block.bit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_BIT = create(key("block.note_block.bit")); + + /** + * {@code minecraft:block.note_block.chime} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_CHIME = create(key("block.note_block.chime")); + + /** + * {@code minecraft:block.note_block.cow_bell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_COW_BELL = create(key("block.note_block.cow_bell")); + + /** + * {@code minecraft:block.note_block.didgeridoo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_DIDGERIDOO = create(key("block.note_block.didgeridoo")); + + /** + * {@code minecraft:block.note_block.flute} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_FLUTE = create(key("block.note_block.flute")); + + /** + * {@code minecraft:block.note_block.guitar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_GUITAR = create(key("block.note_block.guitar")); + + /** + * {@code minecraft:block.note_block.harp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_HARP = create(key("block.note_block.harp")); + + /** + * {@code minecraft:block.note_block.hat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_HAT = create(key("block.note_block.hat")); + + /** + * {@code minecraft:block.note_block.imitate.creeper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_CREEPER = create(key("block.note_block.imitate.creeper")); + + /** + * {@code minecraft:block.note_block.imitate.ender_dragon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON = create(key("block.note_block.imitate.ender_dragon")); + + /** + * {@code minecraft:block.note_block.imitate.piglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_PIGLIN = create(key("block.note_block.imitate.piglin")); + + /** + * {@code minecraft:block.note_block.imitate.skeleton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_SKELETON = create(key("block.note_block.imitate.skeleton")); + + /** + * {@code minecraft:block.note_block.imitate.wither_skeleton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON = create(key("block.note_block.imitate.wither_skeleton")); + + /** + * {@code minecraft:block.note_block.imitate.zombie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE = create(key("block.note_block.imitate.zombie")); + + /** + * {@code minecraft:block.note_block.iron_xylophone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_IRON_XYLOPHONE = create(key("block.note_block.iron_xylophone")); + + /** + * {@code minecraft:block.note_block.pling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_PLING = create(key("block.note_block.pling")); + + /** + * {@code minecraft:block.note_block.snare} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_SNARE = create(key("block.note_block.snare")); + + /** + * {@code minecraft:block.note_block.xylophone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NOTE_BLOCK_XYLOPHONE = create(key("block.note_block.xylophone")); + + /** + * {@code minecraft:block.nylium.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NYLIUM_BREAK = create(key("block.nylium.break")); + + /** + * {@code minecraft:block.nylium.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NYLIUM_FALL = create(key("block.nylium.fall")); + + /** + * {@code minecraft:block.nylium.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NYLIUM_HIT = create(key("block.nylium.hit")); + + /** + * {@code minecraft:block.nylium.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NYLIUM_PLACE = create(key("block.nylium.place")); + + /** + * {@code minecraft:block.nylium.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_NYLIUM_STEP = create(key("block.nylium.step")); + + /** + * {@code minecraft:block.packed_mud.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PACKED_MUD_BREAK = create(key("block.packed_mud.break")); + + /** + * {@code minecraft:block.packed_mud.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PACKED_MUD_FALL = create(key("block.packed_mud.fall")); + + /** + * {@code minecraft:block.packed_mud.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PACKED_MUD_HIT = create(key("block.packed_mud.hit")); + + /** + * {@code minecraft:block.packed_mud.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PACKED_MUD_PLACE = create(key("block.packed_mud.place")); + + /** + * {@code minecraft:block.packed_mud.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PACKED_MUD_STEP = create(key("block.packed_mud.step")); + + /** + * {@code minecraft:block.pale_hanging_moss.idle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PALE_HANGING_MOSS_IDLE = create(key("block.pale_hanging_moss.idle")); + + /** + * {@code minecraft:block.pink_petals.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PINK_PETALS_BREAK = create(key("block.pink_petals.break")); + + /** + * {@code minecraft:block.pink_petals.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PINK_PETALS_FALL = create(key("block.pink_petals.fall")); + + /** + * {@code minecraft:block.pink_petals.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PINK_PETALS_HIT = create(key("block.pink_petals.hit")); + + /** + * {@code minecraft:block.pink_petals.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PINK_PETALS_PLACE = create(key("block.pink_petals.place")); + + /** + * {@code minecraft:block.pink_petals.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PINK_PETALS_STEP = create(key("block.pink_petals.step")); + + /** + * {@code minecraft:block.piston.contract} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PISTON_CONTRACT = create(key("block.piston.contract")); + + /** + * {@code minecraft:block.piston.extend} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PISTON_EXTEND = create(key("block.piston.extend")); + + /** + * {@code minecraft:block.pointed_dripstone.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_BREAK = create(key("block.pointed_dripstone.break")); + + /** + * {@code minecraft:block.pointed_dripstone.drip_lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_DRIP_LAVA = create(key("block.pointed_dripstone.drip_lava")); + + /** + * {@code minecraft:block.pointed_dripstone.drip_lava_into_cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON = create(key("block.pointed_dripstone.drip_lava_into_cauldron")); + + /** + * {@code minecraft:block.pointed_dripstone.drip_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_DRIP_WATER = create(key("block.pointed_dripstone.drip_water")); + + /** + * {@code minecraft:block.pointed_dripstone.drip_water_into_cauldron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON = create(key("block.pointed_dripstone.drip_water_into_cauldron")); + + /** + * {@code minecraft:block.pointed_dripstone.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_FALL = create(key("block.pointed_dripstone.fall")); + + /** + * {@code minecraft:block.pointed_dripstone.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_HIT = create(key("block.pointed_dripstone.hit")); + + /** + * {@code minecraft:block.pointed_dripstone.land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_LAND = create(key("block.pointed_dripstone.land")); + + /** + * {@code minecraft:block.pointed_dripstone.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_PLACE = create(key("block.pointed_dripstone.place")); + + /** + * {@code minecraft:block.pointed_dripstone.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POINTED_DRIPSTONE_STEP = create(key("block.pointed_dripstone.step")); + + /** + * {@code minecraft:block.polished_deepslate.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_DEEPSLATE_BREAK = create(key("block.polished_deepslate.break")); + + /** + * {@code minecraft:block.polished_deepslate.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_DEEPSLATE_FALL = create(key("block.polished_deepslate.fall")); + + /** + * {@code minecraft:block.polished_deepslate.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_DEEPSLATE_HIT = create(key("block.polished_deepslate.hit")); + + /** + * {@code minecraft:block.polished_deepslate.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_DEEPSLATE_PLACE = create(key("block.polished_deepslate.place")); + + /** + * {@code minecraft:block.polished_deepslate.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_DEEPSLATE_STEP = create(key("block.polished_deepslate.step")); + + /** + * {@code minecraft:block.polished_tuff.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_TUFF_BREAK = create(key("block.polished_tuff.break")); + + /** + * {@code minecraft:block.polished_tuff.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_TUFF_FALL = create(key("block.polished_tuff.fall")); + + /** + * {@code minecraft:block.polished_tuff.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_TUFF_HIT = create(key("block.polished_tuff.hit")); + + /** + * {@code minecraft:block.polished_tuff.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_TUFF_PLACE = create(key("block.polished_tuff.place")); + + /** + * {@code minecraft:block.polished_tuff.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POLISHED_TUFF_STEP = create(key("block.polished_tuff.step")); + + /** + * {@code minecraft:block.portal.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PORTAL_AMBIENT = create(key("block.portal.ambient")); + + /** + * {@code minecraft:block.portal.travel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PORTAL_TRAVEL = create(key("block.portal.travel")); + + /** + * {@code minecraft:block.portal.trigger} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PORTAL_TRIGGER = create(key("block.portal.trigger")); + + /** + * {@code minecraft:block.powder_snow.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POWDER_SNOW_BREAK = create(key("block.powder_snow.break")); + + /** + * {@code minecraft:block.powder_snow.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POWDER_SNOW_FALL = create(key("block.powder_snow.fall")); + + /** + * {@code minecraft:block.powder_snow.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POWDER_SNOW_HIT = create(key("block.powder_snow.hit")); + + /** + * {@code minecraft:block.powder_snow.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POWDER_SNOW_PLACE = create(key("block.powder_snow.place")); + + /** + * {@code minecraft:block.powder_snow.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_POWDER_SNOW_STEP = create(key("block.powder_snow.step")); + + /** + * {@code minecraft:block.pumpkin.carve} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PUMPKIN_CARVE = create(key("block.pumpkin.carve")); + + /** + * {@code minecraft:block.redstone_torch.burnout} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_REDSTONE_TORCH_BURNOUT = create(key("block.redstone_torch.burnout")); + + /** + * {@code minecraft:block.resin.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BREAK = create(key("block.resin.break")); + + /** + * {@code minecraft:block.resin.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_FALL = create(key("block.resin.fall")); + + /** + * {@code minecraft:block.resin.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_PLACE = create(key("block.resin.place")); + + /** + * {@code minecraft:block.resin.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_STEP = create(key("block.resin.step")); + + /** + * {@code minecraft:block.resin_bricks.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BRICKS_BREAK = create(key("block.resin_bricks.break")); + + /** + * {@code minecraft:block.resin_bricks.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BRICKS_FALL = create(key("block.resin_bricks.fall")); + + /** + * {@code minecraft:block.resin_bricks.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BRICKS_HIT = create(key("block.resin_bricks.hit")); + + /** + * {@code minecraft:block.resin_bricks.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BRICKS_PLACE = create(key("block.resin_bricks.place")); + + /** + * {@code minecraft:block.resin_bricks.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESIN_BRICKS_STEP = create(key("block.resin_bricks.step")); + + /** + * {@code minecraft:block.respawn_anchor.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESPAWN_ANCHOR_AMBIENT = create(key("block.respawn_anchor.ambient")); + + /** + * {@code minecraft:block.respawn_anchor.charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESPAWN_ANCHOR_CHARGE = create(key("block.respawn_anchor.charge")); + + /** + * {@code minecraft:block.respawn_anchor.deplete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESPAWN_ANCHOR_DEPLETE = create(key("block.respawn_anchor.deplete")); + + /** + * {@code minecraft:block.respawn_anchor.set_spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_RESPAWN_ANCHOR_SET_SPAWN = create(key("block.respawn_anchor.set_spawn")); + + /** + * {@code minecraft:block.rooted_dirt.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTED_DIRT_BREAK = create(key("block.rooted_dirt.break")); + + /** + * {@code minecraft:block.rooted_dirt.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTED_DIRT_FALL = create(key("block.rooted_dirt.fall")); + + /** + * {@code minecraft:block.rooted_dirt.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTED_DIRT_HIT = create(key("block.rooted_dirt.hit")); + + /** + * {@code minecraft:block.rooted_dirt.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTED_DIRT_PLACE = create(key("block.rooted_dirt.place")); + + /** + * {@code minecraft:block.rooted_dirt.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTED_DIRT_STEP = create(key("block.rooted_dirt.step")); + + /** + * {@code minecraft:block.roots.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTS_BREAK = create(key("block.roots.break")); + + /** + * {@code minecraft:block.roots.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTS_FALL = create(key("block.roots.fall")); + + /** + * {@code minecraft:block.roots.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTS_HIT = create(key("block.roots.hit")); + + /** + * {@code minecraft:block.roots.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTS_PLACE = create(key("block.roots.place")); + + /** + * {@code minecraft:block.roots.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ROOTS_STEP = create(key("block.roots.step")); + + /** + * {@code minecraft:block.sand.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SAND_BREAK = create(key("block.sand.break")); + + /** + * {@code minecraft:block.sand.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SAND_FALL = create(key("block.sand.fall")); + + /** + * {@code minecraft:block.sand.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SAND_HIT = create(key("block.sand.hit")); + + /** + * {@code minecraft:block.sand.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SAND_PLACE = create(key("block.sand.place")); + + /** + * {@code minecraft:block.sand.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SAND_STEP = create(key("block.sand.step")); + + /** + * {@code minecraft:block.scaffolding.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCAFFOLDING_BREAK = create(key("block.scaffolding.break")); + + /** + * {@code minecraft:block.scaffolding.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCAFFOLDING_FALL = create(key("block.scaffolding.fall")); + + /** + * {@code minecraft:block.scaffolding.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCAFFOLDING_HIT = create(key("block.scaffolding.hit")); + + /** + * {@code minecraft:block.scaffolding.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCAFFOLDING_PLACE = create(key("block.scaffolding.place")); + + /** + * {@code minecraft:block.scaffolding.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCAFFOLDING_STEP = create(key("block.scaffolding.step")); + + /** + * {@code minecraft:block.sculk.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_BREAK = create(key("block.sculk.break")); + + /** + * {@code minecraft:block.sculk.charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CHARGE = create(key("block.sculk.charge")); + + /** + * {@code minecraft:block.sculk.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_FALL = create(key("block.sculk.fall")); + + /** + * {@code minecraft:block.sculk.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_HIT = create(key("block.sculk.hit")); + + /** + * {@code minecraft:block.sculk.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_PLACE = create(key("block.sculk.place")); + + /** + * {@code minecraft:block.sculk.spread} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SPREAD = create(key("block.sculk.spread")); + + /** + * {@code minecraft:block.sculk.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_STEP = create(key("block.sculk.step")); + + /** + * {@code minecraft:block.sculk_catalyst.bloom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_BLOOM = create(key("block.sculk_catalyst.bloom")); + + /** + * {@code minecraft:block.sculk_catalyst.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_BREAK = create(key("block.sculk_catalyst.break")); + + /** + * {@code minecraft:block.sculk_catalyst.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_FALL = create(key("block.sculk_catalyst.fall")); + + /** + * {@code minecraft:block.sculk_catalyst.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_HIT = create(key("block.sculk_catalyst.hit")); + + /** + * {@code minecraft:block.sculk_catalyst.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_PLACE = create(key("block.sculk_catalyst.place")); + + /** + * {@code minecraft:block.sculk_catalyst.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_CATALYST_STEP = create(key("block.sculk_catalyst.step")); + + /** + * {@code minecraft:block.sculk_sensor.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_BREAK = create(key("block.sculk_sensor.break")); + + /** + * {@code minecraft:block.sculk_sensor.clicking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_CLICKING = create(key("block.sculk_sensor.clicking")); + + /** + * {@code minecraft:block.sculk_sensor.clicking_stop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_CLICKING_STOP = create(key("block.sculk_sensor.clicking_stop")); + + /** + * {@code minecraft:block.sculk_sensor.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_FALL = create(key("block.sculk_sensor.fall")); + + /** + * {@code minecraft:block.sculk_sensor.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_HIT = create(key("block.sculk_sensor.hit")); + + /** + * {@code minecraft:block.sculk_sensor.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_PLACE = create(key("block.sculk_sensor.place")); + + /** + * {@code minecraft:block.sculk_sensor.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SENSOR_STEP = create(key("block.sculk_sensor.step")); + + /** + * {@code minecraft:block.sculk_shrieker.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_BREAK = create(key("block.sculk_shrieker.break")); + + /** + * {@code minecraft:block.sculk_shrieker.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_FALL = create(key("block.sculk_shrieker.fall")); + + /** + * {@code minecraft:block.sculk_shrieker.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_HIT = create(key("block.sculk_shrieker.hit")); + + /** + * {@code minecraft:block.sculk_shrieker.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_PLACE = create(key("block.sculk_shrieker.place")); + + /** + * {@code minecraft:block.sculk_shrieker.shriek} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_SHRIEK = create(key("block.sculk_shrieker.shriek")); + + /** + * {@code minecraft:block.sculk_shrieker.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_SHRIEKER_STEP = create(key("block.sculk_shrieker.step")); + + /** + * {@code minecraft:block.sculk_vein.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_VEIN_BREAK = create(key("block.sculk_vein.break")); + + /** + * {@code minecraft:block.sculk_vein.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_VEIN_FALL = create(key("block.sculk_vein.fall")); + + /** + * {@code minecraft:block.sculk_vein.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_VEIN_HIT = create(key("block.sculk_vein.hit")); + + /** + * {@code minecraft:block.sculk_vein.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_VEIN_PLACE = create(key("block.sculk_vein.place")); + + /** + * {@code minecraft:block.sculk_vein.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SCULK_VEIN_STEP = create(key("block.sculk_vein.step")); + + /** + * {@code minecraft:block.shroomlight.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHROOMLIGHT_BREAK = create(key("block.shroomlight.break")); + + /** + * {@code minecraft:block.shroomlight.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHROOMLIGHT_FALL = create(key("block.shroomlight.fall")); + + /** + * {@code minecraft:block.shroomlight.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHROOMLIGHT_HIT = create(key("block.shroomlight.hit")); + + /** + * {@code minecraft:block.shroomlight.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHROOMLIGHT_PLACE = create(key("block.shroomlight.place")); + + /** + * {@code minecraft:block.shroomlight.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHROOMLIGHT_STEP = create(key("block.shroomlight.step")); + + /** + * {@code minecraft:block.shulker_box.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHULKER_BOX_CLOSE = create(key("block.shulker_box.close")); + + /** + * {@code minecraft:block.shulker_box.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SHULKER_BOX_OPEN = create(key("block.shulker_box.open")); + + /** + * {@code minecraft:block.sign.waxed_interact_fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SIGN_WAXED_INTERACT_FAIL = create(key("block.sign.waxed_interact_fail")); + + /** + * {@code minecraft:block.slime_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SLIME_BLOCK_BREAK = create(key("block.slime_block.break")); + + /** + * {@code minecraft:block.slime_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SLIME_BLOCK_FALL = create(key("block.slime_block.fall")); + + /** + * {@code minecraft:block.slime_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SLIME_BLOCK_HIT = create(key("block.slime_block.hit")); + + /** + * {@code minecraft:block.slime_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SLIME_BLOCK_PLACE = create(key("block.slime_block.place")); + + /** + * {@code minecraft:block.slime_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SLIME_BLOCK_STEP = create(key("block.slime_block.step")); + + /** + * {@code minecraft:block.small_amethyst_bud.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_AMETHYST_BUD_BREAK = create(key("block.small_amethyst_bud.break")); + + /** + * {@code minecraft:block.small_amethyst_bud.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_AMETHYST_BUD_PLACE = create(key("block.small_amethyst_bud.place")); + + /** + * {@code minecraft:block.small_dripleaf.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_DRIPLEAF_BREAK = create(key("block.small_dripleaf.break")); + + /** + * {@code minecraft:block.small_dripleaf.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_DRIPLEAF_FALL = create(key("block.small_dripleaf.fall")); + + /** + * {@code minecraft:block.small_dripleaf.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_DRIPLEAF_HIT = create(key("block.small_dripleaf.hit")); + + /** + * {@code minecraft:block.small_dripleaf.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_DRIPLEAF_PLACE = create(key("block.small_dripleaf.place")); + + /** + * {@code minecraft:block.small_dripleaf.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMALL_DRIPLEAF_STEP = create(key("block.small_dripleaf.step")); + + /** + * {@code minecraft:block.smithing_table.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMITHING_TABLE_USE = create(key("block.smithing_table.use")); + + /** + * {@code minecraft:block.smoker.smoke} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SMOKER_SMOKE = create(key("block.smoker.smoke")); + + /** + * {@code minecraft:block.sniffer_egg.crack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNIFFER_EGG_CRACK = create(key("block.sniffer_egg.crack")); + + /** + * {@code minecraft:block.sniffer_egg.hatch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNIFFER_EGG_HATCH = create(key("block.sniffer_egg.hatch")); + + /** + * {@code minecraft:block.sniffer_egg.plop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNIFFER_EGG_PLOP = create(key("block.sniffer_egg.plop")); + + /** + * {@code minecraft:block.snow.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNOW_BREAK = create(key("block.snow.break")); + + /** + * {@code minecraft:block.snow.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNOW_FALL = create(key("block.snow.fall")); + + /** + * {@code minecraft:block.snow.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNOW_HIT = create(key("block.snow.hit")); + + /** + * {@code minecraft:block.snow.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNOW_PLACE = create(key("block.snow.place")); + + /** + * {@code minecraft:block.snow.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SNOW_STEP = create(key("block.snow.step")); + + /** + * {@code minecraft:block.soul_sand.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SAND_BREAK = create(key("block.soul_sand.break")); + + /** + * {@code minecraft:block.soul_sand.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SAND_FALL = create(key("block.soul_sand.fall")); + + /** + * {@code minecraft:block.soul_sand.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SAND_HIT = create(key("block.soul_sand.hit")); + + /** + * {@code minecraft:block.soul_sand.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SAND_PLACE = create(key("block.soul_sand.place")); + + /** + * {@code minecraft:block.soul_sand.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SAND_STEP = create(key("block.soul_sand.step")); + + /** + * {@code minecraft:block.soul_soil.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SOIL_BREAK = create(key("block.soul_soil.break")); + + /** + * {@code minecraft:block.soul_soil.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SOIL_FALL = create(key("block.soul_soil.fall")); + + /** + * {@code minecraft:block.soul_soil.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SOIL_HIT = create(key("block.soul_soil.hit")); + + /** + * {@code minecraft:block.soul_soil.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SOIL_PLACE = create(key("block.soul_soil.place")); + + /** + * {@code minecraft:block.soul_soil.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SOUL_SOIL_STEP = create(key("block.soul_soil.step")); + + /** + * {@code minecraft:block.spawner.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPAWNER_BREAK = create(key("block.spawner.break")); + + /** + * {@code minecraft:block.spawner.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPAWNER_FALL = create(key("block.spawner.fall")); + + /** + * {@code minecraft:block.spawner.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPAWNER_HIT = create(key("block.spawner.hit")); + + /** + * {@code minecraft:block.spawner.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPAWNER_PLACE = create(key("block.spawner.place")); + + /** + * {@code minecraft:block.spawner.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPAWNER_STEP = create(key("block.spawner.step")); + + /** + * {@code minecraft:block.sponge.absorb} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_ABSORB = create(key("block.sponge.absorb")); + + /** + * {@code minecraft:block.sponge.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_BREAK = create(key("block.sponge.break")); + + /** + * {@code minecraft:block.sponge.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_FALL = create(key("block.sponge.fall")); + + /** + * {@code minecraft:block.sponge.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_HIT = create(key("block.sponge.hit")); + + /** + * {@code minecraft:block.sponge.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_PLACE = create(key("block.sponge.place")); + + /** + * {@code minecraft:block.sponge.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPONGE_STEP = create(key("block.sponge.step")); + + /** + * {@code minecraft:block.spore_blossom.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPORE_BLOSSOM_BREAK = create(key("block.spore_blossom.break")); + + /** + * {@code minecraft:block.spore_blossom.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPORE_BLOSSOM_FALL = create(key("block.spore_blossom.fall")); + + /** + * {@code minecraft:block.spore_blossom.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPORE_BLOSSOM_HIT = create(key("block.spore_blossom.hit")); + + /** + * {@code minecraft:block.spore_blossom.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPORE_BLOSSOM_PLACE = create(key("block.spore_blossom.place")); + + /** + * {@code minecraft:block.spore_blossom.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SPORE_BLOSSOM_STEP = create(key("block.spore_blossom.step")); + + /** + * {@code minecraft:block.stem.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STEM_BREAK = create(key("block.stem.break")); + + /** + * {@code minecraft:block.stem.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STEM_FALL = create(key("block.stem.fall")); + + /** + * {@code minecraft:block.stem.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STEM_HIT = create(key("block.stem.hit")); + + /** + * {@code minecraft:block.stem.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STEM_PLACE = create(key("block.stem.place")); + + /** + * {@code minecraft:block.stem.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STEM_STEP = create(key("block.stem.step")); + + /** + * {@code minecraft:block.stone.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_BREAK = create(key("block.stone.break")); + + /** + * {@code minecraft:block.stone.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_FALL = create(key("block.stone.fall")); + + /** + * {@code minecraft:block.stone.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_HIT = create(key("block.stone.hit")); + + /** + * {@code minecraft:block.stone.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_PLACE = create(key("block.stone.place")); + + /** + * {@code minecraft:block.stone.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_STEP = create(key("block.stone.step")); + + /** + * {@code minecraft:block.stone_button.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_BUTTON_CLICK_OFF = create(key("block.stone_button.click_off")); + + /** + * {@code minecraft:block.stone_button.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_BUTTON_CLICK_ON = create(key("block.stone_button.click_on")); + + /** + * {@code minecraft:block.stone_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF = create(key("block.stone_pressure_plate.click_off")); + + /** + * {@code minecraft:block.stone_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_STONE_PRESSURE_PLATE_CLICK_ON = create(key("block.stone_pressure_plate.click_on")); + + /** + * {@code minecraft:block.suspicious_gravel.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_GRAVEL_BREAK = create(key("block.suspicious_gravel.break")); + + /** + * {@code minecraft:block.suspicious_gravel.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_GRAVEL_FALL = create(key("block.suspicious_gravel.fall")); + + /** + * {@code minecraft:block.suspicious_gravel.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_GRAVEL_HIT = create(key("block.suspicious_gravel.hit")); + + /** + * {@code minecraft:block.suspicious_gravel.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_GRAVEL_PLACE = create(key("block.suspicious_gravel.place")); + + /** + * {@code minecraft:block.suspicious_gravel.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_GRAVEL_STEP = create(key("block.suspicious_gravel.step")); + + /** + * {@code minecraft:block.suspicious_sand.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_SAND_BREAK = create(key("block.suspicious_sand.break")); + + /** + * {@code minecraft:block.suspicious_sand.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_SAND_FALL = create(key("block.suspicious_sand.fall")); + + /** + * {@code minecraft:block.suspicious_sand.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_SAND_HIT = create(key("block.suspicious_sand.hit")); + + /** + * {@code minecraft:block.suspicious_sand.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_SAND_PLACE = create(key("block.suspicious_sand.place")); + + /** + * {@code minecraft:block.suspicious_sand.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SUSPICIOUS_SAND_STEP = create(key("block.suspicious_sand.step")); + + /** + * {@code minecraft:block.sweet_berry_bush.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SWEET_BERRY_BUSH_BREAK = create(key("block.sweet_berry_bush.break")); + + /** + * {@code minecraft:block.sweet_berry_bush.pick_berries} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES = create(key("block.sweet_berry_bush.pick_berries")); + + /** + * {@code minecraft:block.sweet_berry_bush.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_SWEET_BERRY_BUSH_PLACE = create(key("block.sweet_berry_bush.place")); + + /** + * {@code minecraft:block.trial_spawner.about_to_spawn_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_ABOUT_TO_SPAWN_ITEM = create(key("block.trial_spawner.about_to_spawn_item")); + + /** + * {@code minecraft:block.trial_spawner.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_AMBIENT = create(key("block.trial_spawner.ambient")); + + /** + * {@code minecraft:block.trial_spawner.ambient_ominous} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_AMBIENT_OMINOUS = create(key("block.trial_spawner.ambient_ominous")); + + /** + * {@code minecraft:block.trial_spawner.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_BREAK = create(key("block.trial_spawner.break")); + + /** + * {@code minecraft:block.trial_spawner.close_shutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_CLOSE_SHUTTER = create(key("block.trial_spawner.close_shutter")); + + /** + * {@code minecraft:block.trial_spawner.detect_player} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_DETECT_PLAYER = create(key("block.trial_spawner.detect_player")); + + /** + * {@code minecraft:block.trial_spawner.eject_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_EJECT_ITEM = create(key("block.trial_spawner.eject_item")); + + /** + * {@code minecraft:block.trial_spawner.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_FALL = create(key("block.trial_spawner.fall")); + + /** + * {@code minecraft:block.trial_spawner.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_HIT = create(key("block.trial_spawner.hit")); + + /** + * {@code minecraft:block.trial_spawner.ominous_activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_OMINOUS_ACTIVATE = create(key("block.trial_spawner.ominous_activate")); + + /** + * {@code minecraft:block.trial_spawner.open_shutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER = create(key("block.trial_spawner.open_shutter")); + + /** + * {@code minecraft:block.trial_spawner.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_PLACE = create(key("block.trial_spawner.place")); + + /** + * {@code minecraft:block.trial_spawner.spawn_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_SPAWN_ITEM = create(key("block.trial_spawner.spawn_item")); + + /** + * {@code minecraft:block.trial_spawner.spawn_item_begin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_SPAWN_ITEM_BEGIN = create(key("block.trial_spawner.spawn_item_begin")); + + /** + * {@code minecraft:block.trial_spawner.spawn_mob} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_SPAWN_MOB = create(key("block.trial_spawner.spawn_mob")); + + /** + * {@code minecraft:block.trial_spawner.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIAL_SPAWNER_STEP = create(key("block.trial_spawner.step")); + + /** + * {@code minecraft:block.tripwire.attach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIPWIRE_ATTACH = create(key("block.tripwire.attach")); + + /** + * {@code minecraft:block.tripwire.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIPWIRE_CLICK_OFF = create(key("block.tripwire.click_off")); + + /** + * {@code minecraft:block.tripwire.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIPWIRE_CLICK_ON = create(key("block.tripwire.click_on")); + + /** + * {@code minecraft:block.tripwire.detach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TRIPWIRE_DETACH = create(key("block.tripwire.detach")); + + /** + * {@code minecraft:block.tuff.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BREAK = create(key("block.tuff.break")); + + /** + * {@code minecraft:block.tuff.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_FALL = create(key("block.tuff.fall")); + + /** + * {@code minecraft:block.tuff.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_HIT = create(key("block.tuff.hit")); + + /** + * {@code minecraft:block.tuff.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_PLACE = create(key("block.tuff.place")); + + /** + * {@code minecraft:block.tuff.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_STEP = create(key("block.tuff.step")); + + /** + * {@code minecraft:block.tuff_bricks.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BRICKS_BREAK = create(key("block.tuff_bricks.break")); + + /** + * {@code minecraft:block.tuff_bricks.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BRICKS_FALL = create(key("block.tuff_bricks.fall")); + + /** + * {@code minecraft:block.tuff_bricks.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BRICKS_HIT = create(key("block.tuff_bricks.hit")); + + /** + * {@code minecraft:block.tuff_bricks.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BRICKS_PLACE = create(key("block.tuff_bricks.place")); + + /** + * {@code minecraft:block.tuff_bricks.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_TUFF_BRICKS_STEP = create(key("block.tuff_bricks.step")); + + /** + * {@code minecraft:block.vault.activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_ACTIVATE = create(key("block.vault.activate")); + + /** + * {@code minecraft:block.vault.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_AMBIENT = create(key("block.vault.ambient")); + + /** + * {@code minecraft:block.vault.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_BREAK = create(key("block.vault.break")); + + /** + * {@code minecraft:block.vault.close_shutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_CLOSE_SHUTTER = create(key("block.vault.close_shutter")); + + /** + * {@code minecraft:block.vault.deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_DEACTIVATE = create(key("block.vault.deactivate")); + + /** + * {@code minecraft:block.vault.eject_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_EJECT_ITEM = create(key("block.vault.eject_item")); + + /** + * {@code minecraft:block.vault.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_FALL = create(key("block.vault.fall")); + + /** + * {@code minecraft:block.vault.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_HIT = create(key("block.vault.hit")); + + /** + * {@code minecraft:block.vault.insert_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_INSERT_ITEM = create(key("block.vault.insert_item")); + + /** + * {@code minecraft:block.vault.insert_item_fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_INSERT_ITEM_FAIL = create(key("block.vault.insert_item_fail")); + + /** + * {@code minecraft:block.vault.open_shutter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_OPEN_SHUTTER = create(key("block.vault.open_shutter")); + + /** + * {@code minecraft:block.vault.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_PLACE = create(key("block.vault.place")); + + /** + * {@code minecraft:block.vault.reject_rewarded_player} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_REJECT_REWARDED_PLAYER = create(key("block.vault.reject_rewarded_player")); + + /** + * {@code minecraft:block.vault.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VAULT_STEP = create(key("block.vault.step")); + + /** + * {@code minecraft:block.vine.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VINE_BREAK = create(key("block.vine.break")); + + /** + * {@code minecraft:block.vine.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VINE_FALL = create(key("block.vine.fall")); + + /** + * {@code minecraft:block.vine.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VINE_HIT = create(key("block.vine.hit")); + + /** + * {@code minecraft:block.vine.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VINE_PLACE = create(key("block.vine.place")); + + /** + * {@code minecraft:block.vine.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_VINE_STEP = create(key("block.vine.step")); + + /** + * {@code minecraft:block.wart_block.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WART_BLOCK_BREAK = create(key("block.wart_block.break")); + + /** + * {@code minecraft:block.wart_block.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WART_BLOCK_FALL = create(key("block.wart_block.fall")); + + /** + * {@code minecraft:block.wart_block.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WART_BLOCK_HIT = create(key("block.wart_block.hit")); + + /** + * {@code minecraft:block.wart_block.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WART_BLOCK_PLACE = create(key("block.wart_block.place")); + + /** + * {@code minecraft:block.wart_block.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WART_BLOCK_STEP = create(key("block.wart_block.step")); + + /** + * {@code minecraft:block.water.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WATER_AMBIENT = create(key("block.water.ambient")); + + /** + * {@code minecraft:block.weeping_vines.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WEEPING_VINES_BREAK = create(key("block.weeping_vines.break")); + + /** + * {@code minecraft:block.weeping_vines.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WEEPING_VINES_FALL = create(key("block.weeping_vines.fall")); + + /** + * {@code minecraft:block.weeping_vines.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WEEPING_VINES_HIT = create(key("block.weeping_vines.hit")); + + /** + * {@code minecraft:block.weeping_vines.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WEEPING_VINES_PLACE = create(key("block.weeping_vines.place")); + + /** + * {@code minecraft:block.weeping_vines.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WEEPING_VINES_STEP = create(key("block.weeping_vines.step")); + + /** + * {@code minecraft:block.wet_grass.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_GRASS_BREAK = create(key("block.wet_grass.break")); + + /** + * {@code minecraft:block.wet_grass.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_GRASS_FALL = create(key("block.wet_grass.fall")); + + /** + * {@code minecraft:block.wet_grass.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_GRASS_HIT = create(key("block.wet_grass.hit")); + + /** + * {@code minecraft:block.wet_grass.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_GRASS_PLACE = create(key("block.wet_grass.place")); + + /** + * {@code minecraft:block.wet_grass.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_GRASS_STEP = create(key("block.wet_grass.step")); + + /** + * {@code minecraft:block.wet_sponge.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_BREAK = create(key("block.wet_sponge.break")); + + /** + * {@code minecraft:block.wet_sponge.dries} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_DRIES = create(key("block.wet_sponge.dries")); + + /** + * {@code minecraft:block.wet_sponge.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_FALL = create(key("block.wet_sponge.fall")); + + /** + * {@code minecraft:block.wet_sponge.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_HIT = create(key("block.wet_sponge.hit")); + + /** + * {@code minecraft:block.wet_sponge.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_PLACE = create(key("block.wet_sponge.place")); + + /** + * {@code minecraft:block.wet_sponge.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WET_SPONGE_STEP = create(key("block.wet_sponge.step")); + + /** + * {@code minecraft:block.wood.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOD_BREAK = create(key("block.wood.break")); + + /** + * {@code minecraft:block.wood.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOD_FALL = create(key("block.wood.fall")); + + /** + * {@code minecraft:block.wood.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOD_HIT = create(key("block.wood.hit")); + + /** + * {@code minecraft:block.wood.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOD_PLACE = create(key("block.wood.place")); + + /** + * {@code minecraft:block.wood.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOD_STEP = create(key("block.wood.step")); + + /** + * {@code minecraft:block.wooden_button.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_BUTTON_CLICK_OFF = create(key("block.wooden_button.click_off")); + + /** + * {@code minecraft:block.wooden_button.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_BUTTON_CLICK_ON = create(key("block.wooden_button.click_on")); + + /** + * {@code minecraft:block.wooden_door.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_DOOR_CLOSE = create(key("block.wooden_door.close")); + + /** + * {@code minecraft:block.wooden_door.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_DOOR_OPEN = create(key("block.wooden_door.open")); + + /** + * {@code minecraft:block.wooden_pressure_plate.click_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF = create(key("block.wooden_pressure_plate.click_off")); + + /** + * {@code minecraft:block.wooden_pressure_plate.click_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON = create(key("block.wooden_pressure_plate.click_on")); + + /** + * {@code minecraft:block.wooden_trapdoor.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_TRAPDOOR_CLOSE = create(key("block.wooden_trapdoor.close")); + + /** + * {@code minecraft:block.wooden_trapdoor.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOODEN_TRAPDOOR_OPEN = create(key("block.wooden_trapdoor.open")); + + /** + * {@code minecraft:block.wool.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOL_BREAK = create(key("block.wool.break")); + + /** + * {@code minecraft:block.wool.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOL_FALL = create(key("block.wool.fall")); + + /** + * {@code minecraft:block.wool.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOL_HIT = create(key("block.wool.hit")); + + /** + * {@code minecraft:block.wool.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOL_PLACE = create(key("block.wool.place")); + + /** + * {@code minecraft:block.wool.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_WOOL_STEP = create(key("block.wool.step")); + + /** + * {@code minecraft:enchant.thorns.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENCHANT_THORNS_HIT = create(key("enchant.thorns.hit")); + + /** + * {@code minecraft:entity.allay.ambient_with_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_AMBIENT_WITH_ITEM = create(key("entity.allay.ambient_with_item")); + + /** + * {@code minecraft:entity.allay.ambient_without_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM = create(key("entity.allay.ambient_without_item")); + + /** + * {@code minecraft:entity.allay.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_DEATH = create(key("entity.allay.death")); + + /** + * {@code minecraft:entity.allay.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_HURT = create(key("entity.allay.hurt")); + + /** + * {@code minecraft:entity.allay.item_given} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_ITEM_GIVEN = create(key("entity.allay.item_given")); + + /** + * {@code minecraft:entity.allay.item_taken} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_ITEM_TAKEN = create(key("entity.allay.item_taken")); + + /** + * {@code minecraft:entity.allay.item_thrown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ALLAY_ITEM_THROWN = create(key("entity.allay.item_thrown")); + + /** + * {@code minecraft:entity.armadillo.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_AMBIENT = create(key("entity.armadillo.ambient")); + + /** + * {@code minecraft:entity.armadillo.brush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_BRUSH = create(key("entity.armadillo.brush")); + + /** + * {@code minecraft:entity.armadillo.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_DEATH = create(key("entity.armadillo.death")); + + /** + * {@code minecraft:entity.armadillo.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_EAT = create(key("entity.armadillo.eat")); + + /** + * {@code minecraft:entity.armadillo.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_HURT = create(key("entity.armadillo.hurt")); + + /** + * {@code minecraft:entity.armadillo.hurt_reduced} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_HURT_REDUCED = create(key("entity.armadillo.hurt_reduced")); + + /** + * {@code minecraft:entity.armadillo.land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_LAND = create(key("entity.armadillo.land")); + + /** + * {@code minecraft:entity.armadillo.peek} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_PEEK = create(key("entity.armadillo.peek")); + + /** + * {@code minecraft:entity.armadillo.roll} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_ROLL = create(key("entity.armadillo.roll")); + + /** + * {@code minecraft:entity.armadillo.scute_drop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_SCUTE_DROP = create(key("entity.armadillo.scute_drop")); + + /** + * {@code minecraft:entity.armadillo.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_STEP = create(key("entity.armadillo.step")); + + /** + * {@code minecraft:entity.armadillo.unroll_finish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_UNROLL_FINISH = create(key("entity.armadillo.unroll_finish")); + + /** + * {@code minecraft:entity.armadillo.unroll_start} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMADILLO_UNROLL_START = create(key("entity.armadillo.unroll_start")); + + /** + * {@code minecraft:entity.armor_stand.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMOR_STAND_BREAK = create(key("entity.armor_stand.break")); + + /** + * {@code minecraft:entity.armor_stand.fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMOR_STAND_FALL = create(key("entity.armor_stand.fall")); + + /** + * {@code minecraft:entity.armor_stand.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMOR_STAND_HIT = create(key("entity.armor_stand.hit")); + + /** + * {@code minecraft:entity.armor_stand.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARMOR_STAND_PLACE = create(key("entity.armor_stand.place")); + + /** + * {@code minecraft:entity.arrow.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARROW_HIT = create(key("entity.arrow.hit")); + + /** + * {@code minecraft:entity.arrow.hit_player} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARROW_HIT_PLAYER = create(key("entity.arrow.hit_player")); + + /** + * {@code minecraft:entity.arrow.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ARROW_SHOOT = create(key("entity.arrow.shoot")); + + /** + * {@code minecraft:entity.axolotl.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_ATTACK = create(key("entity.axolotl.attack")); + + /** + * {@code minecraft:entity.axolotl.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_DEATH = create(key("entity.axolotl.death")); + + /** + * {@code minecraft:entity.axolotl.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_HURT = create(key("entity.axolotl.hurt")); + + /** + * {@code minecraft:entity.axolotl.idle_air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_IDLE_AIR = create(key("entity.axolotl.idle_air")); + + /** + * {@code minecraft:entity.axolotl.idle_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_IDLE_WATER = create(key("entity.axolotl.idle_water")); + + /** + * {@code minecraft:entity.axolotl.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_SPLASH = create(key("entity.axolotl.splash")); + + /** + * {@code minecraft:entity.axolotl.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_AXOLOTL_SWIM = create(key("entity.axolotl.swim")); + + /** + * {@code minecraft:entity.bat.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BAT_AMBIENT = create(key("entity.bat.ambient")); + + /** + * {@code minecraft:entity.bat.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BAT_DEATH = create(key("entity.bat.death")); + + /** + * {@code minecraft:entity.bat.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BAT_HURT = create(key("entity.bat.hurt")); + + /** + * {@code minecraft:entity.bat.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BAT_LOOP = create(key("entity.bat.loop")); + + /** + * {@code minecraft:entity.bat.takeoff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BAT_TAKEOFF = create(key("entity.bat.takeoff")); + + /** + * {@code minecraft:entity.bee.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_DEATH = create(key("entity.bee.death")); + + /** + * {@code minecraft:entity.bee.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_HURT = create(key("entity.bee.hurt")); + + /** + * {@code minecraft:entity.bee.loop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_LOOP = create(key("entity.bee.loop")); + + /** + * {@code minecraft:entity.bee.loop_aggressive} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_LOOP_AGGRESSIVE = create(key("entity.bee.loop_aggressive")); + + /** + * {@code minecraft:entity.bee.pollinate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_POLLINATE = create(key("entity.bee.pollinate")); + + /** + * {@code minecraft:entity.bee.sting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BEE_STING = create(key("entity.bee.sting")); + + /** + * {@code minecraft:entity.blaze.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BLAZE_AMBIENT = create(key("entity.blaze.ambient")); + + /** + * {@code minecraft:entity.blaze.burn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BLAZE_BURN = create(key("entity.blaze.burn")); + + /** + * {@code minecraft:entity.blaze.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BLAZE_DEATH = create(key("entity.blaze.death")); + + /** + * {@code minecraft:entity.blaze.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BLAZE_HURT = create(key("entity.blaze.hurt")); + + /** + * {@code minecraft:entity.blaze.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BLAZE_SHOOT = create(key("entity.blaze.shoot")); + + /** + * {@code minecraft:entity.boat.paddle_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOAT_PADDLE_LAND = create(key("entity.boat.paddle_land")); + + /** + * {@code minecraft:entity.boat.paddle_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOAT_PADDLE_WATER = create(key("entity.boat.paddle_water")); + + /** + * {@code minecraft:entity.bogged.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOGGED_AMBIENT = create(key("entity.bogged.ambient")); + + /** + * {@code minecraft:entity.bogged.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOGGED_DEATH = create(key("entity.bogged.death")); + + /** + * {@code minecraft:entity.bogged.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOGGED_HURT = create(key("entity.bogged.hurt")); + + /** + * {@code minecraft:entity.bogged.shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOGGED_SHEAR = create(key("entity.bogged.shear")); + + /** + * {@code minecraft:entity.bogged.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BOGGED_STEP = create(key("entity.bogged.step")); + + /** + * {@code minecraft:entity.breeze.charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_CHARGE = create(key("entity.breeze.charge")); + + /** + * {@code minecraft:entity.breeze.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_DEATH = create(key("entity.breeze.death")); + + /** + * {@code minecraft:entity.breeze.deflect} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_DEFLECT = create(key("entity.breeze.deflect")); + + /** + * {@code minecraft:entity.breeze.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_HURT = create(key("entity.breeze.hurt")); + + /** + * {@code minecraft:entity.breeze.idle_air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_IDLE_AIR = create(key("entity.breeze.idle_air")); + + /** + * {@code minecraft:entity.breeze.idle_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_IDLE_GROUND = create(key("entity.breeze.idle_ground")); + + /** + * {@code minecraft:entity.breeze.inhale} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_INHALE = create(key("entity.breeze.inhale")); + + /** + * {@code minecraft:entity.breeze.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_JUMP = create(key("entity.breeze.jump")); + + /** + * {@code minecraft:entity.breeze.land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_LAND = create(key("entity.breeze.land")); + + /** + * {@code minecraft:entity.breeze.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_SHOOT = create(key("entity.breeze.shoot")); + + /** + * {@code minecraft:entity.breeze.slide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_SLIDE = create(key("entity.breeze.slide")); + + /** + * {@code minecraft:entity.breeze.whirl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_WHIRL = create(key("entity.breeze.whirl")); + + /** + * {@code minecraft:entity.breeze.wind_burst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_BREEZE_WIND_BURST = create(key("entity.breeze.wind_burst")); + + /** + * {@code minecraft:entity.camel.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_AMBIENT = create(key("entity.camel.ambient")); + + /** + * {@code minecraft:entity.camel.dash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_DASH = create(key("entity.camel.dash")); + + /** + * {@code minecraft:entity.camel.dash_ready} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_DASH_READY = create(key("entity.camel.dash_ready")); + + /** + * {@code minecraft:entity.camel.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_DEATH = create(key("entity.camel.death")); + + /** + * {@code minecraft:entity.camel.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_EAT = create(key("entity.camel.eat")); + + /** + * {@code minecraft:entity.camel.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_HURT = create(key("entity.camel.hurt")); + + /** + * {@code minecraft:entity.camel.saddle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_SADDLE = create(key("entity.camel.saddle")); + + /** + * {@code minecraft:entity.camel.sit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_SIT = create(key("entity.camel.sit")); + + /** + * {@code minecraft:entity.camel.stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_STAND = create(key("entity.camel.stand")); + + /** + * {@code minecraft:entity.camel.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_STEP = create(key("entity.camel.step")); + + /** + * {@code minecraft:entity.camel.step_sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAMEL_STEP_SAND = create(key("entity.camel.step_sand")); + + /** + * {@code minecraft:entity.cat.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_AMBIENT = create(key("entity.cat.ambient")); + + /** + * {@code minecraft:entity.cat.beg_for_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_BEG_FOR_FOOD = create(key("entity.cat.beg_for_food")); + + /** + * {@code minecraft:entity.cat.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_DEATH = create(key("entity.cat.death")); + + /** + * {@code minecraft:entity.cat.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_EAT = create(key("entity.cat.eat")); + + /** + * {@code minecraft:entity.cat.hiss} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_HISS = create(key("entity.cat.hiss")); + + /** + * {@code minecraft:entity.cat.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_HURT = create(key("entity.cat.hurt")); + + /** + * {@code minecraft:entity.cat.purr} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_PURR = create(key("entity.cat.purr")); + + /** + * {@code minecraft:entity.cat.purreow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_PURREOW = create(key("entity.cat.purreow")); + + /** + * {@code minecraft:entity.cat.stray_ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CAT_STRAY_AMBIENT = create(key("entity.cat.stray_ambient")); + + /** + * {@code minecraft:entity.chicken.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CHICKEN_AMBIENT = create(key("entity.chicken.ambient")); + + /** + * {@code minecraft:entity.chicken.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CHICKEN_DEATH = create(key("entity.chicken.death")); + + /** + * {@code minecraft:entity.chicken.egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CHICKEN_EGG = create(key("entity.chicken.egg")); + + /** + * {@code minecraft:entity.chicken.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CHICKEN_HURT = create(key("entity.chicken.hurt")); + + /** + * {@code minecraft:entity.chicken.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CHICKEN_STEP = create(key("entity.chicken.step")); + + /** + * {@code minecraft:entity.cod.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COD_AMBIENT = create(key("entity.cod.ambient")); + + /** + * {@code minecraft:entity.cod.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COD_DEATH = create(key("entity.cod.death")); + + /** + * {@code minecraft:entity.cod.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COD_FLOP = create(key("entity.cod.flop")); + + /** + * {@code minecraft:entity.cod.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COD_HURT = create(key("entity.cod.hurt")); + + /** + * {@code minecraft:entity.cow.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COW_AMBIENT = create(key("entity.cow.ambient")); + + /** + * {@code minecraft:entity.cow.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COW_DEATH = create(key("entity.cow.death")); + + /** + * {@code minecraft:entity.cow.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COW_HURT = create(key("entity.cow.hurt")); + + /** + * {@code minecraft:entity.cow.milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COW_MILK = create(key("entity.cow.milk")); + + /** + * {@code minecraft:entity.cow.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_COW_STEP = create(key("entity.cow.step")); + + /** + * {@code minecraft:entity.creaking.activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_ACTIVATE = create(key("entity.creaking.activate")); + + /** + * {@code minecraft:entity.creaking.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_AMBIENT = create(key("entity.creaking.ambient")); + + /** + * {@code minecraft:entity.creaking.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_ATTACK = create(key("entity.creaking.attack")); + + /** + * {@code minecraft:entity.creaking.deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_DEACTIVATE = create(key("entity.creaking.deactivate")); + + /** + * {@code minecraft:entity.creaking.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_DEATH = create(key("entity.creaking.death")); + + /** + * {@code minecraft:entity.creaking.freeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_FREEZE = create(key("entity.creaking.freeze")); + + /** + * {@code minecraft:entity.creaking.spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_SPAWN = create(key("entity.creaking.spawn")); + + /** + * {@code minecraft:entity.creaking.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_STEP = create(key("entity.creaking.step")); + + /** + * {@code minecraft:entity.creaking.sway} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_SWAY = create(key("entity.creaking.sway")); + + /** + * {@code minecraft:entity.creaking.twitch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_TWITCH = create(key("entity.creaking.twitch")); + + /** + * {@code minecraft:entity.creaking.unfreeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREAKING_UNFREEZE = create(key("entity.creaking.unfreeze")); + + /** + * {@code minecraft:entity.creeper.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREEPER_DEATH = create(key("entity.creeper.death")); + + /** + * {@code minecraft:entity.creeper.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREEPER_HURT = create(key("entity.creeper.hurt")); + + /** + * {@code minecraft:entity.creeper.primed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_CREEPER_PRIMED = create(key("entity.creeper.primed")); + + /** + * {@code minecraft:entity.dolphin.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_AMBIENT = create(key("entity.dolphin.ambient")); + + /** + * {@code minecraft:entity.dolphin.ambient_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_AMBIENT_WATER = create(key("entity.dolphin.ambient_water")); + + /** + * {@code minecraft:entity.dolphin.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_ATTACK = create(key("entity.dolphin.attack")); + + /** + * {@code minecraft:entity.dolphin.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_DEATH = create(key("entity.dolphin.death")); + + /** + * {@code minecraft:entity.dolphin.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_EAT = create(key("entity.dolphin.eat")); + + /** + * {@code minecraft:entity.dolphin.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_HURT = create(key("entity.dolphin.hurt")); + + /** + * {@code minecraft:entity.dolphin.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_JUMP = create(key("entity.dolphin.jump")); + + /** + * {@code minecraft:entity.dolphin.play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_PLAY = create(key("entity.dolphin.play")); + + /** + * {@code minecraft:entity.dolphin.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_SPLASH = create(key("entity.dolphin.splash")); + + /** + * {@code minecraft:entity.dolphin.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DOLPHIN_SWIM = create(key("entity.dolphin.swim")); + + /** + * {@code minecraft:entity.donkey.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_AMBIENT = create(key("entity.donkey.ambient")); + + /** + * {@code minecraft:entity.donkey.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_ANGRY = create(key("entity.donkey.angry")); + + /** + * {@code minecraft:entity.donkey.chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_CHEST = create(key("entity.donkey.chest")); + + /** + * {@code minecraft:entity.donkey.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_DEATH = create(key("entity.donkey.death")); + + /** + * {@code minecraft:entity.donkey.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_EAT = create(key("entity.donkey.eat")); + + /** + * {@code minecraft:entity.donkey.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_HURT = create(key("entity.donkey.hurt")); + + /** + * {@code minecraft:entity.donkey.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DONKEY_JUMP = create(key("entity.donkey.jump")); + + /** + * {@code minecraft:entity.dragon_fireball.explode} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DRAGON_FIREBALL_EXPLODE = create(key("entity.dragon_fireball.explode")); + + /** + * {@code minecraft:entity.drowned.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_AMBIENT = create(key("entity.drowned.ambient")); + + /** + * {@code minecraft:entity.drowned.ambient_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_AMBIENT_WATER = create(key("entity.drowned.ambient_water")); + + /** + * {@code minecraft:entity.drowned.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_DEATH = create(key("entity.drowned.death")); + + /** + * {@code minecraft:entity.drowned.death_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_DEATH_WATER = create(key("entity.drowned.death_water")); + + /** + * {@code minecraft:entity.drowned.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_HURT = create(key("entity.drowned.hurt")); + + /** + * {@code minecraft:entity.drowned.hurt_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_HURT_WATER = create(key("entity.drowned.hurt_water")); + + /** + * {@code minecraft:entity.drowned.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_SHOOT = create(key("entity.drowned.shoot")); + + /** + * {@code minecraft:entity.drowned.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_STEP = create(key("entity.drowned.step")); + + /** + * {@code minecraft:entity.drowned.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DROWNED_SWIM = create(key("entity.drowned.swim")); + + /** + * {@code minecraft:entity.egg.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EGG_THROW = create(key("entity.egg.throw")); + + /** + * {@code minecraft:entity.elder_guardian.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_AMBIENT = create(key("entity.elder_guardian.ambient")); + + /** + * {@code minecraft:entity.elder_guardian.ambient_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_AMBIENT_LAND = create(key("entity.elder_guardian.ambient_land")); + + /** + * {@code minecraft:entity.elder_guardian.curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_CURSE = create(key("entity.elder_guardian.curse")); + + /** + * {@code minecraft:entity.elder_guardian.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_DEATH = create(key("entity.elder_guardian.death")); + + /** + * {@code minecraft:entity.elder_guardian.death_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_DEATH_LAND = create(key("entity.elder_guardian.death_land")); + + /** + * {@code minecraft:entity.elder_guardian.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_FLOP = create(key("entity.elder_guardian.flop")); + + /** + * {@code minecraft:entity.elder_guardian.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_HURT = create(key("entity.elder_guardian.hurt")); + + /** + * {@code minecraft:entity.elder_guardian.hurt_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ELDER_GUARDIAN_HURT_LAND = create(key("entity.elder_guardian.hurt_land")); + + /** + * {@code minecraft:entity.ender_dragon.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_AMBIENT = create(key("entity.ender_dragon.ambient")); + + /** + * {@code minecraft:entity.ender_dragon.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_DEATH = create(key("entity.ender_dragon.death")); + + /** + * {@code minecraft:entity.ender_dragon.flap} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_FLAP = create(key("entity.ender_dragon.flap")); + + /** + * {@code minecraft:entity.ender_dragon.growl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_GROWL = create(key("entity.ender_dragon.growl")); + + /** + * {@code minecraft:entity.ender_dragon.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_HURT = create(key("entity.ender_dragon.hurt")); + + /** + * {@code minecraft:entity.ender_dragon.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_DRAGON_SHOOT = create(key("entity.ender_dragon.shoot")); + + /** + * {@code minecraft:entity.ender_eye.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_EYE_DEATH = create(key("entity.ender_eye.death")); + + /** + * {@code minecraft:entity.ender_eye.launch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_EYE_LAUNCH = create(key("entity.ender_eye.launch")); + + /** + * {@code minecraft:entity.ender_pearl.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDER_PEARL_THROW = create(key("entity.ender_pearl.throw")); + + /** + * {@code minecraft:entity.enderman.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_AMBIENT = create(key("entity.enderman.ambient")); + + /** + * {@code minecraft:entity.enderman.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_DEATH = create(key("entity.enderman.death")); + + /** + * {@code minecraft:entity.enderman.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_HURT = create(key("entity.enderman.hurt")); + + /** + * {@code minecraft:entity.enderman.scream} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_SCREAM = create(key("entity.enderman.scream")); + + /** + * {@code minecraft:entity.enderman.stare} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_STARE = create(key("entity.enderman.stare")); + + /** + * {@code minecraft:entity.enderman.teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMAN_TELEPORT = create(key("entity.enderman.teleport")); + + /** + * {@code minecraft:entity.endermite.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMITE_AMBIENT = create(key("entity.endermite.ambient")); + + /** + * {@code minecraft:entity.endermite.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMITE_DEATH = create(key("entity.endermite.death")); + + /** + * {@code minecraft:entity.endermite.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMITE_HURT = create(key("entity.endermite.hurt")); + + /** + * {@code minecraft:entity.endermite.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ENDERMITE_STEP = create(key("entity.endermite.step")); + + /** + * {@code minecraft:entity.evoker.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_AMBIENT = create(key("entity.evoker.ambient")); + + /** + * {@code minecraft:entity.evoker.cast_spell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_CAST_SPELL = create(key("entity.evoker.cast_spell")); + + /** + * {@code minecraft:entity.evoker.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_CELEBRATE = create(key("entity.evoker.celebrate")); + + /** + * {@code minecraft:entity.evoker.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_DEATH = create(key("entity.evoker.death")); + + /** + * {@code minecraft:entity.evoker.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_HURT = create(key("entity.evoker.hurt")); + + /** + * {@code minecraft:entity.evoker.prepare_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_PREPARE_ATTACK = create(key("entity.evoker.prepare_attack")); + + /** + * {@code minecraft:entity.evoker.prepare_summon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_PREPARE_SUMMON = create(key("entity.evoker.prepare_summon")); + + /** + * {@code minecraft:entity.evoker.prepare_wololo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_PREPARE_WOLOLO = create(key("entity.evoker.prepare_wololo")); + + /** + * {@code minecraft:entity.evoker_fangs.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EVOKER_FANGS_ATTACK = create(key("entity.evoker_fangs.attack")); + + /** + * {@code minecraft:entity.experience_bottle.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EXPERIENCE_BOTTLE_THROW = create(key("entity.experience_bottle.throw")); + + /** + * {@code minecraft:entity.experience_orb.pickup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_EXPERIENCE_ORB_PICKUP = create(key("entity.experience_orb.pickup")); + + /** + * {@code minecraft:entity.firework_rocket.blast} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_BLAST = create(key("entity.firework_rocket.blast")); + + /** + * {@code minecraft:entity.firework_rocket.blast_far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_BLAST_FAR = create(key("entity.firework_rocket.blast_far")); + + /** + * {@code minecraft:entity.firework_rocket.large_blast} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_LARGE_BLAST = create(key("entity.firework_rocket.large_blast")); + + /** + * {@code minecraft:entity.firework_rocket.large_blast_far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_LARGE_BLAST_FAR = create(key("entity.firework_rocket.large_blast_far")); + + /** + * {@code minecraft:entity.firework_rocket.launch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_LAUNCH = create(key("entity.firework_rocket.launch")); + + /** + * {@code minecraft:entity.firework_rocket.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_SHOOT = create(key("entity.firework_rocket.shoot")); + + /** + * {@code minecraft:entity.firework_rocket.twinkle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_TWINKLE = create(key("entity.firework_rocket.twinkle")); + + /** + * {@code minecraft:entity.firework_rocket.twinkle_far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FIREWORK_ROCKET_TWINKLE_FAR = create(key("entity.firework_rocket.twinkle_far")); + + /** + * {@code minecraft:entity.fish.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FISH_SWIM = create(key("entity.fish.swim")); + + /** + * {@code minecraft:entity.fishing_bobber.retrieve} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FISHING_BOBBER_RETRIEVE = create(key("entity.fishing_bobber.retrieve")); + + /** + * {@code minecraft:entity.fishing_bobber.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FISHING_BOBBER_SPLASH = create(key("entity.fishing_bobber.splash")); + + /** + * {@code minecraft:entity.fishing_bobber.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FISHING_BOBBER_THROW = create(key("entity.fishing_bobber.throw")); + + /** + * {@code minecraft:entity.fox.aggro} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_AGGRO = create(key("entity.fox.aggro")); + + /** + * {@code minecraft:entity.fox.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_AMBIENT = create(key("entity.fox.ambient")); + + /** + * {@code minecraft:entity.fox.bite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_BITE = create(key("entity.fox.bite")); + + /** + * {@code minecraft:entity.fox.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_DEATH = create(key("entity.fox.death")); + + /** + * {@code minecraft:entity.fox.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_EAT = create(key("entity.fox.eat")); + + /** + * {@code minecraft:entity.fox.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_HURT = create(key("entity.fox.hurt")); + + /** + * {@code minecraft:entity.fox.screech} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_SCREECH = create(key("entity.fox.screech")); + + /** + * {@code minecraft:entity.fox.sleep} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_SLEEP = create(key("entity.fox.sleep")); + + /** + * {@code minecraft:entity.fox.sniff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_SNIFF = create(key("entity.fox.sniff")); + + /** + * {@code minecraft:entity.fox.spit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_SPIT = create(key("entity.fox.spit")); + + /** + * {@code minecraft:entity.fox.teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FOX_TELEPORT = create(key("entity.fox.teleport")); + + /** + * {@code minecraft:entity.frog.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_AMBIENT = create(key("entity.frog.ambient")); + + /** + * {@code minecraft:entity.frog.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_DEATH = create(key("entity.frog.death")); + + /** + * {@code minecraft:entity.frog.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_EAT = create(key("entity.frog.eat")); + + /** + * {@code minecraft:entity.frog.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_HURT = create(key("entity.frog.hurt")); + + /** + * {@code minecraft:entity.frog.lay_spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_LAY_SPAWN = create(key("entity.frog.lay_spawn")); + + /** + * {@code minecraft:entity.frog.long_jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_LONG_JUMP = create(key("entity.frog.long_jump")); + + /** + * {@code minecraft:entity.frog.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_STEP = create(key("entity.frog.step")); + + /** + * {@code minecraft:entity.frog.tongue} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_FROG_TONGUE = create(key("entity.frog.tongue")); + + /** + * {@code minecraft:entity.generic.big_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_BIG_FALL = create(key("entity.generic.big_fall")); + + /** + * {@code minecraft:entity.generic.burn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_BURN = create(key("entity.generic.burn")); + + /** + * {@code minecraft:entity.generic.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_DEATH = create(key("entity.generic.death")); + + /** + * {@code minecraft:entity.generic.drink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_DRINK = create(key("entity.generic.drink")); + + /** + * {@code minecraft:entity.generic.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_EAT = create(key("entity.generic.eat")); + + /** + * {@code minecraft:entity.generic.explode} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_EXPLODE = create(key("entity.generic.explode")); + + /** + * {@code minecraft:entity.generic.extinguish_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_EXTINGUISH_FIRE = create(key("entity.generic.extinguish_fire")); + + /** + * {@code minecraft:entity.generic.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_HURT = create(key("entity.generic.hurt")); + + /** + * {@code minecraft:entity.generic.small_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_SMALL_FALL = create(key("entity.generic.small_fall")); + + /** + * {@code minecraft:entity.generic.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_SPLASH = create(key("entity.generic.splash")); + + /** + * {@code minecraft:entity.generic.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GENERIC_SWIM = create(key("entity.generic.swim")); + + /** + * {@code minecraft:entity.ghast.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_AMBIENT = create(key("entity.ghast.ambient")); + + /** + * {@code minecraft:entity.ghast.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_DEATH = create(key("entity.ghast.death")); + + /** + * {@code minecraft:entity.ghast.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_HURT = create(key("entity.ghast.hurt")); + + /** + * {@code minecraft:entity.ghast.scream} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_SCREAM = create(key("entity.ghast.scream")); + + /** + * {@code minecraft:entity.ghast.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_SHOOT = create(key("entity.ghast.shoot")); + + /** + * {@code minecraft:entity.ghast.warn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GHAST_WARN = create(key("entity.ghast.warn")); + + /** + * {@code minecraft:entity.glow_item_frame.add_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_ITEM_FRAME_ADD_ITEM = create(key("entity.glow_item_frame.add_item")); + + /** + * {@code minecraft:entity.glow_item_frame.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_ITEM_FRAME_BREAK = create(key("entity.glow_item_frame.break")); + + /** + * {@code minecraft:entity.glow_item_frame.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_ITEM_FRAME_PLACE = create(key("entity.glow_item_frame.place")); + + /** + * {@code minecraft:entity.glow_item_frame.remove_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_ITEM_FRAME_REMOVE_ITEM = create(key("entity.glow_item_frame.remove_item")); + + /** + * {@code minecraft:entity.glow_item_frame.rotate_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_ITEM_FRAME_ROTATE_ITEM = create(key("entity.glow_item_frame.rotate_item")); + + /** + * {@code minecraft:entity.glow_squid.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_SQUID_AMBIENT = create(key("entity.glow_squid.ambient")); + + /** + * {@code minecraft:entity.glow_squid.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_SQUID_DEATH = create(key("entity.glow_squid.death")); + + /** + * {@code minecraft:entity.glow_squid.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_SQUID_HURT = create(key("entity.glow_squid.hurt")); + + /** + * {@code minecraft:entity.glow_squid.squirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GLOW_SQUID_SQUIRT = create(key("entity.glow_squid.squirt")); + + /** + * {@code minecraft:entity.goat.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_AMBIENT = create(key("entity.goat.ambient")); + + /** + * {@code minecraft:entity.goat.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_DEATH = create(key("entity.goat.death")); + + /** + * {@code minecraft:entity.goat.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_EAT = create(key("entity.goat.eat")); + + /** + * {@code minecraft:entity.goat.horn_break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_HORN_BREAK = create(key("entity.goat.horn_break")); + + /** + * {@code minecraft:entity.goat.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_HURT = create(key("entity.goat.hurt")); + + /** + * {@code minecraft:entity.goat.long_jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_LONG_JUMP = create(key("entity.goat.long_jump")); + + /** + * {@code minecraft:entity.goat.milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_MILK = create(key("entity.goat.milk")); + + /** + * {@code minecraft:entity.goat.prepare_ram} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_PREPARE_RAM = create(key("entity.goat.prepare_ram")); + + /** + * {@code minecraft:entity.goat.ram_impact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_RAM_IMPACT = create(key("entity.goat.ram_impact")); + + /** + * {@code minecraft:entity.goat.screaming.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_AMBIENT = create(key("entity.goat.screaming.ambient")); + + /** + * {@code minecraft:entity.goat.screaming.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_DEATH = create(key("entity.goat.screaming.death")); + + /** + * {@code minecraft:entity.goat.screaming.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_EAT = create(key("entity.goat.screaming.eat")); + + /** + * {@code minecraft:entity.goat.screaming.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_HURT = create(key("entity.goat.screaming.hurt")); + + /** + * {@code minecraft:entity.goat.screaming.long_jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_LONG_JUMP = create(key("entity.goat.screaming.long_jump")); + + /** + * {@code minecraft:entity.goat.screaming.milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_MILK = create(key("entity.goat.screaming.milk")); + + /** + * {@code minecraft:entity.goat.screaming.prepare_ram} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_PREPARE_RAM = create(key("entity.goat.screaming.prepare_ram")); + + /** + * {@code minecraft:entity.goat.screaming.ram_impact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_SCREAMING_RAM_IMPACT = create(key("entity.goat.screaming.ram_impact")); + + /** + * {@code minecraft:entity.goat.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GOAT_STEP = create(key("entity.goat.step")); + + /** + * {@code minecraft:entity.guardian.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_AMBIENT = create(key("entity.guardian.ambient")); + + /** + * {@code minecraft:entity.guardian.ambient_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_AMBIENT_LAND = create(key("entity.guardian.ambient_land")); + + /** + * {@code minecraft:entity.guardian.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_ATTACK = create(key("entity.guardian.attack")); + + /** + * {@code minecraft:entity.guardian.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_DEATH = create(key("entity.guardian.death")); + + /** + * {@code minecraft:entity.guardian.death_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_DEATH_LAND = create(key("entity.guardian.death_land")); + + /** + * {@code minecraft:entity.guardian.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_FLOP = create(key("entity.guardian.flop")); + + /** + * {@code minecraft:entity.guardian.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_HURT = create(key("entity.guardian.hurt")); + + /** + * {@code minecraft:entity.guardian.hurt_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_GUARDIAN_HURT_LAND = create(key("entity.guardian.hurt_land")); + + /** + * {@code minecraft:entity.hoglin.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_AMBIENT = create(key("entity.hoglin.ambient")); + + /** + * {@code minecraft:entity.hoglin.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_ANGRY = create(key("entity.hoglin.angry")); + + /** + * {@code minecraft:entity.hoglin.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_ATTACK = create(key("entity.hoglin.attack")); + + /** + * {@code minecraft:entity.hoglin.converted_to_zombified} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED = create(key("entity.hoglin.converted_to_zombified")); + + /** + * {@code minecraft:entity.hoglin.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_DEATH = create(key("entity.hoglin.death")); + + /** + * {@code minecraft:entity.hoglin.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_HURT = create(key("entity.hoglin.hurt")); + + /** + * {@code minecraft:entity.hoglin.retreat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_RETREAT = create(key("entity.hoglin.retreat")); + + /** + * {@code minecraft:entity.hoglin.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOGLIN_STEP = create(key("entity.hoglin.step")); + + /** + * {@code minecraft:entity.horse.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_AMBIENT = create(key("entity.horse.ambient")); + + /** + * {@code minecraft:entity.horse.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_ANGRY = create(key("entity.horse.angry")); + + /** + * {@code minecraft:entity.horse.armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_ARMOR = create(key("entity.horse.armor")); + + /** + * {@code minecraft:entity.horse.breathe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_BREATHE = create(key("entity.horse.breathe")); + + /** + * {@code minecraft:entity.horse.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_DEATH = create(key("entity.horse.death")); + + /** + * {@code minecraft:entity.horse.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_EAT = create(key("entity.horse.eat")); + + /** + * {@code minecraft:entity.horse.gallop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_GALLOP = create(key("entity.horse.gallop")); + + /** + * {@code minecraft:entity.horse.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_HURT = create(key("entity.horse.hurt")); + + /** + * {@code minecraft:entity.horse.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_JUMP = create(key("entity.horse.jump")); + + /** + * {@code minecraft:entity.horse.land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_LAND = create(key("entity.horse.land")); + + /** + * {@code minecraft:entity.horse.saddle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_SADDLE = create(key("entity.horse.saddle")); + + /** + * {@code minecraft:entity.horse.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_STEP = create(key("entity.horse.step")); + + /** + * {@code minecraft:entity.horse.step_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HORSE_STEP_WOOD = create(key("entity.horse.step_wood")); + + /** + * {@code minecraft:entity.hostile.big_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_BIG_FALL = create(key("entity.hostile.big_fall")); + + /** + * {@code minecraft:entity.hostile.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_DEATH = create(key("entity.hostile.death")); + + /** + * {@code minecraft:entity.hostile.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_HURT = create(key("entity.hostile.hurt")); + + /** + * {@code minecraft:entity.hostile.small_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_SMALL_FALL = create(key("entity.hostile.small_fall")); + + /** + * {@code minecraft:entity.hostile.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_SPLASH = create(key("entity.hostile.splash")); + + /** + * {@code minecraft:entity.hostile.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HOSTILE_SWIM = create(key("entity.hostile.swim")); + + /** + * {@code minecraft:entity.husk.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HUSK_AMBIENT = create(key("entity.husk.ambient")); + + /** + * {@code minecraft:entity.husk.converted_to_zombie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HUSK_CONVERTED_TO_ZOMBIE = create(key("entity.husk.converted_to_zombie")); + + /** + * {@code minecraft:entity.husk.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HUSK_DEATH = create(key("entity.husk.death")); + + /** + * {@code minecraft:entity.husk.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HUSK_HURT = create(key("entity.husk.hurt")); + + /** + * {@code minecraft:entity.husk.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_HUSK_STEP = create(key("entity.husk.step")); + + /** + * {@code minecraft:entity.illusioner.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_AMBIENT = create(key("entity.illusioner.ambient")); + + /** + * {@code minecraft:entity.illusioner.cast_spell} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_CAST_SPELL = create(key("entity.illusioner.cast_spell")); + + /** + * {@code minecraft:entity.illusioner.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_DEATH = create(key("entity.illusioner.death")); + + /** + * {@code minecraft:entity.illusioner.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_HURT = create(key("entity.illusioner.hurt")); + + /** + * {@code minecraft:entity.illusioner.mirror_move} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_MIRROR_MOVE = create(key("entity.illusioner.mirror_move")); + + /** + * {@code minecraft:entity.illusioner.prepare_blindness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_PREPARE_BLINDNESS = create(key("entity.illusioner.prepare_blindness")); + + /** + * {@code minecraft:entity.illusioner.prepare_mirror} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ILLUSIONER_PREPARE_MIRROR = create(key("entity.illusioner.prepare_mirror")); + + /** + * {@code minecraft:entity.iron_golem.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_ATTACK = create(key("entity.iron_golem.attack")); + + /** + * {@code minecraft:entity.iron_golem.damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_DAMAGE = create(key("entity.iron_golem.damage")); + + /** + * {@code minecraft:entity.iron_golem.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_DEATH = create(key("entity.iron_golem.death")); + + /** + * {@code minecraft:entity.iron_golem.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_HURT = create(key("entity.iron_golem.hurt")); + + /** + * {@code minecraft:entity.iron_golem.repair} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_REPAIR = create(key("entity.iron_golem.repair")); + + /** + * {@code minecraft:entity.iron_golem.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_IRON_GOLEM_STEP = create(key("entity.iron_golem.step")); + + /** + * {@code minecraft:entity.item.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_BREAK = create(key("entity.item.break")); + + /** + * {@code minecraft:entity.item.pickup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_PICKUP = create(key("entity.item.pickup")); + + /** + * {@code minecraft:entity.item_frame.add_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_FRAME_ADD_ITEM = create(key("entity.item_frame.add_item")); + + /** + * {@code minecraft:entity.item_frame.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_FRAME_BREAK = create(key("entity.item_frame.break")); + + /** + * {@code minecraft:entity.item_frame.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_FRAME_PLACE = create(key("entity.item_frame.place")); + + /** + * {@code minecraft:entity.item_frame.remove_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_FRAME_REMOVE_ITEM = create(key("entity.item_frame.remove_item")); + + /** + * {@code minecraft:entity.item_frame.rotate_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ITEM_FRAME_ROTATE_ITEM = create(key("entity.item_frame.rotate_item")); + + /** + * {@code minecraft:entity.leash_knot.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LEASH_KNOT_BREAK = create(key("entity.leash_knot.break")); + + /** + * {@code minecraft:entity.leash_knot.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LEASH_KNOT_PLACE = create(key("entity.leash_knot.place")); + + /** + * {@code minecraft:entity.lightning_bolt.impact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LIGHTNING_BOLT_IMPACT = create(key("entity.lightning_bolt.impact")); + + /** + * {@code minecraft:entity.lightning_bolt.thunder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LIGHTNING_BOLT_THUNDER = create(key("entity.lightning_bolt.thunder")); + + /** + * {@code minecraft:entity.lingering_potion.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LINGERING_POTION_THROW = create(key("entity.lingering_potion.throw")); + + /** + * {@code minecraft:entity.llama.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_AMBIENT = create(key("entity.llama.ambient")); + + /** + * {@code minecraft:entity.llama.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_ANGRY = create(key("entity.llama.angry")); + + /** + * {@code minecraft:entity.llama.chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_CHEST = create(key("entity.llama.chest")); + + /** + * {@code minecraft:entity.llama.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_DEATH = create(key("entity.llama.death")); + + /** + * {@code minecraft:entity.llama.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_EAT = create(key("entity.llama.eat")); + + /** + * {@code minecraft:entity.llama.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_HURT = create(key("entity.llama.hurt")); + + /** + * {@code minecraft:entity.llama.spit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_SPIT = create(key("entity.llama.spit")); + + /** + * {@code minecraft:entity.llama.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_STEP = create(key("entity.llama.step")); + + /** + * {@code minecraft:entity.llama.swag} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_LLAMA_SWAG = create(key("entity.llama.swag")); + + /** + * {@code minecraft:entity.magma_cube.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_DEATH = create(key("entity.magma_cube.death")); + + /** + * {@code minecraft:entity.magma_cube.death_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_DEATH_SMALL = create(key("entity.magma_cube.death_small")); + + /** + * {@code minecraft:entity.magma_cube.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_HURT = create(key("entity.magma_cube.hurt")); + + /** + * {@code minecraft:entity.magma_cube.hurt_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_HURT_SMALL = create(key("entity.magma_cube.hurt_small")); + + /** + * {@code minecraft:entity.magma_cube.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_JUMP = create(key("entity.magma_cube.jump")); + + /** + * {@code minecraft:entity.magma_cube.squish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_SQUISH = create(key("entity.magma_cube.squish")); + + /** + * {@code minecraft:entity.magma_cube.squish_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MAGMA_CUBE_SQUISH_SMALL = create(key("entity.magma_cube.squish_small")); + + /** + * {@code minecraft:entity.minecart.inside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MINECART_INSIDE = create(key("entity.minecart.inside")); + + /** + * {@code minecraft:entity.minecart.inside.underwater} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MINECART_INSIDE_UNDERWATER = create(key("entity.minecart.inside.underwater")); + + /** + * {@code minecraft:entity.minecart.riding} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MINECART_RIDING = create(key("entity.minecart.riding")); + + /** + * {@code minecraft:entity.mooshroom.convert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOOSHROOM_CONVERT = create(key("entity.mooshroom.convert")); + + /** + * {@code minecraft:entity.mooshroom.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOOSHROOM_EAT = create(key("entity.mooshroom.eat")); + + /** + * {@code minecraft:entity.mooshroom.milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOOSHROOM_MILK = create(key("entity.mooshroom.milk")); + + /** + * {@code minecraft:entity.mooshroom.shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOOSHROOM_SHEAR = create(key("entity.mooshroom.shear")); + + /** + * {@code minecraft:entity.mooshroom.suspicious_milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOOSHROOM_SUSPICIOUS_MILK = create(key("entity.mooshroom.suspicious_milk")); + + /** + * {@code minecraft:entity.mule.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_AMBIENT = create(key("entity.mule.ambient")); + + /** + * {@code minecraft:entity.mule.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_ANGRY = create(key("entity.mule.angry")); + + /** + * {@code minecraft:entity.mule.chest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_CHEST = create(key("entity.mule.chest")); + + /** + * {@code minecraft:entity.mule.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_DEATH = create(key("entity.mule.death")); + + /** + * {@code minecraft:entity.mule.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_EAT = create(key("entity.mule.eat")); + + /** + * {@code minecraft:entity.mule.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_HURT = create(key("entity.mule.hurt")); + + /** + * {@code minecraft:entity.mule.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MULE_JUMP = create(key("entity.mule.jump")); + + /** + * {@code minecraft:entity.ocelot.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_OCELOT_AMBIENT = create(key("entity.ocelot.ambient")); + + /** + * {@code minecraft:entity.ocelot.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_OCELOT_DEATH = create(key("entity.ocelot.death")); + + /** + * {@code minecraft:entity.ocelot.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_OCELOT_HURT = create(key("entity.ocelot.hurt")); + + /** + * {@code minecraft:entity.painting.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PAINTING_BREAK = create(key("entity.painting.break")); + + /** + * {@code minecraft:entity.painting.place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PAINTING_PLACE = create(key("entity.painting.place")); + + /** + * {@code minecraft:entity.panda.aggressive_ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_AGGRESSIVE_AMBIENT = create(key("entity.panda.aggressive_ambient")); + + /** + * {@code minecraft:entity.panda.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_AMBIENT = create(key("entity.panda.ambient")); + + /** + * {@code minecraft:entity.panda.bite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_BITE = create(key("entity.panda.bite")); + + /** + * {@code minecraft:entity.panda.cant_breed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_CANT_BREED = create(key("entity.panda.cant_breed")); + + /** + * {@code minecraft:entity.panda.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_DEATH = create(key("entity.panda.death")); + + /** + * {@code minecraft:entity.panda.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_EAT = create(key("entity.panda.eat")); + + /** + * {@code minecraft:entity.panda.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_HURT = create(key("entity.panda.hurt")); + + /** + * {@code minecraft:entity.panda.pre_sneeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_PRE_SNEEZE = create(key("entity.panda.pre_sneeze")); + + /** + * {@code minecraft:entity.panda.sneeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_SNEEZE = create(key("entity.panda.sneeze")); + + /** + * {@code minecraft:entity.panda.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_STEP = create(key("entity.panda.step")); + + /** + * {@code minecraft:entity.panda.worried_ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PANDA_WORRIED_AMBIENT = create(key("entity.panda.worried_ambient")); + + /** + * {@code minecraft:entity.parrot.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_AMBIENT = create(key("entity.parrot.ambient")); + + /** + * {@code minecraft:entity.parrot.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_DEATH = create(key("entity.parrot.death")); + + /** + * {@code minecraft:entity.parrot.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_EAT = create(key("entity.parrot.eat")); + + /** + * {@code minecraft:entity.parrot.fly} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_FLY = create(key("entity.parrot.fly")); + + /** + * {@code minecraft:entity.parrot.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_HURT = create(key("entity.parrot.hurt")); + + /** + * {@code minecraft:entity.parrot.imitate.blaze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_BLAZE = create(key("entity.parrot.imitate.blaze")); + + /** + * {@code minecraft:entity.parrot.imitate.bogged} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_BOGGED = create(key("entity.parrot.imitate.bogged")); + + /** + * {@code minecraft:entity.parrot.imitate.breeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_BREEZE = create(key("entity.parrot.imitate.breeze")); + + /** + * {@code minecraft:entity.parrot.imitate.creaking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_CREAKING = create(key("entity.parrot.imitate.creaking")); + + /** + * {@code minecraft:entity.parrot.imitate.creeper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_CREEPER = create(key("entity.parrot.imitate.creeper")); + + /** + * {@code minecraft:entity.parrot.imitate.drowned} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_DROWNED = create(key("entity.parrot.imitate.drowned")); + + /** + * {@code minecraft:entity.parrot.imitate.elder_guardian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ELDER_GUARDIAN = create(key("entity.parrot.imitate.elder_guardian")); + + /** + * {@code minecraft:entity.parrot.imitate.ender_dragon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ENDER_DRAGON = create(key("entity.parrot.imitate.ender_dragon")); + + /** + * {@code minecraft:entity.parrot.imitate.endermite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ENDERMITE = create(key("entity.parrot.imitate.endermite")); + + /** + * {@code minecraft:entity.parrot.imitate.evoker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_EVOKER = create(key("entity.parrot.imitate.evoker")); + + /** + * {@code minecraft:entity.parrot.imitate.ghast} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_GHAST = create(key("entity.parrot.imitate.ghast")); + + /** + * {@code minecraft:entity.parrot.imitate.guardian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_GUARDIAN = create(key("entity.parrot.imitate.guardian")); + + /** + * {@code minecraft:entity.parrot.imitate.hoglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_HOGLIN = create(key("entity.parrot.imitate.hoglin")); + + /** + * {@code minecraft:entity.parrot.imitate.husk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_HUSK = create(key("entity.parrot.imitate.husk")); + + /** + * {@code minecraft:entity.parrot.imitate.illusioner} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ILLUSIONER = create(key("entity.parrot.imitate.illusioner")); + + /** + * {@code minecraft:entity.parrot.imitate.magma_cube} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_MAGMA_CUBE = create(key("entity.parrot.imitate.magma_cube")); + + /** + * {@code minecraft:entity.parrot.imitate.phantom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_PHANTOM = create(key("entity.parrot.imitate.phantom")); + + /** + * {@code minecraft:entity.parrot.imitate.piglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_PIGLIN = create(key("entity.parrot.imitate.piglin")); + + /** + * {@code minecraft:entity.parrot.imitate.piglin_brute} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_PIGLIN_BRUTE = create(key("entity.parrot.imitate.piglin_brute")); + + /** + * {@code minecraft:entity.parrot.imitate.pillager} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_PILLAGER = create(key("entity.parrot.imitate.pillager")); + + /** + * {@code minecraft:entity.parrot.imitate.ravager} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_RAVAGER = create(key("entity.parrot.imitate.ravager")); + + /** + * {@code minecraft:entity.parrot.imitate.shulker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_SHULKER = create(key("entity.parrot.imitate.shulker")); + + /** + * {@code minecraft:entity.parrot.imitate.silverfish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_SILVERFISH = create(key("entity.parrot.imitate.silverfish")); + + /** + * {@code minecraft:entity.parrot.imitate.skeleton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_SKELETON = create(key("entity.parrot.imitate.skeleton")); + + /** + * {@code minecraft:entity.parrot.imitate.slime} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_SLIME = create(key("entity.parrot.imitate.slime")); + + /** + * {@code minecraft:entity.parrot.imitate.spider} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_SPIDER = create(key("entity.parrot.imitate.spider")); + + /** + * {@code minecraft:entity.parrot.imitate.stray} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_STRAY = create(key("entity.parrot.imitate.stray")); + + /** + * {@code minecraft:entity.parrot.imitate.vex} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_VEX = create(key("entity.parrot.imitate.vex")); + + /** + * {@code minecraft:entity.parrot.imitate.vindicator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_VINDICATOR = create(key("entity.parrot.imitate.vindicator")); + + /** + * {@code minecraft:entity.parrot.imitate.warden} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_WARDEN = create(key("entity.parrot.imitate.warden")); + + /** + * {@code minecraft:entity.parrot.imitate.witch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_WITCH = create(key("entity.parrot.imitate.witch")); + + /** + * {@code minecraft:entity.parrot.imitate.wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_WITHER = create(key("entity.parrot.imitate.wither")); + + /** + * {@code minecraft:entity.parrot.imitate.wither_skeleton} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_WITHER_SKELETON = create(key("entity.parrot.imitate.wither_skeleton")); + + /** + * {@code minecraft:entity.parrot.imitate.zoglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ZOGLIN = create(key("entity.parrot.imitate.zoglin")); + + /** + * {@code minecraft:entity.parrot.imitate.zombie} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ZOMBIE = create(key("entity.parrot.imitate.zombie")); + + /** + * {@code minecraft:entity.parrot.imitate.zombie_villager} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_IMITATE_ZOMBIE_VILLAGER = create(key("entity.parrot.imitate.zombie_villager")); + + /** + * {@code minecraft:entity.parrot.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PARROT_STEP = create(key("entity.parrot.step")); + + /** + * {@code minecraft:entity.phantom.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_AMBIENT = create(key("entity.phantom.ambient")); + + /** + * {@code minecraft:entity.phantom.bite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_BITE = create(key("entity.phantom.bite")); + + /** + * {@code minecraft:entity.phantom.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_DEATH = create(key("entity.phantom.death")); + + /** + * {@code minecraft:entity.phantom.flap} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_FLAP = create(key("entity.phantom.flap")); + + /** + * {@code minecraft:entity.phantom.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_HURT = create(key("entity.phantom.hurt")); + + /** + * {@code minecraft:entity.phantom.swoop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PHANTOM_SWOOP = create(key("entity.phantom.swoop")); + + /** + * {@code minecraft:entity.pig.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIG_AMBIENT = create(key("entity.pig.ambient")); + + /** + * {@code minecraft:entity.pig.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIG_DEATH = create(key("entity.pig.death")); + + /** + * {@code minecraft:entity.pig.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIG_HURT = create(key("entity.pig.hurt")); + + /** + * {@code minecraft:entity.pig.saddle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIG_SADDLE = create(key("entity.pig.saddle")); + + /** + * {@code minecraft:entity.pig.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIG_STEP = create(key("entity.pig.step")); + + /** + * {@code minecraft:entity.piglin.admiring_item} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_ADMIRING_ITEM = create(key("entity.piglin.admiring_item")); + + /** + * {@code minecraft:entity.piglin.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_AMBIENT = create(key("entity.piglin.ambient")); + + /** + * {@code minecraft:entity.piglin.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_ANGRY = create(key("entity.piglin.angry")); + + /** + * {@code minecraft:entity.piglin.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_CELEBRATE = create(key("entity.piglin.celebrate")); + + /** + * {@code minecraft:entity.piglin.converted_to_zombified} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED = create(key("entity.piglin.converted_to_zombified")); + + /** + * {@code minecraft:entity.piglin.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_DEATH = create(key("entity.piglin.death")); + + /** + * {@code minecraft:entity.piglin.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_HURT = create(key("entity.piglin.hurt")); + + /** + * {@code minecraft:entity.piglin.jealous} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_JEALOUS = create(key("entity.piglin.jealous")); + + /** + * {@code minecraft:entity.piglin.retreat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_RETREAT = create(key("entity.piglin.retreat")); + + /** + * {@code minecraft:entity.piglin.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_STEP = create(key("entity.piglin.step")); + + /** + * {@code minecraft:entity.piglin_brute.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_AMBIENT = create(key("entity.piglin_brute.ambient")); + + /** + * {@code minecraft:entity.piglin_brute.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_ANGRY = create(key("entity.piglin_brute.angry")); + + /** + * {@code minecraft:entity.piglin_brute.converted_to_zombified} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED = create(key("entity.piglin_brute.converted_to_zombified")); + + /** + * {@code minecraft:entity.piglin_brute.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_DEATH = create(key("entity.piglin_brute.death")); + + /** + * {@code minecraft:entity.piglin_brute.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_HURT = create(key("entity.piglin_brute.hurt")); + + /** + * {@code minecraft:entity.piglin_brute.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PIGLIN_BRUTE_STEP = create(key("entity.piglin_brute.step")); + + /** + * {@code minecraft:entity.pillager.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PILLAGER_AMBIENT = create(key("entity.pillager.ambient")); + + /** + * {@code minecraft:entity.pillager.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PILLAGER_CELEBRATE = create(key("entity.pillager.celebrate")); + + /** + * {@code minecraft:entity.pillager.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PILLAGER_DEATH = create(key("entity.pillager.death")); + + /** + * {@code minecraft:entity.pillager.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PILLAGER_HURT = create(key("entity.pillager.hurt")); + + /** + * {@code minecraft:entity.player.attack.crit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_CRIT = create(key("entity.player.attack.crit")); + + /** + * {@code minecraft:entity.player.attack.knockback} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_KNOCKBACK = create(key("entity.player.attack.knockback")); + + /** + * {@code minecraft:entity.player.attack.nodamage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_NODAMAGE = create(key("entity.player.attack.nodamage")); + + /** + * {@code minecraft:entity.player.attack.strong} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_STRONG = create(key("entity.player.attack.strong")); + + /** + * {@code minecraft:entity.player.attack.sweep} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_SWEEP = create(key("entity.player.attack.sweep")); + + /** + * {@code minecraft:entity.player.attack.weak} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_ATTACK_WEAK = create(key("entity.player.attack.weak")); + + /** + * {@code minecraft:entity.player.big_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_BIG_FALL = create(key("entity.player.big_fall")); + + /** + * {@code minecraft:entity.player.breath} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_BREATH = create(key("entity.player.breath")); + + /** + * {@code minecraft:entity.player.burp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_BURP = create(key("entity.player.burp")); + + /** + * {@code minecraft:entity.player.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_DEATH = create(key("entity.player.death")); + + /** + * {@code minecraft:entity.player.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_HURT = create(key("entity.player.hurt")); + + /** + * {@code minecraft:entity.player.hurt_drown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_HURT_DROWN = create(key("entity.player.hurt_drown")); + + /** + * {@code minecraft:entity.player.hurt_freeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_HURT_FREEZE = create(key("entity.player.hurt_freeze")); + + /** + * {@code minecraft:entity.player.hurt_on_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_HURT_ON_FIRE = create(key("entity.player.hurt_on_fire")); + + /** + * {@code minecraft:entity.player.hurt_sweet_berry_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH = create(key("entity.player.hurt_sweet_berry_bush")); + + /** + * {@code minecraft:entity.player.levelup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_LEVELUP = create(key("entity.player.levelup")); + + /** + * {@code minecraft:entity.player.small_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_SMALL_FALL = create(key("entity.player.small_fall")); + + /** + * {@code minecraft:entity.player.splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_SPLASH = create(key("entity.player.splash")); + + /** + * {@code minecraft:entity.player.splash.high_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_SPLASH_HIGH_SPEED = create(key("entity.player.splash.high_speed")); + + /** + * {@code minecraft:entity.player.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_SWIM = create(key("entity.player.swim")); + + /** + * {@code minecraft:entity.player.teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLAYER_TELEPORT = create(key("entity.player.teleport")); + + /** + * {@code minecraft:entity.polar_bear.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_AMBIENT = create(key("entity.polar_bear.ambient")); + + /** + * {@code minecraft:entity.polar_bear.ambient_baby} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_AMBIENT_BABY = create(key("entity.polar_bear.ambient_baby")); + + /** + * {@code minecraft:entity.polar_bear.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_DEATH = create(key("entity.polar_bear.death")); + + /** + * {@code minecraft:entity.polar_bear.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_HURT = create(key("entity.polar_bear.hurt")); + + /** + * {@code minecraft:entity.polar_bear.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_STEP = create(key("entity.polar_bear.step")); + + /** + * {@code minecraft:entity.polar_bear.warning} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_POLAR_BEAR_WARNING = create(key("entity.polar_bear.warning")); + + /** + * {@code minecraft:entity.puffer_fish.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_AMBIENT = create(key("entity.puffer_fish.ambient")); + + /** + * {@code minecraft:entity.puffer_fish.blow_out} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_BLOW_OUT = create(key("entity.puffer_fish.blow_out")); + + /** + * {@code minecraft:entity.puffer_fish.blow_up} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_BLOW_UP = create(key("entity.puffer_fish.blow_up")); + + /** + * {@code minecraft:entity.puffer_fish.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_DEATH = create(key("entity.puffer_fish.death")); + + /** + * {@code minecraft:entity.puffer_fish.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_FLOP = create(key("entity.puffer_fish.flop")); + + /** + * {@code minecraft:entity.puffer_fish.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_HURT = create(key("entity.puffer_fish.hurt")); + + /** + * {@code minecraft:entity.puffer_fish.sting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PUFFER_FISH_STING = create(key("entity.puffer_fish.sting")); + + /** + * {@code minecraft:entity.rabbit.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RABBIT_AMBIENT = create(key("entity.rabbit.ambient")); + + /** + * {@code minecraft:entity.rabbit.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RABBIT_ATTACK = create(key("entity.rabbit.attack")); + + /** + * {@code minecraft:entity.rabbit.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RABBIT_DEATH = create(key("entity.rabbit.death")); + + /** + * {@code minecraft:entity.rabbit.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RABBIT_HURT = create(key("entity.rabbit.hurt")); + + /** + * {@code minecraft:entity.rabbit.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RABBIT_JUMP = create(key("entity.rabbit.jump")); + + /** + * {@code minecraft:entity.ravager.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_AMBIENT = create(key("entity.ravager.ambient")); + + /** + * {@code minecraft:entity.ravager.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_ATTACK = create(key("entity.ravager.attack")); + + /** + * {@code minecraft:entity.ravager.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_CELEBRATE = create(key("entity.ravager.celebrate")); + + /** + * {@code minecraft:entity.ravager.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_DEATH = create(key("entity.ravager.death")); + + /** + * {@code minecraft:entity.ravager.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_HURT = create(key("entity.ravager.hurt")); + + /** + * {@code minecraft:entity.ravager.roar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_ROAR = create(key("entity.ravager.roar")); + + /** + * {@code minecraft:entity.ravager.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_STEP = create(key("entity.ravager.step")); + + /** + * {@code minecraft:entity.ravager.stunned} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_RAVAGER_STUNNED = create(key("entity.ravager.stunned")); + + /** + * {@code minecraft:entity.salmon.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SALMON_AMBIENT = create(key("entity.salmon.ambient")); + + /** + * {@code minecraft:entity.salmon.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SALMON_DEATH = create(key("entity.salmon.death")); + + /** + * {@code minecraft:entity.salmon.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SALMON_FLOP = create(key("entity.salmon.flop")); + + /** + * {@code minecraft:entity.salmon.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SALMON_HURT = create(key("entity.salmon.hurt")); + + /** + * {@code minecraft:entity.sheep.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHEEP_AMBIENT = create(key("entity.sheep.ambient")); + + /** + * {@code minecraft:entity.sheep.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHEEP_DEATH = create(key("entity.sheep.death")); + + /** + * {@code minecraft:entity.sheep.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHEEP_HURT = create(key("entity.sheep.hurt")); + + /** + * {@code minecraft:entity.sheep.shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHEEP_SHEAR = create(key("entity.sheep.shear")); + + /** + * {@code minecraft:entity.sheep.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHEEP_STEP = create(key("entity.sheep.step")); + + /** + * {@code minecraft:entity.shulker.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_AMBIENT = create(key("entity.shulker.ambient")); + + /** + * {@code minecraft:entity.shulker.close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_CLOSE = create(key("entity.shulker.close")); + + /** + * {@code minecraft:entity.shulker.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_DEATH = create(key("entity.shulker.death")); + + /** + * {@code minecraft:entity.shulker.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_HURT = create(key("entity.shulker.hurt")); + + /** + * {@code minecraft:entity.shulker.hurt_closed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_HURT_CLOSED = create(key("entity.shulker.hurt_closed")); + + /** + * {@code minecraft:entity.shulker.open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_OPEN = create(key("entity.shulker.open")); + + /** + * {@code minecraft:entity.shulker.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_SHOOT = create(key("entity.shulker.shoot")); + + /** + * {@code minecraft:entity.shulker.teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_TELEPORT = create(key("entity.shulker.teleport")); + + /** + * {@code minecraft:entity.shulker_bullet.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_BULLET_HIT = create(key("entity.shulker_bullet.hit")); + + /** + * {@code minecraft:entity.shulker_bullet.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SHULKER_BULLET_HURT = create(key("entity.shulker_bullet.hurt")); + + /** + * {@code minecraft:entity.silverfish.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SILVERFISH_AMBIENT = create(key("entity.silverfish.ambient")); + + /** + * {@code minecraft:entity.silverfish.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SILVERFISH_DEATH = create(key("entity.silverfish.death")); + + /** + * {@code minecraft:entity.silverfish.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SILVERFISH_HURT = create(key("entity.silverfish.hurt")); + + /** + * {@code minecraft:entity.silverfish.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SILVERFISH_STEP = create(key("entity.silverfish.step")); + + /** + * {@code minecraft:entity.skeleton.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_AMBIENT = create(key("entity.skeleton.ambient")); + + /** + * {@code minecraft:entity.skeleton.converted_to_stray} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_CONVERTED_TO_STRAY = create(key("entity.skeleton.converted_to_stray")); + + /** + * {@code minecraft:entity.skeleton.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_DEATH = create(key("entity.skeleton.death")); + + /** + * {@code minecraft:entity.skeleton.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HURT = create(key("entity.skeleton.hurt")); + + /** + * {@code minecraft:entity.skeleton.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_SHOOT = create(key("entity.skeleton.shoot")); + + /** + * {@code minecraft:entity.skeleton.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_STEP = create(key("entity.skeleton.step")); + + /** + * {@code minecraft:entity.skeleton_horse.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_AMBIENT = create(key("entity.skeleton_horse.ambient")); + + /** + * {@code minecraft:entity.skeleton_horse.ambient_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_AMBIENT_WATER = create(key("entity.skeleton_horse.ambient_water")); + + /** + * {@code minecraft:entity.skeleton_horse.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_DEATH = create(key("entity.skeleton_horse.death")); + + /** + * {@code minecraft:entity.skeleton_horse.gallop_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_GALLOP_WATER = create(key("entity.skeleton_horse.gallop_water")); + + /** + * {@code minecraft:entity.skeleton_horse.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_HURT = create(key("entity.skeleton_horse.hurt")); + + /** + * {@code minecraft:entity.skeleton_horse.jump_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_JUMP_WATER = create(key("entity.skeleton_horse.jump_water")); + + /** + * {@code minecraft:entity.skeleton_horse.step_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_STEP_WATER = create(key("entity.skeleton_horse.step_water")); + + /** + * {@code minecraft:entity.skeleton_horse.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SKELETON_HORSE_SWIM = create(key("entity.skeleton_horse.swim")); + + /** + * {@code minecraft:entity.slime.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_ATTACK = create(key("entity.slime.attack")); + + /** + * {@code minecraft:entity.slime.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_DEATH = create(key("entity.slime.death")); + + /** + * {@code minecraft:entity.slime.death_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_DEATH_SMALL = create(key("entity.slime.death_small")); + + /** + * {@code minecraft:entity.slime.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_HURT = create(key("entity.slime.hurt")); + + /** + * {@code minecraft:entity.slime.hurt_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_HURT_SMALL = create(key("entity.slime.hurt_small")); + + /** + * {@code minecraft:entity.slime.jump} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_JUMP = create(key("entity.slime.jump")); + + /** + * {@code minecraft:entity.slime.jump_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_JUMP_SMALL = create(key("entity.slime.jump_small")); + + /** + * {@code minecraft:entity.slime.squish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_SQUISH = create(key("entity.slime.squish")); + + /** + * {@code minecraft:entity.slime.squish_small} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SLIME_SQUISH_SMALL = create(key("entity.slime.squish_small")); + + /** + * {@code minecraft:entity.sniffer.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_DEATH = create(key("entity.sniffer.death")); + + /** + * {@code minecraft:entity.sniffer.digging} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_DIGGING = create(key("entity.sniffer.digging")); + + /** + * {@code minecraft:entity.sniffer.digging_stop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_DIGGING_STOP = create(key("entity.sniffer.digging_stop")); + + /** + * {@code minecraft:entity.sniffer.drop_seed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_DROP_SEED = create(key("entity.sniffer.drop_seed")); + + /** + * {@code minecraft:entity.sniffer.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_EAT = create(key("entity.sniffer.eat")); + + /** + * {@code minecraft:entity.sniffer.happy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_HAPPY = create(key("entity.sniffer.happy")); + + /** + * {@code minecraft:entity.sniffer.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_HURT = create(key("entity.sniffer.hurt")); + + /** + * {@code minecraft:entity.sniffer.idle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_IDLE = create(key("entity.sniffer.idle")); + + /** + * {@code minecraft:entity.sniffer.scenting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_SCENTING = create(key("entity.sniffer.scenting")); + + /** + * {@code minecraft:entity.sniffer.searching} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_SEARCHING = create(key("entity.sniffer.searching")); + + /** + * {@code minecraft:entity.sniffer.sniffing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_SNIFFING = create(key("entity.sniffer.sniffing")); + + /** + * {@code minecraft:entity.sniffer.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNIFFER_STEP = create(key("entity.sniffer.step")); + + /** + * {@code minecraft:entity.snow_golem.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOW_GOLEM_AMBIENT = create(key("entity.snow_golem.ambient")); + + /** + * {@code minecraft:entity.snow_golem.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOW_GOLEM_DEATH = create(key("entity.snow_golem.death")); + + /** + * {@code minecraft:entity.snow_golem.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOW_GOLEM_HURT = create(key("entity.snow_golem.hurt")); + + /** + * {@code minecraft:entity.snow_golem.shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOW_GOLEM_SHEAR = create(key("entity.snow_golem.shear")); + + /** + * {@code minecraft:entity.snow_golem.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOW_GOLEM_SHOOT = create(key("entity.snow_golem.shoot")); + + /** + * {@code minecraft:entity.snowball.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SNOWBALL_THROW = create(key("entity.snowball.throw")); + + /** + * {@code minecraft:entity.spider.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPIDER_AMBIENT = create(key("entity.spider.ambient")); + + /** + * {@code minecraft:entity.spider.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPIDER_DEATH = create(key("entity.spider.death")); + + /** + * {@code minecraft:entity.spider.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPIDER_HURT = create(key("entity.spider.hurt")); + + /** + * {@code minecraft:entity.spider.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPIDER_STEP = create(key("entity.spider.step")); + + /** + * {@code minecraft:entity.splash_potion.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPLASH_POTION_BREAK = create(key("entity.splash_potion.break")); + + /** + * {@code minecraft:entity.splash_potion.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SPLASH_POTION_THROW = create(key("entity.splash_potion.throw")); + + /** + * {@code minecraft:entity.squid.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SQUID_AMBIENT = create(key("entity.squid.ambient")); + + /** + * {@code minecraft:entity.squid.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SQUID_DEATH = create(key("entity.squid.death")); + + /** + * {@code minecraft:entity.squid.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SQUID_HURT = create(key("entity.squid.hurt")); + + /** + * {@code minecraft:entity.squid.squirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_SQUID_SQUIRT = create(key("entity.squid.squirt")); + + /** + * {@code minecraft:entity.stray.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRAY_AMBIENT = create(key("entity.stray.ambient")); + + /** + * {@code minecraft:entity.stray.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRAY_DEATH = create(key("entity.stray.death")); + + /** + * {@code minecraft:entity.stray.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRAY_HURT = create(key("entity.stray.hurt")); + + /** + * {@code minecraft:entity.stray.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRAY_STEP = create(key("entity.stray.step")); + + /** + * {@code minecraft:entity.strider.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_AMBIENT = create(key("entity.strider.ambient")); + + /** + * {@code minecraft:entity.strider.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_DEATH = create(key("entity.strider.death")); + + /** + * {@code minecraft:entity.strider.eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_EAT = create(key("entity.strider.eat")); + + /** + * {@code minecraft:entity.strider.happy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_HAPPY = create(key("entity.strider.happy")); + + /** + * {@code minecraft:entity.strider.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_HURT = create(key("entity.strider.hurt")); + + /** + * {@code minecraft:entity.strider.retreat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_RETREAT = create(key("entity.strider.retreat")); + + /** + * {@code minecraft:entity.strider.saddle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_SADDLE = create(key("entity.strider.saddle")); + + /** + * {@code minecraft:entity.strider.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_STEP = create(key("entity.strider.step")); + + /** + * {@code minecraft:entity.strider.step_lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_STRIDER_STEP_LAVA = create(key("entity.strider.step_lava")); + + /** + * {@code minecraft:entity.tadpole.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TADPOLE_DEATH = create(key("entity.tadpole.death")); + + /** + * {@code minecraft:entity.tadpole.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TADPOLE_FLOP = create(key("entity.tadpole.flop")); + + /** + * {@code minecraft:entity.tadpole.grow_up} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TADPOLE_GROW_UP = create(key("entity.tadpole.grow_up")); + + /** + * {@code minecraft:entity.tadpole.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TADPOLE_HURT = create(key("entity.tadpole.hurt")); + + /** + * {@code minecraft:entity.tnt.primed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TNT_PRIMED = create(key("entity.tnt.primed")); + + /** + * {@code minecraft:entity.tropical_fish.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TROPICAL_FISH_AMBIENT = create(key("entity.tropical_fish.ambient")); + + /** + * {@code minecraft:entity.tropical_fish.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TROPICAL_FISH_DEATH = create(key("entity.tropical_fish.death")); + + /** + * {@code minecraft:entity.tropical_fish.flop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TROPICAL_FISH_FLOP = create(key("entity.tropical_fish.flop")); + + /** + * {@code minecraft:entity.tropical_fish.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TROPICAL_FISH_HURT = create(key("entity.tropical_fish.hurt")); + + /** + * {@code minecraft:entity.turtle.ambient_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_AMBIENT_LAND = create(key("entity.turtle.ambient_land")); + + /** + * {@code minecraft:entity.turtle.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_DEATH = create(key("entity.turtle.death")); + + /** + * {@code minecraft:entity.turtle.death_baby} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_DEATH_BABY = create(key("entity.turtle.death_baby")); + + /** + * {@code minecraft:entity.turtle.egg_break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_EGG_BREAK = create(key("entity.turtle.egg_break")); + + /** + * {@code minecraft:entity.turtle.egg_crack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_EGG_CRACK = create(key("entity.turtle.egg_crack")); + + /** + * {@code minecraft:entity.turtle.egg_hatch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_EGG_HATCH = create(key("entity.turtle.egg_hatch")); + + /** + * {@code minecraft:entity.turtle.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_HURT = create(key("entity.turtle.hurt")); + + /** + * {@code minecraft:entity.turtle.hurt_baby} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_HURT_BABY = create(key("entity.turtle.hurt_baby")); + + /** + * {@code minecraft:entity.turtle.lay_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_LAY_EGG = create(key("entity.turtle.lay_egg")); + + /** + * {@code minecraft:entity.turtle.shamble} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_SHAMBLE = create(key("entity.turtle.shamble")); + + /** + * {@code minecraft:entity.turtle.shamble_baby} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_SHAMBLE_BABY = create(key("entity.turtle.shamble_baby")); + + /** + * {@code minecraft:entity.turtle.swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_TURTLE_SWIM = create(key("entity.turtle.swim")); + + /** + * {@code minecraft:entity.vex.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VEX_AMBIENT = create(key("entity.vex.ambient")); + + /** + * {@code minecraft:entity.vex.charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VEX_CHARGE = create(key("entity.vex.charge")); + + /** + * {@code minecraft:entity.vex.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VEX_DEATH = create(key("entity.vex.death")); + + /** + * {@code minecraft:entity.vex.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VEX_HURT = create(key("entity.vex.hurt")); + + /** + * {@code minecraft:entity.villager.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_AMBIENT = create(key("entity.villager.ambient")); + + /** + * {@code minecraft:entity.villager.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_CELEBRATE = create(key("entity.villager.celebrate")); + + /** + * {@code minecraft:entity.villager.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_DEATH = create(key("entity.villager.death")); + + /** + * {@code minecraft:entity.villager.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_HURT = create(key("entity.villager.hurt")); + + /** + * {@code minecraft:entity.villager.no} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_NO = create(key("entity.villager.no")); + + /** + * {@code minecraft:entity.villager.trade} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_TRADE = create(key("entity.villager.trade")); + + /** + * {@code minecraft:entity.villager.work_armorer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_ARMORER = create(key("entity.villager.work_armorer")); + + /** + * {@code minecraft:entity.villager.work_butcher} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_BUTCHER = create(key("entity.villager.work_butcher")); + + /** + * {@code minecraft:entity.villager.work_cartographer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_CARTOGRAPHER = create(key("entity.villager.work_cartographer")); + + /** + * {@code minecraft:entity.villager.work_cleric} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_CLERIC = create(key("entity.villager.work_cleric")); + + /** + * {@code minecraft:entity.villager.work_farmer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_FARMER = create(key("entity.villager.work_farmer")); + + /** + * {@code minecraft:entity.villager.work_fisherman} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_FISHERMAN = create(key("entity.villager.work_fisherman")); + + /** + * {@code minecraft:entity.villager.work_fletcher} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_FLETCHER = create(key("entity.villager.work_fletcher")); + + /** + * {@code minecraft:entity.villager.work_leatherworker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_LEATHERWORKER = create(key("entity.villager.work_leatherworker")); + + /** + * {@code minecraft:entity.villager.work_librarian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_LIBRARIAN = create(key("entity.villager.work_librarian")); + + /** + * {@code minecraft:entity.villager.work_mason} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_MASON = create(key("entity.villager.work_mason")); + + /** + * {@code minecraft:entity.villager.work_shepherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_SHEPHERD = create(key("entity.villager.work_shepherd")); + + /** + * {@code minecraft:entity.villager.work_toolsmith} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_TOOLSMITH = create(key("entity.villager.work_toolsmith")); + + /** + * {@code minecraft:entity.villager.work_weaponsmith} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_WORK_WEAPONSMITH = create(key("entity.villager.work_weaponsmith")); + + /** + * {@code minecraft:entity.villager.yes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VILLAGER_YES = create(key("entity.villager.yes")); + + /** + * {@code minecraft:entity.vindicator.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VINDICATOR_AMBIENT = create(key("entity.vindicator.ambient")); + + /** + * {@code minecraft:entity.vindicator.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VINDICATOR_CELEBRATE = create(key("entity.vindicator.celebrate")); + + /** + * {@code minecraft:entity.vindicator.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VINDICATOR_DEATH = create(key("entity.vindicator.death")); + + /** + * {@code minecraft:entity.vindicator.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_VINDICATOR_HURT = create(key("entity.vindicator.hurt")); + + /** + * {@code minecraft:entity.wandering_trader.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_AMBIENT = create(key("entity.wandering_trader.ambient")); + + /** + * {@code minecraft:entity.wandering_trader.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_DEATH = create(key("entity.wandering_trader.death")); + + /** + * {@code minecraft:entity.wandering_trader.disappeared} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_DISAPPEARED = create(key("entity.wandering_trader.disappeared")); + + /** + * {@code minecraft:entity.wandering_trader.drink_milk} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_DRINK_MILK = create(key("entity.wandering_trader.drink_milk")); + + /** + * {@code minecraft:entity.wandering_trader.drink_potion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_DRINK_POTION = create(key("entity.wandering_trader.drink_potion")); + + /** + * {@code minecraft:entity.wandering_trader.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_HURT = create(key("entity.wandering_trader.hurt")); + + /** + * {@code minecraft:entity.wandering_trader.no} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_NO = create(key("entity.wandering_trader.no")); + + /** + * {@code minecraft:entity.wandering_trader.reappeared} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_REAPPEARED = create(key("entity.wandering_trader.reappeared")); + + /** + * {@code minecraft:entity.wandering_trader.trade} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_TRADE = create(key("entity.wandering_trader.trade")); + + /** + * {@code minecraft:entity.wandering_trader.yes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WANDERING_TRADER_YES = create(key("entity.wandering_trader.yes")); + + /** + * {@code minecraft:entity.warden.agitated} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_AGITATED = create(key("entity.warden.agitated")); + + /** + * {@code minecraft:entity.warden.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_AMBIENT = create(key("entity.warden.ambient")); + + /** + * {@code minecraft:entity.warden.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_ANGRY = create(key("entity.warden.angry")); + + /** + * {@code minecraft:entity.warden.attack_impact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_ATTACK_IMPACT = create(key("entity.warden.attack_impact")); + + /** + * {@code minecraft:entity.warden.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_DEATH = create(key("entity.warden.death")); + + /** + * {@code minecraft:entity.warden.dig} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_DIG = create(key("entity.warden.dig")); + + /** + * {@code minecraft:entity.warden.emerge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_EMERGE = create(key("entity.warden.emerge")); + + /** + * {@code minecraft:entity.warden.heartbeat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_HEARTBEAT = create(key("entity.warden.heartbeat")); + + /** + * {@code minecraft:entity.warden.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_HURT = create(key("entity.warden.hurt")); + + /** + * {@code minecraft:entity.warden.listening} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_LISTENING = create(key("entity.warden.listening")); + + /** + * {@code minecraft:entity.warden.listening_angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_LISTENING_ANGRY = create(key("entity.warden.listening_angry")); + + /** + * {@code minecraft:entity.warden.nearby_close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_NEARBY_CLOSE = create(key("entity.warden.nearby_close")); + + /** + * {@code minecraft:entity.warden.nearby_closer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_NEARBY_CLOSER = create(key("entity.warden.nearby_closer")); + + /** + * {@code minecraft:entity.warden.nearby_closest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_NEARBY_CLOSEST = create(key("entity.warden.nearby_closest")); + + /** + * {@code minecraft:entity.warden.roar} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_ROAR = create(key("entity.warden.roar")); + + /** + * {@code minecraft:entity.warden.sniff} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_SNIFF = create(key("entity.warden.sniff")); + + /** + * {@code minecraft:entity.warden.sonic_boom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_SONIC_BOOM = create(key("entity.warden.sonic_boom")); + + /** + * {@code minecraft:entity.warden.sonic_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_SONIC_CHARGE = create(key("entity.warden.sonic_charge")); + + /** + * {@code minecraft:entity.warden.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_STEP = create(key("entity.warden.step")); + + /** + * {@code minecraft:entity.warden.tendril_clicks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WARDEN_TENDRIL_CLICKS = create(key("entity.warden.tendril_clicks")); + + /** + * {@code minecraft:entity.wind_charge.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WIND_CHARGE_THROW = create(key("entity.wind_charge.throw")); + + /** + * {@code minecraft:entity.wind_charge.wind_burst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WIND_CHARGE_WIND_BURST = create(key("entity.wind_charge.wind_burst")); + + /** + * {@code minecraft:entity.witch.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_AMBIENT = create(key("entity.witch.ambient")); + + /** + * {@code minecraft:entity.witch.celebrate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_CELEBRATE = create(key("entity.witch.celebrate")); + + /** + * {@code minecraft:entity.witch.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_DEATH = create(key("entity.witch.death")); + + /** + * {@code minecraft:entity.witch.drink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_DRINK = create(key("entity.witch.drink")); + + /** + * {@code minecraft:entity.witch.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_HURT = create(key("entity.witch.hurt")); + + /** + * {@code minecraft:entity.witch.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITCH_THROW = create(key("entity.witch.throw")); + + /** + * {@code minecraft:entity.wither.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_AMBIENT = create(key("entity.wither.ambient")); + + /** + * {@code minecraft:entity.wither.break_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_BREAK_BLOCK = create(key("entity.wither.break_block")); + + /** + * {@code minecraft:entity.wither.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_DEATH = create(key("entity.wither.death")); + + /** + * {@code minecraft:entity.wither.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_HURT = create(key("entity.wither.hurt")); + + /** + * {@code minecraft:entity.wither.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SHOOT = create(key("entity.wither.shoot")); + + /** + * {@code minecraft:entity.wither.spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SPAWN = create(key("entity.wither.spawn")); + + /** + * {@code minecraft:entity.wither_skeleton.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SKELETON_AMBIENT = create(key("entity.wither_skeleton.ambient")); + + /** + * {@code minecraft:entity.wither_skeleton.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SKELETON_DEATH = create(key("entity.wither_skeleton.death")); + + /** + * {@code minecraft:entity.wither_skeleton.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SKELETON_HURT = create(key("entity.wither_skeleton.hurt")); + + /** + * {@code minecraft:entity.wither_skeleton.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WITHER_SKELETON_STEP = create(key("entity.wither_skeleton.step")); + + /** + * {@code minecraft:entity.wolf.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_AMBIENT = create(key("entity.wolf.ambient")); + + /** + * {@code minecraft:entity.wolf.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_DEATH = create(key("entity.wolf.death")); + + /** + * {@code minecraft:entity.wolf.growl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_GROWL = create(key("entity.wolf.growl")); + + /** + * {@code minecraft:entity.wolf.howl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_HOWL = create(key("entity.wolf.howl")); + + /** + * {@code minecraft:entity.wolf.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_HURT = create(key("entity.wolf.hurt")); + + /** + * {@code minecraft:entity.wolf.pant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_PANT = create(key("entity.wolf.pant")); + + /** + * {@code minecraft:entity.wolf.shake} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_SHAKE = create(key("entity.wolf.shake")); + + /** + * {@code minecraft:entity.wolf.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_STEP = create(key("entity.wolf.step")); + + /** + * {@code minecraft:entity.wolf.whine} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_WOLF_WHINE = create(key("entity.wolf.whine")); + + /** + * {@code minecraft:entity.zoglin.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_AMBIENT = create(key("entity.zoglin.ambient")); + + /** + * {@code minecraft:entity.zoglin.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_ANGRY = create(key("entity.zoglin.angry")); + + /** + * {@code minecraft:entity.zoglin.attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_ATTACK = create(key("entity.zoglin.attack")); + + /** + * {@code minecraft:entity.zoglin.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_DEATH = create(key("entity.zoglin.death")); + + /** + * {@code minecraft:entity.zoglin.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_HURT = create(key("entity.zoglin.hurt")); + + /** + * {@code minecraft:entity.zoglin.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOGLIN_STEP = create(key("entity.zoglin.step")); + + /** + * {@code minecraft:entity.zombie.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_AMBIENT = create(key("entity.zombie.ambient")); + + /** + * {@code minecraft:entity.zombie.attack_iron_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_ATTACK_IRON_DOOR = create(key("entity.zombie.attack_iron_door")); + + /** + * {@code minecraft:entity.zombie.attack_wooden_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR = create(key("entity.zombie.attack_wooden_door")); + + /** + * {@code minecraft:entity.zombie.break_wooden_door} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_BREAK_WOODEN_DOOR = create(key("entity.zombie.break_wooden_door")); + + /** + * {@code minecraft:entity.zombie.converted_to_drowned} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_CONVERTED_TO_DROWNED = create(key("entity.zombie.converted_to_drowned")); + + /** + * {@code minecraft:entity.zombie.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_DEATH = create(key("entity.zombie.death")); + + /** + * {@code minecraft:entity.zombie.destroy_egg} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_DESTROY_EGG = create(key("entity.zombie.destroy_egg")); + + /** + * {@code minecraft:entity.zombie.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_HURT = create(key("entity.zombie.hurt")); + + /** + * {@code minecraft:entity.zombie.infect} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_INFECT = create(key("entity.zombie.infect")); + + /** + * {@code minecraft:entity.zombie.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_STEP = create(key("entity.zombie.step")); + + /** + * {@code minecraft:entity.zombie_horse.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_HORSE_AMBIENT = create(key("entity.zombie_horse.ambient")); + + /** + * {@code minecraft:entity.zombie_horse.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_HORSE_DEATH = create(key("entity.zombie_horse.death")); + + /** + * {@code minecraft:entity.zombie_horse.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_HORSE_HURT = create(key("entity.zombie_horse.hurt")); + + /** + * {@code minecraft:entity.zombie_villager.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_AMBIENT = create(key("entity.zombie_villager.ambient")); + + /** + * {@code minecraft:entity.zombie_villager.converted} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_CONVERTED = create(key("entity.zombie_villager.converted")); + + /** + * {@code minecraft:entity.zombie_villager.cure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_CURE = create(key("entity.zombie_villager.cure")); + + /** + * {@code minecraft:entity.zombie_villager.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_DEATH = create(key("entity.zombie_villager.death")); + + /** + * {@code minecraft:entity.zombie_villager.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_HURT = create(key("entity.zombie_villager.hurt")); + + /** + * {@code minecraft:entity.zombie_villager.step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIE_VILLAGER_STEP = create(key("entity.zombie_villager.step")); + + /** + * {@code minecraft:entity.zombified_piglin.ambient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIFIED_PIGLIN_AMBIENT = create(key("entity.zombified_piglin.ambient")); + + /** + * {@code minecraft:entity.zombified_piglin.angry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIFIED_PIGLIN_ANGRY = create(key("entity.zombified_piglin.angry")); + + /** + * {@code minecraft:entity.zombified_piglin.death} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIFIED_PIGLIN_DEATH = create(key("entity.zombified_piglin.death")); + + /** + * {@code minecraft:entity.zombified_piglin.hurt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ZOMBIFIED_PIGLIN_HURT = create(key("entity.zombified_piglin.hurt")); + + /** + * {@code minecraft:event.mob_effect.bad_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EVENT_MOB_EFFECT_BAD_OMEN = create(key("event.mob_effect.bad_omen")); + + /** + * {@code minecraft:event.mob_effect.raid_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EVENT_MOB_EFFECT_RAID_OMEN = create(key("event.mob_effect.raid_omen")); + + /** + * {@code minecraft:event.mob_effect.trial_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EVENT_MOB_EFFECT_TRIAL_OMEN = create(key("event.mob_effect.trial_omen")); + + /** + * {@code minecraft:event.raid.horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EVENT_RAID_HORN = create(key("event.raid.horn")); + + /** + * {@code minecraft:intentionally_empty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INTENTIONALLY_EMPTY = create(key("intentionally_empty")); + + /** + * {@code minecraft:item.armor.equip_chain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_CHAIN = create(key("item.armor.equip_chain")); + + /** + * {@code minecraft:item.armor.equip_diamond} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_DIAMOND = create(key("item.armor.equip_diamond")); + + /** + * {@code minecraft:item.armor.equip_elytra} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_ELYTRA = create(key("item.armor.equip_elytra")); + + /** + * {@code minecraft:item.armor.equip_generic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_GENERIC = create(key("item.armor.equip_generic")); + + /** + * {@code minecraft:item.armor.equip_gold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_GOLD = create(key("item.armor.equip_gold")); + + /** + * {@code minecraft:item.armor.equip_iron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_IRON = create(key("item.armor.equip_iron")); + + /** + * {@code minecraft:item.armor.equip_leather} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_LEATHER = create(key("item.armor.equip_leather")); + + /** + * {@code minecraft:item.armor.equip_netherite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_NETHERITE = create(key("item.armor.equip_netherite")); + + /** + * {@code minecraft:item.armor.equip_turtle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_TURTLE = create(key("item.armor.equip_turtle")); + + /** + * {@code minecraft:item.armor.equip_wolf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_EQUIP_WOLF = create(key("item.armor.equip_wolf")); + + /** + * {@code minecraft:item.armor.unequip_wolf} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ARMOR_UNEQUIP_WOLF = create(key("item.armor.unequip_wolf")); + + /** + * {@code minecraft:item.axe.scrape} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_AXE_SCRAPE = create(key("item.axe.scrape")); + + /** + * {@code minecraft:item.axe.strip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_AXE_STRIP = create(key("item.axe.strip")); + + /** + * {@code minecraft:item.axe.wax_off} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_AXE_WAX_OFF = create(key("item.axe.wax_off")); + + /** + * {@code minecraft:item.bone_meal.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BONE_MEAL_USE = create(key("item.bone_meal.use")); + + /** + * {@code minecraft:item.book.page_turn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BOOK_PAGE_TURN = create(key("item.book.page_turn")); + + /** + * {@code minecraft:item.book.put} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BOOK_PUT = create(key("item.book.put")); + + /** + * {@code minecraft:item.bottle.empty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BOTTLE_EMPTY = create(key("item.bottle.empty")); + + /** + * {@code minecraft:item.bottle.fill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BOTTLE_FILL = create(key("item.bottle.fill")); + + /** + * {@code minecraft:item.bottle.fill_dragonbreath} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BOTTLE_FILL_DRAGONBREATH = create(key("item.bottle.fill_dragonbreath")); + + /** + * {@code minecraft:item.brush.brushing.generic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BRUSH_BRUSHING_GENERIC = create(key("item.brush.brushing.generic")); + + /** + * {@code minecraft:item.brush.brushing.gravel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BRUSH_BRUSHING_GRAVEL = create(key("item.brush.brushing.gravel")); + + /** + * {@code minecraft:item.brush.brushing.gravel.complete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BRUSH_BRUSHING_GRAVEL_COMPLETE = create(key("item.brush.brushing.gravel.complete")); + + /** + * {@code minecraft:item.brush.brushing.sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BRUSH_BRUSHING_SAND = create(key("item.brush.brushing.sand")); + + /** + * {@code minecraft:item.brush.brushing.sand.complete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BRUSH_BRUSHING_SAND_COMPLETE = create(key("item.brush.brushing.sand.complete")); + + /** + * {@code minecraft:item.bucket.empty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY = create(key("item.bucket.empty")); + + /** + * {@code minecraft:item.bucket.empty_axolotl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY_AXOLOTL = create(key("item.bucket.empty_axolotl")); + + /** + * {@code minecraft:item.bucket.empty_fish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY_FISH = create(key("item.bucket.empty_fish")); + + /** + * {@code minecraft:item.bucket.empty_lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY_LAVA = create(key("item.bucket.empty_lava")); + + /** + * {@code minecraft:item.bucket.empty_powder_snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY_POWDER_SNOW = create(key("item.bucket.empty_powder_snow")); + + /** + * {@code minecraft:item.bucket.empty_tadpole} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_EMPTY_TADPOLE = create(key("item.bucket.empty_tadpole")); + + /** + * {@code minecraft:item.bucket.fill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL = create(key("item.bucket.fill")); + + /** + * {@code minecraft:item.bucket.fill_axolotl} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL_AXOLOTL = create(key("item.bucket.fill_axolotl")); + + /** + * {@code minecraft:item.bucket.fill_fish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL_FISH = create(key("item.bucket.fill_fish")); + + /** + * {@code minecraft:item.bucket.fill_lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL_LAVA = create(key("item.bucket.fill_lava")); + + /** + * {@code minecraft:item.bucket.fill_powder_snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL_POWDER_SNOW = create(key("item.bucket.fill_powder_snow")); + + /** + * {@code minecraft:item.bucket.fill_tadpole} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUCKET_FILL_TADPOLE = create(key("item.bucket.fill_tadpole")); + + /** + * {@code minecraft:item.bundle.drop_contents} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUNDLE_DROP_CONTENTS = create(key("item.bundle.drop_contents")); + + /** + * {@code minecraft:item.bundle.insert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUNDLE_INSERT = create(key("item.bundle.insert")); + + /** + * {@code minecraft:item.bundle.insert_fail} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUNDLE_INSERT_FAIL = create(key("item.bundle.insert_fail")); + + /** + * {@code minecraft:item.bundle.remove_one} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_BUNDLE_REMOVE_ONE = create(key("item.bundle.remove_one")); + + /** + * {@code minecraft:item.chorus_fruit.teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CHORUS_FRUIT_TELEPORT = create(key("item.chorus_fruit.teleport")); + + /** + * {@code minecraft:item.crop.plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROP_PLANT = create(key("item.crop.plant")); + + /** + * {@code minecraft:item.crossbow.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_HIT = create(key("item.crossbow.hit")); + + /** + * {@code minecraft:item.crossbow.loading_end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_LOADING_END = create(key("item.crossbow.loading_end")); + + /** + * {@code minecraft:item.crossbow.loading_middle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_LOADING_MIDDLE = create(key("item.crossbow.loading_middle")); + + /** + * {@code minecraft:item.crossbow.loading_start} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_LOADING_START = create(key("item.crossbow.loading_start")); + + /** + * {@code minecraft:item.crossbow.quick_charge_1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_QUICK_CHARGE_1 = create(key("item.crossbow.quick_charge_1")); + + /** + * {@code minecraft:item.crossbow.quick_charge_2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_QUICK_CHARGE_2 = create(key("item.crossbow.quick_charge_2")); + + /** + * {@code minecraft:item.crossbow.quick_charge_3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_QUICK_CHARGE_3 = create(key("item.crossbow.quick_charge_3")); + + /** + * {@code minecraft:item.crossbow.shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_CROSSBOW_SHOOT = create(key("item.crossbow.shoot")); + + /** + * {@code minecraft:item.dye.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_DYE_USE = create(key("item.dye.use")); + + /** + * {@code minecraft:item.elytra.flying} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_ELYTRA_FLYING = create(key("item.elytra.flying")); + + /** + * {@code minecraft:item.firecharge.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_FIRECHARGE_USE = create(key("item.firecharge.use")); + + /** + * {@code minecraft:item.flintandsteel.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_FLINTANDSTEEL_USE = create(key("item.flintandsteel.use")); + + /** + * {@code minecraft:item.glow_ink_sac.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GLOW_INK_SAC_USE = create(key("item.glow_ink_sac.use")); + + /** + * {@code minecraft:item.goat_horn.sound.0} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_0 = create(key("item.goat_horn.sound.0")); + + /** + * {@code minecraft:item.goat_horn.sound.1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_1 = create(key("item.goat_horn.sound.1")); + + /** + * {@code minecraft:item.goat_horn.sound.2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_2 = create(key("item.goat_horn.sound.2")); + + /** + * {@code minecraft:item.goat_horn.sound.3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_3 = create(key("item.goat_horn.sound.3")); + + /** + * {@code minecraft:item.goat_horn.sound.4} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_4 = create(key("item.goat_horn.sound.4")); + + /** + * {@code minecraft:item.goat_horn.sound.5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_5 = create(key("item.goat_horn.sound.5")); + + /** + * {@code minecraft:item.goat_horn.sound.6} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_6 = create(key("item.goat_horn.sound.6")); + + /** + * {@code minecraft:item.goat_horn.sound.7} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_GOAT_HORN_SOUND_7 = create(key("item.goat_horn.sound.7")); + + /** + * {@code minecraft:item.hoe.till} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_HOE_TILL = create(key("item.hoe.till")); + + /** + * {@code minecraft:item.honey_bottle.drink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_HONEY_BOTTLE_DRINK = create(key("item.honey_bottle.drink")); + + /** + * {@code minecraft:item.honeycomb.wax_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_HONEYCOMB_WAX_ON = create(key("item.honeycomb.wax_on")); + + /** + * {@code minecraft:item.ink_sac.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_INK_SAC_USE = create(key("item.ink_sac.use")); + + /** + * {@code minecraft:item.lodestone_compass.lock} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_LODESTONE_COMPASS_LOCK = create(key("item.lodestone_compass.lock")); + + /** + * {@code minecraft:item.mace.smash_air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_MACE_SMASH_AIR = create(key("item.mace.smash_air")); + + /** + * {@code minecraft:item.mace.smash_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_MACE_SMASH_GROUND = create(key("item.mace.smash_ground")); + + /** + * {@code minecraft:item.mace.smash_ground_heavy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_MACE_SMASH_GROUND_HEAVY = create(key("item.mace.smash_ground_heavy")); + + /** + * {@code minecraft:item.nether_wart.plant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_NETHER_WART_PLANT = create(key("item.nether_wart.plant")); + + /** + * {@code minecraft:item.ominous_bottle.dispose} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_OMINOUS_BOTTLE_DISPOSE = create(key("item.ominous_bottle.dispose")); + + /** + * {@code minecraft:item.shield.block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_SHIELD_BLOCK = create(key("item.shield.block")); + + /** + * {@code minecraft:item.shield.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_SHIELD_BREAK = create(key("item.shield.break")); + + /** + * {@code minecraft:item.shovel.flatten} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_SHOVEL_FLATTEN = create(key("item.shovel.flatten")); + + /** + * {@code minecraft:item.spyglass.stop_using} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_SPYGLASS_STOP_USING = create(key("item.spyglass.stop_using")); + + /** + * {@code minecraft:item.spyglass.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_SPYGLASS_USE = create(key("item.spyglass.use")); + + /** + * {@code minecraft:item.totem.use} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TOTEM_USE = create(key("item.totem.use")); + + /** + * {@code minecraft:item.trident.hit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_HIT = create(key("item.trident.hit")); + + /** + * {@code minecraft:item.trident.hit_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_HIT_GROUND = create(key("item.trident.hit_ground")); + + /** + * {@code minecraft:item.trident.return} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_RETURN = create(key("item.trident.return")); + + /** + * {@code minecraft:item.trident.riptide_1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_RIPTIDE_1 = create(key("item.trident.riptide_1")); + + /** + * {@code minecraft:item.trident.riptide_2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_RIPTIDE_2 = create(key("item.trident.riptide_2")); + + /** + * {@code minecraft:item.trident.riptide_3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_RIPTIDE_3 = create(key("item.trident.riptide_3")); + + /** + * {@code minecraft:item.trident.throw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_THROW = create(key("item.trident.throw")); + + /** + * {@code minecraft:item.trident.thunder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_TRIDENT_THUNDER = create(key("item.trident.thunder")); + + /** + * {@code minecraft:item.wolf_armor.break} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_WOLF_ARMOR_BREAK = create(key("item.wolf_armor.break")); + + /** + * {@code minecraft:item.wolf_armor.crack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_WOLF_ARMOR_CRACK = create(key("item.wolf_armor.crack")); + + /** + * {@code minecraft:item.wolf_armor.damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_WOLF_ARMOR_DAMAGE = create(key("item.wolf_armor.damage")); + + /** + * {@code minecraft:item.wolf_armor.repair} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_WOLF_ARMOR_REPAIR = create(key("item.wolf_armor.repair")); + + /** + * {@code minecraft:music.creative} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_CREATIVE = create(key("music.creative")); + + /** + * {@code minecraft:music.credits} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_CREDITS = create(key("music.credits")); + + /** + * {@code minecraft:music.dragon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DRAGON = create(key("music.dragon")); + + /** + * {@code minecraft:music.end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_END = create(key("music.end")); + + /** + * {@code minecraft:music.game} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_GAME = create(key("music.game")); + + /** + * {@code minecraft:music.menu} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_MENU = create(key("music.menu")); + + /** + * {@code minecraft:music.nether.basalt_deltas} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_NETHER_BASALT_DELTAS = create(key("music.nether.basalt_deltas")); + + /** + * {@code minecraft:music.nether.crimson_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_NETHER_CRIMSON_FOREST = create(key("music.nether.crimson_forest")); + + /** + * {@code minecraft:music.nether.nether_wastes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_NETHER_NETHER_WASTES = create(key("music.nether.nether_wastes")); + + /** + * {@code minecraft:music.nether.soul_sand_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_NETHER_SOUL_SAND_VALLEY = create(key("music.nether.soul_sand_valley")); + + /** + * {@code minecraft:music.nether.warped_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_NETHER_WARPED_FOREST = create(key("music.nether.warped_forest")); + + /** + * {@code minecraft:music.overworld.badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_BADLANDS = create(key("music.overworld.badlands")); + + /** + * {@code minecraft:music.overworld.bamboo_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_BAMBOO_JUNGLE = create(key("music.overworld.bamboo_jungle")); + + /** + * {@code minecraft:music.overworld.cherry_grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_CHERRY_GROVE = create(key("music.overworld.cherry_grove")); + + /** + * {@code minecraft:music.overworld.deep_dark} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_DEEP_DARK = create(key("music.overworld.deep_dark")); + + /** + * {@code minecraft:music.overworld.desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_DESERT = create(key("music.overworld.desert")); + + /** + * {@code minecraft:music.overworld.dripstone_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_DRIPSTONE_CAVES = create(key("music.overworld.dripstone_caves")); + + /** + * {@code minecraft:music.overworld.flower_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_FLOWER_FOREST = create(key("music.overworld.flower_forest")); + + /** + * {@code minecraft:music.overworld.forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_FOREST = create(key("music.overworld.forest")); + + /** + * {@code minecraft:music.overworld.frozen_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_FROZEN_PEAKS = create(key("music.overworld.frozen_peaks")); + + /** + * {@code minecraft:music.overworld.grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_GROVE = create(key("music.overworld.grove")); + + /** + * {@code minecraft:music.overworld.jagged_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_JAGGED_PEAKS = create(key("music.overworld.jagged_peaks")); + + /** + * {@code minecraft:music.overworld.jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_JUNGLE = create(key("music.overworld.jungle")); + + /** + * {@code minecraft:music.overworld.lush_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_LUSH_CAVES = create(key("music.overworld.lush_caves")); + + /** + * {@code minecraft:music.overworld.meadow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_MEADOW = create(key("music.overworld.meadow")); + + /** + * {@code minecraft:music.overworld.old_growth_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_OLD_GROWTH_TAIGA = create(key("music.overworld.old_growth_taiga")); + + /** + * {@code minecraft:music.overworld.snowy_slopes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_SNOWY_SLOPES = create(key("music.overworld.snowy_slopes")); + + /** + * {@code minecraft:music.overworld.sparse_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_SPARSE_JUNGLE = create(key("music.overworld.sparse_jungle")); + + /** + * {@code minecraft:music.overworld.stony_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_STONY_PEAKS = create(key("music.overworld.stony_peaks")); + + /** + * {@code minecraft:music.overworld.swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_OVERWORLD_SWAMP = create(key("music.overworld.swamp")); + + /** + * {@code minecraft:music.under_water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_UNDER_WATER = create(key("music.under_water")); + + /** + * {@code minecraft:music_disc.11} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_11 = create(key("music_disc.11")); + + /** + * {@code minecraft:music_disc.13} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_13 = create(key("music_disc.13")); + + /** + * {@code minecraft:music_disc.5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_5 = create(key("music_disc.5")); + + /** + * {@code minecraft:music_disc.blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_BLOCKS = create(key("music_disc.blocks")); + + /** + * {@code minecraft:music_disc.cat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CAT = create(key("music_disc.cat")); + + /** + * {@code minecraft:music_disc.chirp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CHIRP = create(key("music_disc.chirp")); + + /** + * {@code minecraft:music_disc.creator} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CREATOR = create(key("music_disc.creator")); + + /** + * {@code minecraft:music_disc.creator_music_box} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_CREATOR_MUSIC_BOX = create(key("music_disc.creator_music_box")); + + /** + * {@code minecraft:music_disc.far} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_FAR = create(key("music_disc.far")); + + /** + * {@code minecraft:music_disc.mall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_MALL = create(key("music_disc.mall")); + + /** + * {@code minecraft:music_disc.mellohi} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_MELLOHI = create(key("music_disc.mellohi")); + + /** + * {@code minecraft:music_disc.otherside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_OTHERSIDE = create(key("music_disc.otherside")); + + /** + * {@code minecraft:music_disc.pigstep} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_PIGSTEP = create(key("music_disc.pigstep")); + + /** + * {@code minecraft:music_disc.precipice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_PRECIPICE = create(key("music_disc.precipice")); + + /** + * {@code minecraft:music_disc.relic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_RELIC = create(key("music_disc.relic")); + + /** + * {@code minecraft:music_disc.stal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_STAL = create(key("music_disc.stal")); + + /** + * {@code minecraft:music_disc.strad} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_STRAD = create(key("music_disc.strad")); + + /** + * {@code minecraft:music_disc.wait} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_WAIT = create(key("music_disc.wait")); + + /** + * {@code minecraft:music_disc.ward} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSIC_DISC_WARD = create(key("music_disc.ward")); + + /** + * {@code minecraft:particle.soul_escape} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PARTICLE_SOUL_ESCAPE = create(key("particle.soul_escape")); + + /** + * {@code minecraft:ui.button.click} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_BUTTON_CLICK = create(key("ui.button.click")); + + /** + * {@code minecraft:ui.cartography_table.take_result} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_CARTOGRAPHY_TABLE_TAKE_RESULT = create(key("ui.cartography_table.take_result")); + + /** + * {@code minecraft:ui.hud.bubble_pop} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_HUD_BUBBLE_POP = create(key("ui.hud.bubble_pop")); + + /** + * {@code minecraft:ui.loom.select_pattern} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_LOOM_SELECT_PATTERN = create(key("ui.loom.select_pattern")); + + /** + * {@code minecraft:ui.loom.take_result} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_LOOM_TAKE_RESULT = create(key("ui.loom.take_result")); + + /** + * {@code minecraft:ui.stonecutter.select_recipe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_STONECUTTER_SELECT_RECIPE = create(key("ui.stonecutter.select_recipe")); + + /** + * {@code minecraft:ui.stonecutter.take_result} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_STONECUTTER_TAKE_RESULT = create(key("ui.stonecutter.take_result")); + + /** + * {@code minecraft:ui.toast.challenge_complete} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_TOAST_CHALLENGE_COMPLETE = create(key("ui.toast.challenge_complete")); + + /** + * {@code minecraft:ui.toast.in} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_TOAST_IN = create(key("ui.toast.in")); + + /** + * {@code minecraft:ui.toast.out} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UI_TOAST_OUT = create(key("ui.toast.out")); + + /** + * {@code minecraft:weather.rain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHER_RAIN = create(key("weather.rain")); + + /** + * {@code minecraft:weather.rain.above} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEATHER_RAIN_ABOVE = create(key("weather.rain.above")); + + private SoundEventKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.SOUND_EVENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureKeys.java new file mode 100644 index 000000000000..4a390ebc9994 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureKeys.java @@ -0,0 +1,281 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.generator.structure.Structure; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#STRUCTURE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class StructureKeys { + /** + * {@code minecraft:ancient_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ANCIENT_CITY = create(key("ancient_city")); + + /** + * {@code minecraft:bastion_remnant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASTION_REMNANT = create(key("bastion_remnant")); + + /** + * {@code minecraft:buried_treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURIED_TREASURE = create(key("buried_treasure")); + + /** + * {@code minecraft:desert_pyramid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT_PYRAMID = create(key("desert_pyramid")); + + /** + * {@code minecraft:end_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_CITY = create(key("end_city")); + + /** + * {@code minecraft:fortress} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FORTRESS = create(key("fortress")); + + /** + * {@code minecraft:igloo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IGLOO = create(key("igloo")); + + /** + * {@code minecraft:jungle_pyramid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_PYRAMID = create(key("jungle_pyramid")); + + /** + * {@code minecraft:mansion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANSION = create(key("mansion")); + + /** + * {@code minecraft:mineshaft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINESHAFT = create(key("mineshaft")); + + /** + * {@code minecraft:mineshaft_mesa} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINESHAFT_MESA = create(key("mineshaft_mesa")); + + /** + * {@code minecraft:monument} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MONUMENT = create(key("monument")); + + /** + * {@code minecraft:nether_fossil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_FOSSIL = create(key("nether_fossil")); + + /** + * {@code minecraft:ocean_ruin_cold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_RUIN_COLD = create(key("ocean_ruin_cold")); + + /** + * {@code minecraft:ocean_ruin_warm} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_RUIN_WARM = create(key("ocean_ruin_warm")); + + /** + * {@code minecraft:pillager_outpost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PILLAGER_OUTPOST = create(key("pillager_outpost")); + + /** + * {@code minecraft:ruined_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL = create(key("ruined_portal")); + + /** + * {@code minecraft:ruined_portal_desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_DESERT = create(key("ruined_portal_desert")); + + /** + * {@code minecraft:ruined_portal_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_JUNGLE = create(key("ruined_portal_jungle")); + + /** + * {@code minecraft:ruined_portal_mountain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_MOUNTAIN = create(key("ruined_portal_mountain")); + + /** + * {@code minecraft:ruined_portal_nether} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_NETHER = create(key("ruined_portal_nether")); + + /** + * {@code minecraft:ruined_portal_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_OCEAN = create(key("ruined_portal_ocean")); + + /** + * {@code minecraft:ruined_portal_swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL_SWAMP = create(key("ruined_portal_swamp")); + + /** + * {@code minecraft:shipwreck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHIPWRECK = create(key("shipwreck")); + + /** + * {@code minecraft:shipwreck_beached} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHIPWRECK_BEACHED = create(key("shipwreck_beached")); + + /** + * {@code minecraft:stronghold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRONGHOLD = create(key("stronghold")); + + /** + * {@code minecraft:swamp_hut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP_HUT = create(key("swamp_hut")); + + /** + * {@code minecraft:trail_ruins} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRAIL_RUINS = create(key("trail_ruins")); + + /** + * {@code minecraft:trial_chambers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIAL_CHAMBERS = create(key("trial_chambers")); + + /** + * {@code minecraft:village_desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_DESERT = create(key("village_desert")); + + /** + * {@code minecraft:village_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_PLAINS = create(key("village_plains")); + + /** + * {@code minecraft:village_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_SAVANNA = create(key("village_savanna")); + + /** + * {@code minecraft:village_snowy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_SNOWY = create(key("village_snowy")); + + /** + * {@code minecraft:village_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VILLAGE_TAIGA = create(key("village_taiga")); + + private StructureKeys() { + } + + /** + * Creates a key for {@link Structure} in the registry {@code minecraft:worldgen/structure}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.STRUCTURE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java new file mode 100644 index 000000000000..469f355dbd8f --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java @@ -0,0 +1,148 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.generator.structure.StructureType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#STRUCTURE_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class StructureTypeKeys { + /** + * {@code minecraft:buried_treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURIED_TREASURE = create(key("buried_treasure")); + + /** + * {@code minecraft:desert_pyramid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT_PYRAMID = create(key("desert_pyramid")); + + /** + * {@code minecraft:end_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_CITY = create(key("end_city")); + + /** + * {@code minecraft:fortress} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FORTRESS = create(key("fortress")); + + /** + * {@code minecraft:igloo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IGLOO = create(key("igloo")); + + /** + * {@code minecraft:jigsaw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JIGSAW = create(key("jigsaw")); + + /** + * {@code minecraft:jungle_temple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_TEMPLE = create(key("jungle_temple")); + + /** + * {@code minecraft:mineshaft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINESHAFT = create(key("mineshaft")); + + /** + * {@code minecraft:nether_fossil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_FOSSIL = create(key("nether_fossil")); + + /** + * {@code minecraft:ocean_monument} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_MONUMENT = create(key("ocean_monument")); + + /** + * {@code minecraft:ocean_ruin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_RUIN = create(key("ocean_ruin")); + + /** + * {@code minecraft:ruined_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL = create(key("ruined_portal")); + + /** + * {@code minecraft:shipwreck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHIPWRECK = create(key("shipwreck")); + + /** + * {@code minecraft:stronghold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRONGHOLD = create(key("stronghold")); + + /** + * {@code minecraft:swamp_hut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP_HUT = create(key("swamp_hut")); + + /** + * {@code minecraft:woodland_mansion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODLAND_MANSION = create(key("woodland_mansion")); + + private StructureTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.STRUCTURE_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java new file mode 100644 index 000000000000..226f1dcadafe --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java @@ -0,0 +1,120 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#TRIM_MATERIAL}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class TrimMaterialKeys { + /** + * {@code minecraft:amethyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST = create(key("amethyst")); + + /** + * {@code minecraft:copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER = create(key("copper")); + + /** + * {@code minecraft:diamond} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND = create(key("diamond")); + + /** + * {@code minecraft:emerald} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD = create(key("emerald")); + + /** + * {@code minecraft:gold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD = create(key("gold")); + + /** + * {@code minecraft:iron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON = create(key("iron")); + + /** + * {@code minecraft:lapis} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS = create(key("lapis")); + + /** + * {@code minecraft:netherite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE = create(key("netherite")); + + /** + * {@code minecraft:quartz} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ = create(key("quartz")); + + /** + * {@code minecraft:redstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE = create(key("redstone")); + + /** + * {@code minecraft:resin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESIN = create(key("resin")); + + private TrimMaterialKeys() { + } + + /** + * Creates a key for {@link TrimMaterial} in the registry {@code minecraft:trim_material}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.TRIM_MATERIAL, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java new file mode 100644 index 000000000000..67ce5f1b3819 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java @@ -0,0 +1,169 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#TRIM_PATTERN}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class TrimPatternKeys { + /** + * {@code minecraft:bolt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BOLT = create(key("bolt")); + + /** + * {@code minecraft:coast} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAST = create(key("coast")); + + /** + * {@code minecraft:dune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DUNE = create(key("dune")); + + /** + * {@code minecraft:eye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EYE = create(key("eye")); + + /** + * {@code minecraft:flow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOW = create(key("flow")); + + /** + * {@code minecraft:host} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOST = create(key("host")); + + /** + * {@code minecraft:raiser} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAISER = create(key("raiser")); + + /** + * {@code minecraft:rib} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIB = create(key("rib")); + + /** + * {@code minecraft:sentry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SENTRY = create(key("sentry")); + + /** + * {@code minecraft:shaper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHAPER = create(key("shaper")); + + /** + * {@code minecraft:silence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILENCE = create(key("silence")); + + /** + * {@code minecraft:snout} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOUT = create(key("snout")); + + /** + * {@code minecraft:spire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIRE = create(key("spire")); + + /** + * {@code minecraft:tide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TIDE = create(key("tide")); + + /** + * {@code minecraft:vex} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VEX = create(key("vex")); + + /** + * {@code minecraft:ward} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARD = create(key("ward")); + + /** + * {@code minecraft:wayfinder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAYFINDER = create(key("wayfinder")); + + /** + * {@code minecraft:wild} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WILD = create(key("wild")); + + private TrimPatternKeys() { + } + + /** + * Creates a key for {@link TrimPattern} in the registry {@code minecraft:trim_pattern}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.TRIM_PATTERN, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerProfessionKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerProfessionKeys.java new file mode 100644 index 000000000000..30adcd29edb6 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerProfessionKeys.java @@ -0,0 +1,141 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Villager; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#VILLAGER_PROFESSION}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class VillagerProfessionKeys { + /** + * {@code minecraft:armorer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARMORER = create(key("armorer")); + + /** + * {@code minecraft:butcher} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BUTCHER = create(key("butcher")); + + /** + * {@code minecraft:cartographer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CARTOGRAPHER = create(key("cartographer")); + + /** + * {@code minecraft:cleric} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CLERIC = create(key("cleric")); + + /** + * {@code minecraft:farmer} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FARMER = create(key("farmer")); + + /** + * {@code minecraft:fisherman} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FISHERMAN = create(key("fisherman")); + + /** + * {@code minecraft:fletcher} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLETCHER = create(key("fletcher")); + + /** + * {@code minecraft:leatherworker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEATHERWORKER = create(key("leatherworker")); + + /** + * {@code minecraft:librarian} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIBRARIAN = create(key("librarian")); + + /** + * {@code minecraft:mason} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MASON = create(key("mason")); + + /** + * {@code minecraft:nitwit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NITWIT = create(key("nitwit")); + + /** + * {@code minecraft:none} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NONE = create(key("none")); + + /** + * {@code minecraft:shepherd} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEPHERD = create(key("shepherd")); + + /** + * {@code minecraft:toolsmith} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TOOLSMITH = create(key("toolsmith")); + + /** + * {@code minecraft:weaponsmith} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEAPONSMITH = create(key("weaponsmith")); + + private VillagerProfessionKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.VILLAGER_PROFESSION, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerTypeKeys.java new file mode 100644 index 000000000000..3905a992764e --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/VillagerTypeKeys.java @@ -0,0 +1,85 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Villager; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#VILLAGER_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class VillagerTypeKeys { + /** + * {@code minecraft:desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT = create(key("desert")); + + /** + * {@code minecraft:jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE = create(key("jungle")); + + /** + * {@code minecraft:plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAINS = create(key("plains")); + + /** + * {@code minecraft:savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAVANNA = create(key("savanna")); + + /** + * {@code minecraft:snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOW = create(key("snow")); + + /** + * {@code minecraft:swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP = create(key("swamp")); + + /** + * {@code minecraft:taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TAIGA = create(key("taiga")); + + private VillagerTypeKeys() { + } + + private static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.VILLAGER_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java new file mode 100644 index 000000000000..6d59b9bf93e5 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java @@ -0,0 +1,106 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Wolf; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#WOLF_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class WolfVariantKeys { + /** + * {@code minecraft:ashen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ASHEN = create(key("ashen")); + + /** + * {@code minecraft:black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK = create(key("black")); + + /** + * {@code minecraft:chestnut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHESTNUT = create(key("chestnut")); + + /** + * {@code minecraft:pale} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE = create(key("pale")); + + /** + * {@code minecraft:rusty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUSTY = create(key("rusty")); + + /** + * {@code minecraft:snowy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY = create(key("snowy")); + + /** + * {@code minecraft:spotted} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPOTTED = create(key("spotted")); + + /** + * {@code minecraft:striped} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPED = create(key("striped")); + + /** + * {@code minecraft:woods} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODS = create(key("woods")); + + private WolfVariantKeys() { + } + + /** + * Creates a key for {@link Wolf.Variant} in the registry {@code minecraft:wolf_variant}. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static TypedKey create(final Key key) { + return TypedKey.create(RegistryKey.WOLF_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BannerPatternTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BannerPatternTagKeys.java new file mode 100644 index 000000000000..5e1c93327ddf --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BannerPatternTagKeys.java @@ -0,0 +1,120 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.banner.PatternType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BANNER_PATTERN}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BannerPatternTagKeys { + /** + * {@code #minecraft:no_item_required} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NO_ITEM_REQUIRED = create(key("no_item_required")); + + /** + * {@code #minecraft:pattern_item/bordure_indented} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_BORDURE_INDENTED = create(key("pattern_item/bordure_indented")); + + /** + * {@code #minecraft:pattern_item/creeper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_CREEPER = create(key("pattern_item/creeper")); + + /** + * {@code #minecraft:pattern_item/field_masoned} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_FIELD_MASONED = create(key("pattern_item/field_masoned")); + + /** + * {@code #minecraft:pattern_item/flow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_FLOW = create(key("pattern_item/flow")); + + /** + * {@code #minecraft:pattern_item/flower} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_FLOWER = create(key("pattern_item/flower")); + + /** + * {@code #minecraft:pattern_item/globe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_GLOBE = create(key("pattern_item/globe")); + + /** + * {@code #minecraft:pattern_item/guster} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_GUSTER = create(key("pattern_item/guster")); + + /** + * {@code #minecraft:pattern_item/mojang} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_MOJANG = create(key("pattern_item/mojang")); + + /** + * {@code #minecraft:pattern_item/piglin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_PIGLIN = create(key("pattern_item/piglin")); + + /** + * {@code #minecraft:pattern_item/skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PATTERN_ITEM_SKULL = create(key("pattern_item/skull")); + + private BannerPatternTagKeys() { + } + + /** + * Creates a tag key for {@link PatternType} in the registry {@code minecraft:banner_pattern}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.BANNER_PATTERN, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BiomeTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BiomeTagKeys.java new file mode 100644 index 000000000000..acc82a5dfb65 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BiomeTagKeys.java @@ -0,0 +1,533 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.Biome; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BIOME}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BiomeTagKeys { + /** + * {@code #minecraft:allows_surface_slime_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALLOWS_SURFACE_SLIME_SPAWNS = create(key("allows_surface_slime_spawns")); + + /** + * {@code #minecraft:allows_tropical_fish_spawns_at_any_height} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALLOWS_TROPICAL_FISH_SPAWNS_AT_ANY_HEIGHT = create(key("allows_tropical_fish_spawns_at_any_height")); + + /** + * {@code #minecraft:has_closer_water_fog} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_CLOSER_WATER_FOG = create(key("has_closer_water_fog")); + + /** + * {@code #minecraft:has_structure/ancient_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_ANCIENT_CITY = create(key("has_structure/ancient_city")); + + /** + * {@code #minecraft:has_structure/bastion_remnant} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_BASTION_REMNANT = create(key("has_structure/bastion_remnant")); + + /** + * {@code #minecraft:has_structure/buried_treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_BURIED_TREASURE = create(key("has_structure/buried_treasure")); + + /** + * {@code #minecraft:has_structure/desert_pyramid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_DESERT_PYRAMID = create(key("has_structure/desert_pyramid")); + + /** + * {@code #minecraft:has_structure/end_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_END_CITY = create(key("has_structure/end_city")); + + /** + * {@code #minecraft:has_structure/igloo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_IGLOO = create(key("has_structure/igloo")); + + /** + * {@code #minecraft:has_structure/jungle_temple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_JUNGLE_TEMPLE = create(key("has_structure/jungle_temple")); + + /** + * {@code #minecraft:has_structure/mineshaft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_MINESHAFT = create(key("has_structure/mineshaft")); + + /** + * {@code #minecraft:has_structure/mineshaft_mesa} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_MINESHAFT_MESA = create(key("has_structure/mineshaft_mesa")); + + /** + * {@code #minecraft:has_structure/nether_fortress} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_NETHER_FORTRESS = create(key("has_structure/nether_fortress")); + + /** + * {@code #minecraft:has_structure/nether_fossil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_NETHER_FOSSIL = create(key("has_structure/nether_fossil")); + + /** + * {@code #minecraft:has_structure/ocean_monument} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_OCEAN_MONUMENT = create(key("has_structure/ocean_monument")); + + /** + * {@code #minecraft:has_structure/ocean_ruin_cold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_OCEAN_RUIN_COLD = create(key("has_structure/ocean_ruin_cold")); + + /** + * {@code #minecraft:has_structure/ocean_ruin_warm} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_OCEAN_RUIN_WARM = create(key("has_structure/ocean_ruin_warm")); + + /** + * {@code #minecraft:has_structure/pillager_outpost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_PILLAGER_OUTPOST = create(key("has_structure/pillager_outpost")); + + /** + * {@code #minecraft:has_structure/ruined_portal_desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_DESERT = create(key("has_structure/ruined_portal_desert")); + + /** + * {@code #minecraft:has_structure/ruined_portal_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_JUNGLE = create(key("has_structure/ruined_portal_jungle")); + + /** + * {@code #minecraft:has_structure/ruined_portal_mountain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_MOUNTAIN = create(key("has_structure/ruined_portal_mountain")); + + /** + * {@code #minecraft:has_structure/ruined_portal_nether} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_NETHER = create(key("has_structure/ruined_portal_nether")); + + /** + * {@code #minecraft:has_structure/ruined_portal_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_OCEAN = create(key("has_structure/ruined_portal_ocean")); + + /** + * {@code #minecraft:has_structure/ruined_portal_standard} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_STANDARD = create(key("has_structure/ruined_portal_standard")); + + /** + * {@code #minecraft:has_structure/ruined_portal_swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_RUINED_PORTAL_SWAMP = create(key("has_structure/ruined_portal_swamp")); + + /** + * {@code #minecraft:has_structure/shipwreck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_SHIPWRECK = create(key("has_structure/shipwreck")); + + /** + * {@code #minecraft:has_structure/shipwreck_beached} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_SHIPWRECK_BEACHED = create(key("has_structure/shipwreck_beached")); + + /** + * {@code #minecraft:has_structure/stronghold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_STRONGHOLD = create(key("has_structure/stronghold")); + + /** + * {@code #minecraft:has_structure/swamp_hut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_SWAMP_HUT = create(key("has_structure/swamp_hut")); + + /** + * {@code #minecraft:has_structure/trail_ruins} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_TRAIL_RUINS = create(key("has_structure/trail_ruins")); + + /** + * {@code #minecraft:has_structure/trial_chambers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_TRIAL_CHAMBERS = create(key("has_structure/trial_chambers")); + + /** + * {@code #minecraft:has_structure/village_desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_VILLAGE_DESERT = create(key("has_structure/village_desert")); + + /** + * {@code #minecraft:has_structure/village_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_VILLAGE_PLAINS = create(key("has_structure/village_plains")); + + /** + * {@code #minecraft:has_structure/village_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_VILLAGE_SAVANNA = create(key("has_structure/village_savanna")); + + /** + * {@code #minecraft:has_structure/village_snowy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_VILLAGE_SNOWY = create(key("has_structure/village_snowy")); + + /** + * {@code #minecraft:has_structure/village_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_VILLAGE_TAIGA = create(key("has_structure/village_taiga")); + + /** + * {@code #minecraft:has_structure/woodland_mansion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HAS_STRUCTURE_WOODLAND_MANSION = create(key("has_structure/woodland_mansion")); + + /** + * {@code #minecraft:increased_fire_burnout} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCREASED_FIRE_BURNOUT = create(key("increased_fire_burnout")); + + /** + * {@code #minecraft:is_badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_BADLANDS = create(key("is_badlands")); + + /** + * {@code #minecraft:is_beach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_BEACH = create(key("is_beach")); + + /** + * {@code #minecraft:is_deep_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_DEEP_OCEAN = create(key("is_deep_ocean")); + + /** + * {@code #minecraft:is_end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_END = create(key("is_end")); + + /** + * {@code #minecraft:is_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_FOREST = create(key("is_forest")); + + /** + * {@code #minecraft:is_hill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_HILL = create(key("is_hill")); + + /** + * {@code #minecraft:is_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_JUNGLE = create(key("is_jungle")); + + /** + * {@code #minecraft:is_mountain} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_MOUNTAIN = create(key("is_mountain")); + + /** + * {@code #minecraft:is_nether} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_NETHER = create(key("is_nether")); + + /** + * {@code #minecraft:is_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_OCEAN = create(key("is_ocean")); + + /** + * {@code #minecraft:is_overworld} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_OVERWORLD = create(key("is_overworld")); + + /** + * {@code #minecraft:is_river} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_RIVER = create(key("is_river")); + + /** + * {@code #minecraft:is_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_SAVANNA = create(key("is_savanna")); + + /** + * {@code #minecraft:is_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_TAIGA = create(key("is_taiga")); + + /** + * {@code #minecraft:mineshaft_blocking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINESHAFT_BLOCKING = create(key("mineshaft_blocking")); + + /** + * {@code #minecraft:more_frequent_drowned_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MORE_FREQUENT_DROWNED_SPAWNS = create(key("more_frequent_drowned_spawns")); + + /** + * {@code #minecraft:plays_underwater_music} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PLAYS_UNDERWATER_MUSIC = create(key("plays_underwater_music")); + + /** + * {@code #minecraft:polar_bears_spawn_on_alternate_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey POLAR_BEARS_SPAWN_ON_ALTERNATE_BLOCKS = create(key("polar_bears_spawn_on_alternate_blocks")); + + /** + * {@code #minecraft:produces_corals_from_bonemeal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PRODUCES_CORALS_FROM_BONEMEAL = create(key("produces_corals_from_bonemeal")); + + /** + * {@code #minecraft:reduce_water_ambient_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REDUCE_WATER_AMBIENT_SPAWNS = create(key("reduce_water_ambient_spawns")); + + /** + * {@code #minecraft:required_ocean_monument_surrounding} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REQUIRED_OCEAN_MONUMENT_SURROUNDING = create(key("required_ocean_monument_surrounding")); + + /** + * {@code #minecraft:snow_golem_melts} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNOW_GOLEM_MELTS = create(key("snow_golem_melts")); + + /** + * {@code #minecraft:spawns_cold_variant_frogs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPAWNS_COLD_VARIANT_FROGS = create(key("spawns_cold_variant_frogs")); + + /** + * {@code #minecraft:spawns_gold_rabbits} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPAWNS_GOLD_RABBITS = create(key("spawns_gold_rabbits")); + + /** + * {@code #minecraft:spawns_snow_foxes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPAWNS_SNOW_FOXES = create(key("spawns_snow_foxes")); + + /** + * {@code #minecraft:spawns_warm_variant_frogs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPAWNS_WARM_VARIANT_FROGS = create(key("spawns_warm_variant_frogs")); + + /** + * {@code #minecraft:spawns_white_rabbits} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPAWNS_WHITE_RABBITS = create(key("spawns_white_rabbits")); + + /** + * {@code #minecraft:stronghold_biased_to} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STRONGHOLD_BIASED_TO = create(key("stronghold_biased_to")); + + /** + * {@code #minecraft:water_on_map_outlines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WATER_ON_MAP_OUTLINES = create(key("water_on_map_outlines")); + + /** + * {@code #minecraft:without_patrol_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHOUT_PATROL_SPAWNS = create(key("without_patrol_spawns")); + + /** + * {@code #minecraft:without_wandering_trader_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHOUT_WANDERING_TRADER_SPAWNS = create(key("without_wandering_trader_spawns")); + + /** + * {@code #minecraft:without_zombie_sieges} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHOUT_ZOMBIE_SIEGES = create(key("without_zombie_sieges")); + + private BiomeTagKeys() { + } + + /** + * Creates a tag key for {@link Biome} in the registry {@code minecraft:worldgen/biome}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.BIOME, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BlockTypeTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BlockTypeTagKeys.java new file mode 100644 index 000000000000..af2a45f63a63 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/BlockTypeTagKeys.java @@ -0,0 +1,1345 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.BlockType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#BLOCK}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class BlockTypeTagKeys { + /** + * {@code #minecraft:acacia_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ACACIA_LOGS = create(key("acacia_logs")); + + /** + * {@code #minecraft:air} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AIR = create(key("air")); + + /** + * {@code #minecraft:all_hanging_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALL_HANGING_SIGNS = create(key("all_hanging_signs")); + + /** + * {@code #minecraft:all_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALL_SIGNS = create(key("all_signs")); + + /** + * {@code #minecraft:ancient_city_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ANCIENT_CITY_REPLACEABLE = create(key("ancient_city_replaceable")); + + /** + * {@code #minecraft:animals_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ANIMALS_SPAWNABLE_ON = create(key("animals_spawnable_on")); + + /** + * {@code #minecraft:anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ANVIL = create(key("anvil")); + + /** + * {@code #minecraft:armadillo_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ARMADILLO_SPAWNABLE_ON = create(key("armadillo_spawnable_on")); + + /** + * {@code #minecraft:axolotls_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AXOLOTLS_SPAWNABLE_ON = create(key("axolotls_spawnable_on")); + + /** + * {@code #minecraft:azalea_grows_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AZALEA_GROWS_ON = create(key("azalea_grows_on")); + + /** + * {@code #minecraft:azalea_root_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AZALEA_ROOT_REPLACEABLE = create(key("azalea_root_replaceable")); + + /** + * {@code #minecraft:badlands_terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BADLANDS_TERRACOTTA = create(key("badlands_terracotta")); + + /** + * {@code #minecraft:bamboo_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BAMBOO_BLOCKS = create(key("bamboo_blocks")); + + /** + * {@code #minecraft:bamboo_plantable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BAMBOO_PLANTABLE_ON = create(key("bamboo_plantable_on")); + + /** + * {@code #minecraft:banners} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BANNERS = create(key("banners")); + + /** + * {@code #minecraft:base_stone_nether} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BASE_STONE_NETHER = create(key("base_stone_nether")); + + /** + * {@code #minecraft:base_stone_overworld} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BASE_STONE_OVERWORLD = create(key("base_stone_overworld")); + + /** + * {@code #minecraft:bats_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BATS_SPAWNABLE_ON = create(key("bats_spawnable_on")); + + /** + * {@code #minecraft:beacon_base_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEACON_BASE_BLOCKS = create(key("beacon_base_blocks")); + + /** + * {@code #minecraft:beds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEDS = create(key("beds")); + + /** + * {@code #minecraft:bee_attractive} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEE_ATTRACTIVE = create(key("bee_attractive")); + + /** + * {@code #minecraft:bee_growables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEE_GROWABLES = create(key("bee_growables")); + + /** + * {@code #minecraft:beehives} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEEHIVES = create(key("beehives")); + + /** + * {@code #minecraft:big_dripleaf_placeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BIG_DRIPLEAF_PLACEABLE = create(key("big_dripleaf_placeable")); + + /** + * {@code #minecraft:birch_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BIRCH_LOGS = create(key("birch_logs")); + + /** + * {@code #minecraft:blocks_wind_charge_explosions} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BLOCKS_WIND_CHARGE_EXPLOSIONS = create(key("blocks_wind_charge_explosions")); + + /** + * {@code #minecraft:buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BUTTONS = create(key("buttons")); + + /** + * {@code #minecraft:camel_sand_step_sound_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAMEL_SAND_STEP_SOUND_BLOCKS = create(key("camel_sand_step_sound_blocks")); + + /** + * {@code #minecraft:campfires} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAMPFIRES = create(key("campfires")); + + /** + * {@code #minecraft:candle_cakes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CANDLE_CAKES = create(key("candle_cakes")); + + /** + * {@code #minecraft:candles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CANDLES = create(key("candles")); + + /** + * {@code #minecraft:cauldrons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAULDRONS = create(key("cauldrons")); + + /** + * {@code #minecraft:cave_vines} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAVE_VINES = create(key("cave_vines")); + + /** + * {@code #minecraft:ceiling_hanging_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CEILING_HANGING_SIGNS = create(key("ceiling_hanging_signs")); + + /** + * {@code #minecraft:cherry_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CHERRY_LOGS = create(key("cherry_logs")); + + /** + * {@code #minecraft:climbable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CLIMBABLE = create(key("climbable")); + + /** + * {@code #minecraft:coal_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COAL_ORES = create(key("coal_ores")); + + /** + * {@code #minecraft:combination_step_sound_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COMBINATION_STEP_SOUND_BLOCKS = create(key("combination_step_sound_blocks")); + + /** + * {@code #minecraft:completes_find_tree_tutorial} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COMPLETES_FIND_TREE_TUTORIAL = create(key("completes_find_tree_tutorial")); + + /** + * {@code #minecraft:concrete_powder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CONCRETE_POWDER = create(key("concrete_powder")); + + /** + * {@code #minecraft:convertable_to_mud} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CONVERTABLE_TO_MUD = create(key("convertable_to_mud")); + + /** + * {@code #minecraft:copper_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COPPER_ORES = create(key("copper_ores")); + + /** + * {@code #minecraft:coral_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CORAL_BLOCKS = create(key("coral_blocks")); + + /** + * {@code #minecraft:coral_plants} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CORAL_PLANTS = create(key("coral_plants")); + + /** + * {@code #minecraft:corals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CORALS = create(key("corals")); + + /** + * {@code #minecraft:crimson_stems} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CRIMSON_STEMS = create(key("crimson_stems")); + + /** + * {@code #minecraft:crops} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CROPS = create(key("crops")); + + /** + * {@code #minecraft:crystal_sound_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CRYSTAL_SOUND_BLOCKS = create(key("crystal_sound_blocks")); + + /** + * {@code #minecraft:dampens_vibrations} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DAMPENS_VIBRATIONS = create(key("dampens_vibrations")); + + /** + * {@code #minecraft:dark_oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DARK_OAK_LOGS = create(key("dark_oak_logs")); + + /** + * {@code #minecraft:dead_bush_may_place_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DEAD_BUSH_MAY_PLACE_ON = create(key("dead_bush_may_place_on")); + + /** + * {@code #minecraft:deepslate_ore_replaceables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DEEPSLATE_ORE_REPLACEABLES = create(key("deepslate_ore_replaceables")); + + /** + * {@code #minecraft:diamond_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DIAMOND_ORES = create(key("diamond_ores")); + + /** + * {@code #minecraft:dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DIRT = create(key("dirt")); + + /** + * {@code #minecraft:does_not_block_hoppers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DOES_NOT_BLOCK_HOPPERS = create(key("does_not_block_hoppers")); + + /** + * {@code #minecraft:doors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DOORS = create(key("doors")); + + /** + * {@code #minecraft:dragon_immune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DRAGON_IMMUNE = create(key("dragon_immune")); + + /** + * {@code #minecraft:dragon_transparent} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DRAGON_TRANSPARENT = create(key("dragon_transparent")); + + /** + * {@code #minecraft:dripstone_replaceable_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DRIPSTONE_REPLACEABLE_BLOCKS = create(key("dripstone_replaceable_blocks")); + + /** + * {@code #minecraft:emerald_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EMERALD_ORES = create(key("emerald_ores")); + + /** + * {@code #minecraft:enchantment_power_provider} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTMENT_POWER_PROVIDER = create(key("enchantment_power_provider")); + + /** + * {@code #minecraft:enchantment_power_transmitter} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTMENT_POWER_TRANSMITTER = create(key("enchantment_power_transmitter")); + + /** + * {@code #minecraft:enderman_holdable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENDERMAN_HOLDABLE = create(key("enderman_holdable")); + + /** + * {@code #minecraft:fall_damage_resetting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FALL_DAMAGE_RESETTING = create(key("fall_damage_resetting")); + + /** + * {@code #minecraft:features_cannot_replace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FEATURES_CANNOT_REPLACE = create(key("features_cannot_replace")); + + /** + * {@code #minecraft:fence_gates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FENCE_GATES = create(key("fence_gates")); + + /** + * {@code #minecraft:fences} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FENCES = create(key("fences")); + + /** + * {@code #minecraft:fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FIRE = create(key("fire")); + + /** + * {@code #minecraft:flower_pots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FLOWER_POTS = create(key("flower_pots")); + + /** + * {@code #minecraft:flowers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FLOWERS = create(key("flowers")); + + /** + * {@code #minecraft:foxes_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FOXES_SPAWNABLE_ON = create(key("foxes_spawnable_on")); + + /** + * {@code #minecraft:frog_prefer_jump_to} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FROG_PREFER_JUMP_TO = create(key("frog_prefer_jump_to")); + + /** + * {@code #minecraft:frogs_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FROGS_SPAWNABLE_ON = create(key("frogs_spawnable_on")); + + /** + * {@code #minecraft:geode_invalid_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GEODE_INVALID_BLOCKS = create(key("geode_invalid_blocks")); + + /** + * {@code #minecraft:goats_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOATS_SPAWNABLE_ON = create(key("goats_spawnable_on")); + + /** + * {@code #minecraft:gold_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOLD_ORES = create(key("gold_ores")); + + /** + * {@code #minecraft:guarded_by_piglins} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GUARDED_BY_PIGLINS = create(key("guarded_by_piglins")); + + /** + * {@code #minecraft:hoglin_repellents} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HOGLIN_REPELLENTS = create(key("hoglin_repellents")); + + /** + * {@code #minecraft:ice} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ICE = create(key("ice")); + + /** + * {@code #minecraft:impermeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IMPERMEABLE = create(key("impermeable")); + + /** + * {@code #minecraft:incorrect_for_diamond_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_DIAMOND_TOOL = create(key("incorrect_for_diamond_tool")); + + /** + * {@code #minecraft:incorrect_for_gold_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_GOLD_TOOL = create(key("incorrect_for_gold_tool")); + + /** + * {@code #minecraft:incorrect_for_iron_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_IRON_TOOL = create(key("incorrect_for_iron_tool")); + + /** + * {@code #minecraft:incorrect_for_netherite_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_NETHERITE_TOOL = create(key("incorrect_for_netherite_tool")); + + /** + * {@code #minecraft:incorrect_for_stone_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_STONE_TOOL = create(key("incorrect_for_stone_tool")); + + /** + * {@code #minecraft:incorrect_for_wooden_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INCORRECT_FOR_WOODEN_TOOL = create(key("incorrect_for_wooden_tool")); + + /** + * {@code #minecraft:infiniburn_end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INFINIBURN_END = create(key("infiniburn_end")); + + /** + * {@code #minecraft:infiniburn_nether} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INFINIBURN_NETHER = create(key("infiniburn_nether")); + + /** + * {@code #minecraft:infiniburn_overworld} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INFINIBURN_OVERWORLD = create(key("infiniburn_overworld")); + + /** + * {@code #minecraft:inside_step_sound_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INSIDE_STEP_SOUND_BLOCKS = create(key("inside_step_sound_blocks")); + + /** + * {@code #minecraft:invalid_spawn_inside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey INVALID_SPAWN_INSIDE = create(key("invalid_spawn_inside")); + + /** + * {@code #minecraft:iron_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IRON_ORES = create(key("iron_ores")); + + /** + * {@code #minecraft:jungle_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey JUNGLE_LOGS = create(key("jungle_logs")); + + /** + * {@code #minecraft:lapis_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LAPIS_ORES = create(key("lapis_ores")); + + /** + * {@code #minecraft:lava_pool_stone_cannot_replace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LAVA_POOL_STONE_CANNOT_REPLACE = create(key("lava_pool_stone_cannot_replace")); + + /** + * {@code #minecraft:leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LEAVES = create(key("leaves")); + + /** + * {@code #minecraft:logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LOGS = create(key("logs")); + + /** + * {@code #minecraft:logs_that_burn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LOGS_THAT_BURN = create(key("logs_that_burn")); + + /** + * {@code #minecraft:lush_ground_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LUSH_GROUND_REPLACEABLE = create(key("lush_ground_replaceable")); + + /** + * {@code #minecraft:maintains_farmland} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MAINTAINS_FARMLAND = create(key("maintains_farmland")); + + /** + * {@code #minecraft:mangrove_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MANGROVE_LOGS = create(key("mangrove_logs")); + + /** + * {@code #minecraft:mangrove_logs_can_grow_through} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MANGROVE_LOGS_CAN_GROW_THROUGH = create(key("mangrove_logs_can_grow_through")); + + /** + * {@code #minecraft:mangrove_roots_can_grow_through} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MANGROVE_ROOTS_CAN_GROW_THROUGH = create(key("mangrove_roots_can_grow_through")); + + /** + * {@code #minecraft:mineable/axe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINEABLE_AXE = create(key("mineable/axe")); + + /** + * {@code #minecraft:mineable/hoe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINEABLE_HOE = create(key("mineable/hoe")); + + /** + * {@code #minecraft:mineable/pickaxe} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINEABLE_PICKAXE = create(key("mineable/pickaxe")); + + /** + * {@code #minecraft:mineable/shovel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINEABLE_SHOVEL = create(key("mineable/shovel")); + + /** + * {@code #minecraft:mob_interactable_doors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MOB_INTERACTABLE_DOORS = create(key("mob_interactable_doors")); + + /** + * {@code #minecraft:mooshrooms_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MOOSHROOMS_SPAWNABLE_ON = create(key("mooshrooms_spawnable_on")); + + /** + * {@code #minecraft:moss_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MOSS_REPLACEABLE = create(key("moss_replaceable")); + + /** + * {@code #minecraft:mushroom_grow_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MUSHROOM_GROW_BLOCK = create(key("mushroom_grow_block")); + + /** + * {@code #minecraft:needs_diamond_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NEEDS_DIAMOND_TOOL = create(key("needs_diamond_tool")); + + /** + * {@code #minecraft:needs_iron_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NEEDS_IRON_TOOL = create(key("needs_iron_tool")); + + /** + * {@code #minecraft:needs_stone_tool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NEEDS_STONE_TOOL = create(key("needs_stone_tool")); + + /** + * {@code #minecraft:nether_carver_replaceables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NETHER_CARVER_REPLACEABLES = create(key("nether_carver_replaceables")); + + /** + * {@code #minecraft:nylium} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NYLIUM = create(key("nylium")); + + /** + * {@code #minecraft:oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OAK_LOGS = create(key("oak_logs")); + + /** + * {@code #minecraft:occludes_vibration_signals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OCCLUDES_VIBRATION_SIGNALS = create(key("occludes_vibration_signals")); + + /** + * {@code #minecraft:overworld_carver_replaceables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OVERWORLD_CARVER_REPLACEABLES = create(key("overworld_carver_replaceables")); + + /** + * {@code #minecraft:overworld_natural_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OVERWORLD_NATURAL_LOGS = create(key("overworld_natural_logs")); + + /** + * {@code #minecraft:pale_oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PALE_OAK_LOGS = create(key("pale_oak_logs")); + + /** + * {@code #minecraft:parrots_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PARROTS_SPAWNABLE_ON = create(key("parrots_spawnable_on")); + + /** + * {@code #minecraft:piglin_repellents} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_REPELLENTS = create(key("piglin_repellents")); + + /** + * {@code #minecraft:planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PLANKS = create(key("planks")); + + /** + * {@code #minecraft:polar_bears_spawnable_on_alternate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = create(key("polar_bears_spawnable_on_alternate")); + + /** + * {@code #minecraft:portals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PORTALS = create(key("portals")); + + /** + * {@code #minecraft:pressure_plates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PRESSURE_PLATES = create(key("pressure_plates")); + + /** + * {@code #minecraft:prevent_mob_spawning_inside} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PREVENT_MOB_SPAWNING_INSIDE = create(key("prevent_mob_spawning_inside")); + + /** + * {@code #minecraft:rabbits_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey RABBITS_SPAWNABLE_ON = create(key("rabbits_spawnable_on")); + + /** + * {@code #minecraft:rails} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey RAILS = create(key("rails")); + + /** + * {@code #minecraft:redstone_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REDSTONE_ORES = create(key("redstone_ores")); + + /** + * {@code #minecraft:replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPLACEABLE = create(key("replaceable")); + + /** + * {@code #minecraft:replaceable_by_trees} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPLACEABLE_BY_TREES = create(key("replaceable_by_trees")); + + /** + * {@code #minecraft:sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SAND = create(key("sand")); + + /** + * {@code #minecraft:saplings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SAPLINGS = create(key("saplings")); + + /** + * {@code #minecraft:sculk_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SCULK_REPLACEABLE = create(key("sculk_replaceable")); + + /** + * {@code #minecraft:sculk_replaceable_world_gen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SCULK_REPLACEABLE_WORLD_GEN = create(key("sculk_replaceable_world_gen")); + + /** + * {@code #minecraft:shulker_boxes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHULKER_BOXES = create(key("shulker_boxes")); + + /** + * {@code #minecraft:signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SIGNS = create(key("signs")); + + /** + * {@code #minecraft:slabs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SLABS = create(key("slabs")); + + /** + * {@code #minecraft:small_dripleaf_placeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMALL_DRIPLEAF_PLACEABLE = create(key("small_dripleaf_placeable")); + + /** + * {@code #minecraft:small_flowers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMALL_FLOWERS = create(key("small_flowers")); + + /** + * {@code #minecraft:smelts_to_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMELTS_TO_GLASS = create(key("smelts_to_glass")); + + /** + * {@code #minecraft:snaps_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNAPS_GOAT_HORN = create(key("snaps_goat_horn")); + + /** + * {@code #minecraft:sniffer_diggable_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNIFFER_DIGGABLE_BLOCK = create(key("sniffer_diggable_block")); + + /** + * {@code #minecraft:sniffer_egg_hatch_boost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNIFFER_EGG_HATCH_BOOST = create(key("sniffer_egg_hatch_boost")); + + /** + * {@code #minecraft:snow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNOW = create(key("snow")); + + /** + * {@code #minecraft:snow_layer_can_survive_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNOW_LAYER_CAN_SURVIVE_ON = create(key("snow_layer_can_survive_on")); + + /** + * {@code #minecraft:snow_layer_cannot_survive_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNOW_LAYER_CANNOT_SURVIVE_ON = create(key("snow_layer_cannot_survive_on")); + + /** + * {@code #minecraft:soul_fire_base_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SOUL_FIRE_BASE_BLOCKS = create(key("soul_fire_base_blocks")); + + /** + * {@code #minecraft:soul_speed_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SOUL_SPEED_BLOCKS = create(key("soul_speed_blocks")); + + /** + * {@code #minecraft:spruce_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPRUCE_LOGS = create(key("spruce_logs")); + + /** + * {@code #minecraft:stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STAIRS = create(key("stairs")); + + /** + * {@code #minecraft:standing_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STANDING_SIGNS = create(key("standing_signs")); + + /** + * {@code #minecraft:stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_BRICKS = create(key("stone_bricks")); + + /** + * {@code #minecraft:stone_buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_BUTTONS = create(key("stone_buttons")); + + /** + * {@code #minecraft:stone_ore_replaceables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_ORE_REPLACEABLES = create(key("stone_ore_replaceables")); + + /** + * {@code #minecraft:stone_pressure_plates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_PRESSURE_PLATES = create(key("stone_pressure_plates")); + + /** + * {@code #minecraft:strider_warm_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STRIDER_WARM_BLOCKS = create(key("strider_warm_blocks")); + + /** + * {@code #minecraft:sword_efficient} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SWORD_EFFICIENT = create(key("sword_efficient")); + + /** + * {@code #minecraft:terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TERRACOTTA = create(key("terracotta")); + + /** + * {@code #minecraft:trail_ruins_replaceable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRAIL_RUINS_REPLACEABLE = create(key("trail_ruins_replaceable")); + + /** + * {@code #minecraft:trapdoors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRAPDOORS = create(key("trapdoors")); + + /** + * {@code #minecraft:underwater_bonemeals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey UNDERWATER_BONEMEALS = create(key("underwater_bonemeals")); + + /** + * {@code #minecraft:unstable_bottom_center} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey UNSTABLE_BOTTOM_CENTER = create(key("unstable_bottom_center")); + + /** + * {@code #minecraft:valid_spawn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VALID_SPAWN = create(key("valid_spawn")); + + /** + * {@code #minecraft:vibration_resonators} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VIBRATION_RESONATORS = create(key("vibration_resonators")); + + /** + * {@code #minecraft:wall_corals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALL_CORALS = create(key("wall_corals")); + + /** + * {@code #minecraft:wall_hanging_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALL_HANGING_SIGNS = create(key("wall_hanging_signs")); + + /** + * {@code #minecraft:wall_post_override} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALL_POST_OVERRIDE = create(key("wall_post_override")); + + /** + * {@code #minecraft:wall_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALL_SIGNS = create(key("wall_signs")); + + /** + * {@code #minecraft:walls} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALLS = create(key("walls")); + + /** + * {@code #minecraft:warped_stems} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WARPED_STEMS = create(key("warped_stems")); + + /** + * {@code #minecraft:wart_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WART_BLOCKS = create(key("wart_blocks")); + + /** + * {@code #minecraft:wither_immune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHER_IMMUNE = create(key("wither_immune")); + + /** + * {@code #minecraft:wither_summon_base_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHER_SUMMON_BASE_BLOCKS = create(key("wither_summon_base_blocks")); + + /** + * {@code #minecraft:wolves_spawnable_on} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOLVES_SPAWNABLE_ON = create(key("wolves_spawnable_on")); + + /** + * {@code #minecraft:wooden_buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_BUTTONS = create(key("wooden_buttons")); + + /** + * {@code #minecraft:wooden_doors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_DOORS = create(key("wooden_doors")); + + /** + * {@code #minecraft:wooden_fences} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_FENCES = create(key("wooden_fences")); + + /** + * {@code #minecraft:wooden_pressure_plates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_PRESSURE_PLATES = create(key("wooden_pressure_plates")); + + /** + * {@code #minecraft:wooden_slabs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_SLABS = create(key("wooden_slabs")); + + /** + * {@code #minecraft:wooden_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_STAIRS = create(key("wooden_stairs")); + + /** + * {@code #minecraft:wooden_trapdoors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_TRAPDOORS = create(key("wooden_trapdoors")); + + /** + * {@code #minecraft:wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOOL = create(key("wool")); + + /** + * {@code #minecraft:wool_carpets} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOOL_CARPETS = create(key("wool_carpets")); + + private BlockTypeTagKeys() { + } + + /** + * Creates a tag key for {@link BlockType} in the registry {@code minecraft:block}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.BLOCK, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/CatVariantTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/CatVariantTagKeys.java new file mode 100644 index 000000000000..17a43aa9ebbe --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/CatVariantTagKeys.java @@ -0,0 +1,57 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.entity.Cat; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#CAT_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class CatVariantTagKeys { + /** + * {@code #minecraft:default_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DEFAULT_SPAWNS = create(key("default_spawns")); + + /** + * {@code #minecraft:full_moon_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FULL_MOON_SPAWNS = create(key("full_moon_spawns")); + + private CatVariantTagKeys() { + } + + /** + * Creates a tag key for {@link Cat.Type} in the registry {@code minecraft:cat_variant}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.CAT_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/DamageTypeTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/DamageTypeTagKeys.java new file mode 100644 index 000000000000..d70cb03974b0 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/DamageTypeTagKeys.java @@ -0,0 +1,274 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.damage.DamageType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#DAMAGE_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class DamageTypeTagKeys { + /** + * {@code #minecraft:always_hurts_ender_dragons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALWAYS_HURTS_ENDER_DRAGONS = create(key("always_hurts_ender_dragons")); + + /** + * {@code #minecraft:always_kills_armor_stands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALWAYS_KILLS_ARMOR_STANDS = create(key("always_kills_armor_stands")); + + /** + * {@code #minecraft:always_most_significant_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALWAYS_MOST_SIGNIFICANT_FALL = create(key("always_most_significant_fall")); + + /** + * {@code #minecraft:always_triggers_silverfish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALWAYS_TRIGGERS_SILVERFISH = create(key("always_triggers_silverfish")); + + /** + * {@code #minecraft:avoids_guardian_thorns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AVOIDS_GUARDIAN_THORNS = create(key("avoids_guardian_thorns")); + + /** + * {@code #minecraft:burn_from_stepping} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BURN_FROM_STEPPING = create(key("burn_from_stepping")); + + /** + * {@code #minecraft:burns_armor_stands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BURNS_ARMOR_STANDS = create(key("burns_armor_stands")); + + /** + * {@code #minecraft:bypasses_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_ARMOR = create(key("bypasses_armor")); + + /** + * {@code #minecraft:bypasses_effects} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_EFFECTS = create(key("bypasses_effects")); + + /** + * {@code #minecraft:bypasses_enchantments} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_ENCHANTMENTS = create(key("bypasses_enchantments")); + + /** + * {@code #minecraft:bypasses_invulnerability} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_INVULNERABILITY = create(key("bypasses_invulnerability")); + + /** + * {@code #minecraft:bypasses_resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_RESISTANCE = create(key("bypasses_resistance")); + + /** + * {@code #minecraft:bypasses_shield} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_SHIELD = create(key("bypasses_shield")); + + /** + * {@code #minecraft:bypasses_wolf_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BYPASSES_WOLF_ARMOR = create(key("bypasses_wolf_armor")); + + /** + * {@code #minecraft:can_break_armor_stand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAN_BREAK_ARMOR_STAND = create(key("can_break_armor_stand")); + + /** + * {@code #minecraft:damages_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DAMAGES_HELMET = create(key("damages_helmet")); + + /** + * {@code #minecraft:ignites_armor_stands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IGNITES_ARMOR_STANDS = create(key("ignites_armor_stands")); + + /** + * {@code #minecraft:is_drowning} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_DROWNING = create(key("is_drowning")); + + /** + * {@code #minecraft:is_explosion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_EXPLOSION = create(key("is_explosion")); + + /** + * {@code #minecraft:is_fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_FALL = create(key("is_fall")); + + /** + * {@code #minecraft:is_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_FIRE = create(key("is_fire")); + + /** + * {@code #minecraft:is_freezing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_FREEZING = create(key("is_freezing")); + + /** + * {@code #minecraft:is_lightning} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_LIGHTNING = create(key("is_lightning")); + + /** + * {@code #minecraft:is_player_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_PLAYER_ATTACK = create(key("is_player_attack")); + + /** + * {@code #minecraft:is_projectile} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IS_PROJECTILE = create(key("is_projectile")); + + /** + * {@code #minecraft:mace_smash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MACE_SMASH = create(key("mace_smash")); + + /** + * {@code #minecraft:no_anger} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NO_ANGER = create(key("no_anger")); + + /** + * {@code #minecraft:no_impact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NO_IMPACT = create(key("no_impact")); + + /** + * {@code #minecraft:no_knockback} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NO_KNOCKBACK = create(key("no_knockback")); + + /** + * {@code #minecraft:panic_causes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PANIC_CAUSES = create(key("panic_causes")); + + /** + * {@code #minecraft:panic_environmental_causes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PANIC_ENVIRONMENTAL_CAUSES = create(key("panic_environmental_causes")); + + /** + * {@code #minecraft:witch_resistant_to} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITCH_RESISTANT_TO = create(key("witch_resistant_to")); + + /** + * {@code #minecraft:wither_immune_to} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHER_IMMUNE_TO = create(key("wither_immune_to")); + + private DamageTypeTagKeys() { + } + + /** + * Creates a tag key for {@link DamageType} in the registry {@code minecraft:damage_type}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.DAMAGE_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/EnchantmentTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/EnchantmentTagKeys.java new file mode 100644 index 000000000000..cf5a921cdb6d --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/EnchantmentTagKeys.java @@ -0,0 +1,324 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.MinecraftExperimental; +import org.bukkit.enchantments.Enchantment; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#ENCHANTMENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class EnchantmentTagKeys { + /** + * {@code #minecraft:curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CURSE = create(key("curse")); + + /** + * {@code #minecraft:double_trade_price} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DOUBLE_TRADE_PRICE = create(key("double_trade_price")); + + /** + * {@code #minecraft:exclusive_set/armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_ARMOR = create(key("exclusive_set/armor")); + + /** + * {@code #minecraft:exclusive_set/boots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_BOOTS = create(key("exclusive_set/boots")); + + /** + * {@code #minecraft:exclusive_set/bow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_BOW = create(key("exclusive_set/bow")); + + /** + * {@code #minecraft:exclusive_set/crossbow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_CROSSBOW = create(key("exclusive_set/crossbow")); + + /** + * {@code #minecraft:exclusive_set/damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_DAMAGE = create(key("exclusive_set/damage")); + + /** + * {@code #minecraft:exclusive_set/mining} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_MINING = create(key("exclusive_set/mining")); + + /** + * {@code #minecraft:exclusive_set/riptide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EXCLUSIVE_SET_RIPTIDE = create(key("exclusive_set/riptide")); + + /** + * {@code #minecraft:in_enchanting_table} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IN_ENCHANTING_TABLE = create(key("in_enchanting_table")); + + /** + * {@code #minecraft:non_treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NON_TREASURE = create(key("non_treasure")); + + /** + * {@code #minecraft:on_mob_spawn_equipment} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_MOB_SPAWN_EQUIPMENT = create(key("on_mob_spawn_equipment")); + + /** + * {@code #minecraft:on_random_loot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_RANDOM_LOOT = create(key("on_random_loot")); + + /** + * {@code #minecraft:on_traded_equipment} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_TRADED_EQUIPMENT = create(key("on_traded_equipment")); + + /** + * {@code #minecraft:prevents_bee_spawns_when_mining} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PREVENTS_BEE_SPAWNS_WHEN_MINING = create(key("prevents_bee_spawns_when_mining")); + + /** + * {@code #minecraft:prevents_decorated_pot_shattering} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PREVENTS_DECORATED_POT_SHATTERING = create(key("prevents_decorated_pot_shattering")); + + /** + * {@code #minecraft:prevents_ice_melting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PREVENTS_ICE_MELTING = create(key("prevents_ice_melting")); + + /** + * {@code #minecraft:prevents_infested_spawns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PREVENTS_INFESTED_SPAWNS = create(key("prevents_infested_spawns")); + + /** + * {@code #minecraft:smelts_loot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMELTS_LOOT = create(key("smelts_loot")); + + /** + * {@code #minecraft:tooltip_order} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TOOLTIP_ORDER = create(key("tooltip_order")); + + /** + * {@code #minecraft:tradeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRADEABLE = create(key("tradeable")); + + /** + * {@code #minecraft:trades/desert_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_DESERT_COMMON = create(key("trades/desert_common")); + + /** + * {@code #minecraft:trades/desert_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_DESERT_SPECIAL = create(key("trades/desert_special")); + + /** + * {@code #minecraft:trades/jungle_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_JUNGLE_COMMON = create(key("trades/jungle_common")); + + /** + * {@code #minecraft:trades/jungle_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_JUNGLE_SPECIAL = create(key("trades/jungle_special")); + + /** + * {@code #minecraft:trades/plains_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_PLAINS_COMMON = create(key("trades/plains_common")); + + /** + * {@code #minecraft:trades/plains_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_PLAINS_SPECIAL = create(key("trades/plains_special")); + + /** + * {@code #minecraft:trades/savanna_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SAVANNA_COMMON = create(key("trades/savanna_common")); + + /** + * {@code #minecraft:trades/savanna_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SAVANNA_SPECIAL = create(key("trades/savanna_special")); + + /** + * {@code #minecraft:trades/snow_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SNOW_COMMON = create(key("trades/snow_common")); + + /** + * {@code #minecraft:trades/snow_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SNOW_SPECIAL = create(key("trades/snow_special")); + + /** + * {@code #minecraft:trades/swamp_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SWAMP_COMMON = create(key("trades/swamp_common")); + + /** + * {@code #minecraft:trades/swamp_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_SWAMP_SPECIAL = create(key("trades/swamp_special")); + + /** + * {@code #minecraft:trades/taiga_common} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_TAIGA_COMMON = create(key("trades/taiga_common")); + + /** + * {@code #minecraft:trades/taiga_special} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey TRADES_TAIGA_SPECIAL = create(key("trades/taiga_special")); + + /** + * {@code #minecraft:treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TREASURE = create(key("treasure")); + + private EnchantmentTagKeys() { + } + + /** + * Creates a tag key for {@link Enchantment} in the registry {@code minecraft:enchantment}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.ENCHANTMENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/FluidTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/FluidTagKeys.java new file mode 100644 index 000000000000..4a33d3e87e90 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/FluidTagKeys.java @@ -0,0 +1,57 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.Fluid; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#FLUID}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class FluidTagKeys { + /** + * {@code #minecraft:lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LAVA = create(key("lava")); + + /** + * {@code #minecraft:water} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WATER = create(key("water")); + + private FluidTagKeys() { + } + + /** + * Creates a tag key for {@link Fluid} in the registry {@code minecraft:fluid}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.FLUID, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/GameEventTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/GameEventTagKeys.java new file mode 100644 index 000000000000..3cb6d6e1e05e --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/GameEventTagKeys.java @@ -0,0 +1,78 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.GameEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#GAME_EVENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class GameEventTagKeys { + /** + * {@code #minecraft:allay_can_listen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ALLAY_CAN_LISTEN = create(key("allay_can_listen")); + + /** + * {@code #minecraft:ignore_vibrations_sneaking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IGNORE_VIBRATIONS_SNEAKING = create(key("ignore_vibrations_sneaking")); + + /** + * {@code #minecraft:shrieker_can_listen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHRIEKER_CAN_LISTEN = create(key("shrieker_can_listen")); + + /** + * {@code #minecraft:vibrations} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VIBRATIONS = create(key("vibrations")); + + /** + * {@code #minecraft:warden_can_listen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WARDEN_CAN_LISTEN = create(key("warden_can_listen")); + + private GameEventTagKeys() { + } + + /** + * Creates a tag key for {@link GameEvent} in the registry {@code minecraft:game_event}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.GAME_EVENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/InstrumentTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/InstrumentTagKeys.java new file mode 100644 index 000000000000..527fb77610b0 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/InstrumentTagKeys.java @@ -0,0 +1,64 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.MusicInstrument; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#INSTRUMENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class InstrumentTagKeys { + /** + * {@code #minecraft:goat_horns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOAT_HORNS = create(key("goat_horns")); + + /** + * {@code #minecraft:regular_goat_horns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REGULAR_GOAT_HORNS = create(key("regular_goat_horns")); + + /** + * {@code #minecraft:screaming_goat_horns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SCREAMING_GOAT_HORNS = create(key("screaming_goat_horns")); + + private InstrumentTagKeys() { + } + + /** + * Creates a tag key for {@link MusicInstrument} in the registry {@code minecraft:instrument}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.INSTRUMENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/ItemTypeTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/ItemTypeTagKeys.java new file mode 100644 index 000000000000..bf43d9af90b8 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/ItemTypeTagKeys.java @@ -0,0 +1,1254 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.ItemType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#ITEM}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class ItemTypeTagKeys { + /** + * {@code #minecraft:acacia_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ACACIA_LOGS = create(key("acacia_logs")); + + /** + * {@code #minecraft:anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ANVIL = create(key("anvil")); + + /** + * {@code #minecraft:armadillo_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ARMADILLO_FOOD = create(key("armadillo_food")); + + /** + * {@code #minecraft:arrows} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ARROWS = create(key("arrows")); + + /** + * {@code #minecraft:axes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AXES = create(key("axes")); + + /** + * {@code #minecraft:axolotl_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey AXOLOTL_FOOD = create(key("axolotl_food")); + + /** + * {@code #minecraft:bamboo_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BAMBOO_BLOCKS = create(key("bamboo_blocks")); + + /** + * {@code #minecraft:banners} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BANNERS = create(key("banners")); + + /** + * {@code #minecraft:beacon_payment_items} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEACON_PAYMENT_ITEMS = create(key("beacon_payment_items")); + + /** + * {@code #minecraft:beds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEDS = create(key("beds")); + + /** + * {@code #minecraft:bee_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BEE_FOOD = create(key("bee_food")); + + /** + * {@code #minecraft:birch_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BIRCH_LOGS = create(key("birch_logs")); + + /** + * {@code #minecraft:boats} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BOATS = create(key("boats")); + + /** + * {@code #minecraft:bookshelf_books} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BOOKSHELF_BOOKS = create(key("bookshelf_books")); + + /** + * {@code #minecraft:breaks_decorated_pots} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BREAKS_DECORATED_POTS = create(key("breaks_decorated_pots")); + + /** + * {@code #minecraft:brewing_fuel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BREWING_FUEL = create(key("brewing_fuel")); + + /** + * {@code #minecraft:bundles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BUNDLES = create(key("bundles")); + + /** + * {@code #minecraft:buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey BUTTONS = create(key("buttons")); + + /** + * {@code #minecraft:camel_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAMEL_FOOD = create(key("camel_food")); + + /** + * {@code #minecraft:candles} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CANDLES = create(key("candles")); + + /** + * {@code #minecraft:cat_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CAT_FOOD = create(key("cat_food")); + + /** + * {@code #minecraft:cherry_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CHERRY_LOGS = create(key("cherry_logs")); + + /** + * {@code #minecraft:chest_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CHEST_ARMOR = create(key("chest_armor")); + + /** + * {@code #minecraft:chest_boats} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CHEST_BOATS = create(key("chest_boats")); + + /** + * {@code #minecraft:chicken_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CHICKEN_FOOD = create(key("chicken_food")); + + /** + * {@code #minecraft:cluster_max_harvestables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CLUSTER_MAX_HARVESTABLES = create(key("cluster_max_harvestables")); + + /** + * {@code #minecraft:coal_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COAL_ORES = create(key("coal_ores")); + + /** + * {@code #minecraft:coals} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COALS = create(key("coals")); + + /** + * {@code #minecraft:compasses} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COMPASSES = create(key("compasses")); + + /** + * {@code #minecraft:completes_find_tree_tutorial} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COMPLETES_FIND_TREE_TUTORIAL = create(key("completes_find_tree_tutorial")); + + /** + * {@code #minecraft:copper_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COPPER_ORES = create(key("copper_ores")); + + /** + * {@code #minecraft:cow_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey COW_FOOD = create(key("cow_food")); + + /** + * {@code #minecraft:creeper_drop_music_discs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CREEPER_DROP_MUSIC_DISCS = create(key("creeper_drop_music_discs")); + + /** + * {@code #minecraft:creeper_igniters} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CREEPER_IGNITERS = create(key("creeper_igniters")); + + /** + * {@code #minecraft:crimson_stems} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CRIMSON_STEMS = create(key("crimson_stems")); + + /** + * {@code #minecraft:dampens_vibrations} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DAMPENS_VIBRATIONS = create(key("dampens_vibrations")); + + /** + * {@code #minecraft:dark_oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DARK_OAK_LOGS = create(key("dark_oak_logs")); + + /** + * {@code #minecraft:decorated_pot_ingredients} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DECORATED_POT_INGREDIENTS = create(key("decorated_pot_ingredients")); + + /** + * {@code #minecraft:decorated_pot_sherds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DECORATED_POT_SHERDS = create(key("decorated_pot_sherds")); + + /** + * {@code #minecraft:diamond_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DIAMOND_ORES = create(key("diamond_ores")); + + /** + * {@code #minecraft:diamond_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DIAMOND_TOOL_MATERIALS = create(key("diamond_tool_materials")); + + /** + * {@code #minecraft:dirt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DIRT = create(key("dirt")); + + /** + * {@code #minecraft:doors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DOORS = create(key("doors")); + + /** + * {@code #minecraft:drowned_preferred_weapons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DROWNED_PREFERRED_WEAPONS = create(key("drowned_preferred_weapons")); + + /** + * {@code #minecraft:duplicates_allays} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DUPLICATES_ALLAYS = create(key("duplicates_allays")); + + /** + * {@code #minecraft:dyeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DYEABLE = create(key("dyeable")); + + /** + * {@code #minecraft:emerald_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EMERALD_ORES = create(key("emerald_ores")); + + /** + * {@code #minecraft:enchantable/armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_ARMOR = create(key("enchantable/armor")); + + /** + * {@code #minecraft:enchantable/bow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_BOW = create(key("enchantable/bow")); + + /** + * {@code #minecraft:enchantable/chest_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_CHEST_ARMOR = create(key("enchantable/chest_armor")); + + /** + * {@code #minecraft:enchantable/crossbow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_CROSSBOW = create(key("enchantable/crossbow")); + + /** + * {@code #minecraft:enchantable/durability} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_DURABILITY = create(key("enchantable/durability")); + + /** + * {@code #minecraft:enchantable/equippable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_EQUIPPABLE = create(key("enchantable/equippable")); + + /** + * {@code #minecraft:enchantable/fire_aspect} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_FIRE_ASPECT = create(key("enchantable/fire_aspect")); + + /** + * {@code #minecraft:enchantable/fishing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_FISHING = create(key("enchantable/fishing")); + + /** + * {@code #minecraft:enchantable/foot_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_FOOT_ARMOR = create(key("enchantable/foot_armor")); + + /** + * {@code #minecraft:enchantable/head_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_HEAD_ARMOR = create(key("enchantable/head_armor")); + + /** + * {@code #minecraft:enchantable/leg_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_LEG_ARMOR = create(key("enchantable/leg_armor")); + + /** + * {@code #minecraft:enchantable/mace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_MACE = create(key("enchantable/mace")); + + /** + * {@code #minecraft:enchantable/mining} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_MINING = create(key("enchantable/mining")); + + /** + * {@code #minecraft:enchantable/mining_loot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_MINING_LOOT = create(key("enchantable/mining_loot")); + + /** + * {@code #minecraft:enchantable/sharp_weapon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_SHARP_WEAPON = create(key("enchantable/sharp_weapon")); + + /** + * {@code #minecraft:enchantable/sword} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_SWORD = create(key("enchantable/sword")); + + /** + * {@code #minecraft:enchantable/trident} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_TRIDENT = create(key("enchantable/trident")); + + /** + * {@code #minecraft:enchantable/vanishing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_VANISHING = create(key("enchantable/vanishing")); + + /** + * {@code #minecraft:enchantable/weapon} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ENCHANTABLE_WEAPON = create(key("enchantable/weapon")); + + /** + * {@code #minecraft:fence_gates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FENCE_GATES = create(key("fence_gates")); + + /** + * {@code #minecraft:fences} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FENCES = create(key("fences")); + + /** + * {@code #minecraft:fishes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FISHES = create(key("fishes")); + + /** + * {@code #minecraft:foot_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FOOT_ARMOR = create(key("foot_armor")); + + /** + * {@code #minecraft:fox_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FOX_FOOD = create(key("fox_food")); + + /** + * {@code #minecraft:freeze_immune_wearables} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FREEZE_IMMUNE_WEARABLES = create(key("freeze_immune_wearables")); + + /** + * {@code #minecraft:frog_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FROG_FOOD = create(key("frog_food")); + + /** + * {@code #minecraft:furnace_minecart_fuel} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey FURNACE_MINECART_FUEL = create(key("furnace_minecart_fuel")); + + /** + * {@code #minecraft:gaze_disguise_equipment} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GAZE_DISGUISE_EQUIPMENT = create(key("gaze_disguise_equipment")); + + /** + * {@code #minecraft:goat_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOAT_FOOD = create(key("goat_food")); + + /** + * {@code #minecraft:gold_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOLD_ORES = create(key("gold_ores")); + + /** + * {@code #minecraft:gold_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey GOLD_TOOL_MATERIALS = create(key("gold_tool_materials")); + + /** + * {@code #minecraft:hanging_signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HANGING_SIGNS = create(key("hanging_signs")); + + /** + * {@code #minecraft:head_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HEAD_ARMOR = create(key("head_armor")); + + /** + * {@code #minecraft:hoes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HOES = create(key("hoes")); + + /** + * {@code #minecraft:hoglin_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HOGLIN_FOOD = create(key("hoglin_food")); + + /** + * {@code #minecraft:horse_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HORSE_FOOD = create(key("horse_food")); + + /** + * {@code #minecraft:horse_tempt_items} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey HORSE_TEMPT_ITEMS = create(key("horse_tempt_items")); + + /** + * {@code #minecraft:ignored_by_piglin_babies} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IGNORED_BY_PIGLIN_BABIES = create(key("ignored_by_piglin_babies")); + + /** + * {@code #minecraft:iron_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IRON_ORES = create(key("iron_ores")); + + /** + * {@code #minecraft:iron_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey IRON_TOOL_MATERIALS = create(key("iron_tool_materials")); + + /** + * {@code #minecraft:jungle_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey JUNGLE_LOGS = create(key("jungle_logs")); + + /** + * {@code #minecraft:lapis_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LAPIS_ORES = create(key("lapis_ores")); + + /** + * {@code #minecraft:leaves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LEAVES = create(key("leaves")); + + /** + * {@code #minecraft:lectern_books} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LECTERN_BOOKS = create(key("lectern_books")); + + /** + * {@code #minecraft:leg_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LEG_ARMOR = create(key("leg_armor")); + + /** + * {@code #minecraft:llama_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LLAMA_FOOD = create(key("llama_food")); + + /** + * {@code #minecraft:llama_tempt_items} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LLAMA_TEMPT_ITEMS = create(key("llama_tempt_items")); + + /** + * {@code #minecraft:logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LOGS = create(key("logs")); + + /** + * {@code #minecraft:logs_that_burn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey LOGS_THAT_BURN = create(key("logs_that_burn")); + + /** + * {@code #minecraft:mangrove_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MANGROVE_LOGS = create(key("mangrove_logs")); + + /** + * {@code #minecraft:map_invisibility_equipment} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MAP_INVISIBILITY_EQUIPMENT = create(key("map_invisibility_equipment")); + + /** + * {@code #minecraft:meat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MEAT = create(key("meat")); + + /** + * {@code #minecraft:netherite_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NETHERITE_TOOL_MATERIALS = create(key("netherite_tool_materials")); + + /** + * {@code #minecraft:non_flammable_wood} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NON_FLAMMABLE_WOOD = create(key("non_flammable_wood")); + + /** + * {@code #minecraft:noteblock_top_instruments} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey NOTEBLOCK_TOP_INSTRUMENTS = create(key("noteblock_top_instruments")); + + /** + * {@code #minecraft:oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OAK_LOGS = create(key("oak_logs")); + + /** + * {@code #minecraft:ocelot_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OCELOT_FOOD = create(key("ocelot_food")); + + /** + * {@code #minecraft:pale_oak_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PALE_OAK_LOGS = create(key("pale_oak_logs")); + + /** + * {@code #minecraft:panda_eats_from_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PANDA_EATS_FROM_GROUND = create(key("panda_eats_from_ground")); + + /** + * {@code #minecraft:panda_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PANDA_FOOD = create(key("panda_food")); + + /** + * {@code #minecraft:parrot_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PARROT_FOOD = create(key("parrot_food")); + + /** + * {@code #minecraft:parrot_poisonous_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PARROT_POISONOUS_FOOD = create(key("parrot_poisonous_food")); + + /** + * {@code #minecraft:pickaxes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PICKAXES = create(key("pickaxes")); + + /** + * {@code #minecraft:pig_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIG_FOOD = create(key("pig_food")); + + /** + * {@code #minecraft:piglin_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_FOOD = create(key("piglin_food")); + + /** + * {@code #minecraft:piglin_loved} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_LOVED = create(key("piglin_loved")); + + /** + * {@code #minecraft:piglin_preferred_weapons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_PREFERRED_WEAPONS = create(key("piglin_preferred_weapons")); + + /** + * {@code #minecraft:piglin_repellents} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_REPELLENTS = create(key("piglin_repellents")); + + /** + * {@code #minecraft:piglin_safe_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PIGLIN_SAFE_ARMOR = create(key("piglin_safe_armor")); + + /** + * {@code #minecraft:pillager_preferred_weapons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PILLAGER_PREFERRED_WEAPONS = create(key("pillager_preferred_weapons")); + + /** + * {@code #minecraft:planks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PLANKS = create(key("planks")); + + /** + * {@code #minecraft:rabbit_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey RABBIT_FOOD = create(key("rabbit_food")); + + /** + * {@code #minecraft:rails} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey RAILS = create(key("rails")); + + /** + * {@code #minecraft:redstone_ores} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REDSTONE_ORES = create(key("redstone_ores")); + + /** + * {@code #minecraft:repairs_chain_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_CHAIN_ARMOR = create(key("repairs_chain_armor")); + + /** + * {@code #minecraft:repairs_diamond_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_DIAMOND_ARMOR = create(key("repairs_diamond_armor")); + + /** + * {@code #minecraft:repairs_gold_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_GOLD_ARMOR = create(key("repairs_gold_armor")); + + /** + * {@code #minecraft:repairs_iron_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_IRON_ARMOR = create(key("repairs_iron_armor")); + + /** + * {@code #minecraft:repairs_leather_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_LEATHER_ARMOR = create(key("repairs_leather_armor")); + + /** + * {@code #minecraft:repairs_netherite_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_NETHERITE_ARMOR = create(key("repairs_netherite_armor")); + + /** + * {@code #minecraft:repairs_turtle_helmet} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_TURTLE_HELMET = create(key("repairs_turtle_helmet")); + + /** + * {@code #minecraft:repairs_wolf_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey REPAIRS_WOLF_ARMOR = create(key("repairs_wolf_armor")); + + /** + * {@code #minecraft:sand} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SAND = create(key("sand")); + + /** + * {@code #minecraft:saplings} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SAPLINGS = create(key("saplings")); + + /** + * {@code #minecraft:sheep_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHEEP_FOOD = create(key("sheep_food")); + + /** + * {@code #minecraft:shovels} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHOVELS = create(key("shovels")); + + /** + * {@code #minecraft:shulker_boxes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHULKER_BOXES = create(key("shulker_boxes")); + + /** + * {@code #minecraft:signs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SIGNS = create(key("signs")); + + /** + * {@code #minecraft:skeleton_preferred_weapons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SKELETON_PREFERRED_WEAPONS = create(key("skeleton_preferred_weapons")); + + /** + * {@code #minecraft:skulls} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SKULLS = create(key("skulls")); + + /** + * {@code #minecraft:slabs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SLABS = create(key("slabs")); + + /** + * {@code #minecraft:small_flowers} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMALL_FLOWERS = create(key("small_flowers")); + + /** + * {@code #minecraft:smelts_to_glass} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SMELTS_TO_GLASS = create(key("smelts_to_glass")); + + /** + * {@code #minecraft:sniffer_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SNIFFER_FOOD = create(key("sniffer_food")); + + /** + * {@code #minecraft:soul_fire_base_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SOUL_FIRE_BASE_BLOCKS = create(key("soul_fire_base_blocks")); + + /** + * {@code #minecraft:spruce_logs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SPRUCE_LOGS = create(key("spruce_logs")); + + /** + * {@code #minecraft:stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STAIRS = create(key("stairs")); + + /** + * {@code #minecraft:stone_bricks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_BRICKS = create(key("stone_bricks")); + + /** + * {@code #minecraft:stone_buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_BUTTONS = create(key("stone_buttons")); + + /** + * {@code #minecraft:stone_crafting_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_CRAFTING_MATERIALS = create(key("stone_crafting_materials")); + + /** + * {@code #minecraft:stone_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STONE_TOOL_MATERIALS = create(key("stone_tool_materials")); + + /** + * {@code #minecraft:strider_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STRIDER_FOOD = create(key("strider_food")); + + /** + * {@code #minecraft:strider_tempt_items} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey STRIDER_TEMPT_ITEMS = create(key("strider_tempt_items")); + + /** + * {@code #minecraft:swords} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SWORDS = create(key("swords")); + + /** + * {@code #minecraft:terracotta} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TERRACOTTA = create(key("terracotta")); + + /** + * {@code #minecraft:trapdoors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRAPDOORS = create(key("trapdoors")); + + /** + * {@code #minecraft:trim_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRIM_MATERIALS = create(key("trim_materials")); + + /** + * {@code #minecraft:trimmable_armor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TRIMMABLE_ARMOR = create(key("trimmable_armor")); + + /** + * {@code #minecraft:turtle_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey TURTLE_FOOD = create(key("turtle_food")); + + /** + * {@code #minecraft:villager_picks_up} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VILLAGER_PICKS_UP = create(key("villager_picks_up")); + + /** + * {@code #minecraft:villager_plantable_seeds} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VILLAGER_PLANTABLE_SEEDS = create(key("villager_plantable_seeds")); + + /** + * {@code #minecraft:walls} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WALLS = create(key("walls")); + + /** + * {@code #minecraft:warped_stems} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WARPED_STEMS = create(key("warped_stems")); + + /** + * {@code #minecraft:wart_blocks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WART_BLOCKS = create(key("wart_blocks")); + + /** + * {@code #minecraft:wither_skeleton_disliked_weapons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WITHER_SKELETON_DISLIKED_WEAPONS = create(key("wither_skeleton_disliked_weapons")); + + /** + * {@code #minecraft:wolf_food} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOLF_FOOD = create(key("wolf_food")); + + /** + * {@code #minecraft:wooden_buttons} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_BUTTONS = create(key("wooden_buttons")); + + /** + * {@code #minecraft:wooden_doors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_DOORS = create(key("wooden_doors")); + + /** + * {@code #minecraft:wooden_fences} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_FENCES = create(key("wooden_fences")); + + /** + * {@code #minecraft:wooden_pressure_plates} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_PRESSURE_PLATES = create(key("wooden_pressure_plates")); + + /** + * {@code #minecraft:wooden_slabs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_SLABS = create(key("wooden_slabs")); + + /** + * {@code #minecraft:wooden_stairs} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_STAIRS = create(key("wooden_stairs")); + + /** + * {@code #minecraft:wooden_tool_materials} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_TOOL_MATERIALS = create(key("wooden_tool_materials")); + + /** + * {@code #minecraft:wooden_trapdoors} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOODEN_TRAPDOORS = create(key("wooden_trapdoors")); + + /** + * {@code #minecraft:wool} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOOL = create(key("wool")); + + /** + * {@code #minecraft:wool_carpets} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey WOOL_CARPETS = create(key("wool_carpets")); + + private ItemTypeTagKeys() { + } + + /** + * Creates a tag key for {@link ItemType} in the registry {@code minecraft:item}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.ITEM, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/PaintingVariantTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/PaintingVariantTagKeys.java new file mode 100644 index 000000000000..50dac36d1c4c --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/PaintingVariantTagKeys.java @@ -0,0 +1,50 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.Art; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#PAINTING_VARIANT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class PaintingVariantTagKeys { + /** + * {@code #minecraft:placeable} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey PLACEABLE = create(key("placeable")); + + private PaintingVariantTagKeys() { + } + + /** + * Creates a tag key for {@link Art} in the registry {@code minecraft:painting_variant}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.PAINTING_VARIANT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/StructureTagKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/StructureTagKeys.java new file mode 100644 index 000000000000..5043b933d339 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/tags/StructureTagKeys.java @@ -0,0 +1,198 @@ +package io.papermc.paper.registry.keys.tags; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import org.bukkit.MinecraftExperimental; +import org.bukkit.generator.structure.Structure; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Vanilla keys for {@link RegistryKey#STRUCTURE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.21.4") +@NullMarked +@ApiStatus.Experimental +public final class StructureTagKeys { + /** + * {@code #minecraft:cats_spawn_as_black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CATS_SPAWN_AS_BLACK = create(key("cats_spawn_as_black")); + + /** + * {@code #minecraft:cats_spawn_in} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey CATS_SPAWN_IN = create(key("cats_spawn_in")); + + /** + * {@code #minecraft:dolphin_located} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey DOLPHIN_LOCATED = create(key("dolphin_located")); + + /** + * {@code #minecraft:eye_of_ender_located} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey EYE_OF_ENDER_LOCATED = create(key("eye_of_ender_located")); + + /** + * {@code #minecraft:mineshaft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey MINESHAFT = create(key("mineshaft")); + + /** + * {@code #minecraft:ocean_ruin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey OCEAN_RUIN = create(key("ocean_ruin")); + + /** + * {@code #minecraft:on_desert_village_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_DESERT_VILLAGE_MAPS = create(key("on_desert_village_maps")); + + /** + * {@code #minecraft:on_jungle_explorer_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_JUNGLE_EXPLORER_MAPS = create(key("on_jungle_explorer_maps")); + + /** + * {@code #minecraft:on_ocean_explorer_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_OCEAN_EXPLORER_MAPS = create(key("on_ocean_explorer_maps")); + + /** + * {@code #minecraft:on_plains_village_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_PLAINS_VILLAGE_MAPS = create(key("on_plains_village_maps")); + + /** + * {@code #minecraft:on_savanna_village_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_SAVANNA_VILLAGE_MAPS = create(key("on_savanna_village_maps")); + + /** + * {@code #minecraft:on_snowy_village_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_SNOWY_VILLAGE_MAPS = create(key("on_snowy_village_maps")); + + /** + * {@code #minecraft:on_swamp_explorer_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_SWAMP_EXPLORER_MAPS = create(key("on_swamp_explorer_maps")); + + /** + * {@code #minecraft:on_taiga_village_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.TRADE_REBALANCE) + public static final TagKey ON_TAIGA_VILLAGE_MAPS = create(key("on_taiga_village_maps")); + + /** + * {@code #minecraft:on_treasure_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_TREASURE_MAPS = create(key("on_treasure_maps")); + + /** + * {@code #minecraft:on_trial_chambers_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_TRIAL_CHAMBERS_MAPS = create(key("on_trial_chambers_maps")); + + /** + * {@code #minecraft:on_woodland_explorer_maps} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey ON_WOODLAND_EXPLORER_MAPS = create(key("on_woodland_explorer_maps")); + + /** + * {@code #minecraft:ruined_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey RUINED_PORTAL = create(key("ruined_portal")); + + /** + * {@code #minecraft:shipwreck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey SHIPWRECK = create(key("shipwreck")); + + /** + * {@code #minecraft:village} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TagKey VILLAGE = create(key("village")); + + private StructureTagKeys() { + } + + /** + * Creates a tag key for {@link Structure} in the registry {@code minecraft:worldgen/structure}. + * + * @param key the tag key's key + * @return a new tag key + */ + @ApiStatus.Experimental + public static TagKey create(final Key key) { + return TagKey.create(RegistryKey.STRUCTURE, key); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/Generators.java b/paper-api-generator/src/main/java/io/papermc/generator/Generators.java new file mode 100644 index 000000000000..73e4f708258b --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/Generators.java @@ -0,0 +1,92 @@ +package io.papermc.generator; + +import io.papermc.generator.types.GeneratedKeyType; +import io.papermc.generator.types.GeneratedTagKeyType; +import io.papermc.generator.types.SourceGenerator; +import io.papermc.generator.types.goal.MobGoalGenerator; +import io.papermc.paper.registry.RegistryKey; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import org.bukkit.Art; +import org.bukkit.Fluid; +import org.bukkit.GameEvent; +import org.bukkit.JukeboxSong; +import org.bukkit.MusicInstrument; +import org.bukkit.Sound; +import org.bukkit.attribute.Attribute; +import org.bukkit.block.Biome; +import org.bukkit.block.BlockType; +import org.bukkit.block.banner.PatternType; +import org.bukkit.damage.DamageType; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Cat; +import org.bukkit.entity.Frog; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Wolf; +import org.bukkit.generator.structure.Structure; +import org.bukkit.generator.structure.StructureType; +import org.bukkit.inventory.ItemType; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.map.MapCursor; +import org.bukkit.potion.PotionEffectType; + +public interface Generators { + + SourceGenerator[] API = { + // built-ins + simpleKey("GameEventKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT, true), + simpleKey("StructureTypeKeys", StructureType.class, Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, false), + simpleKey("MobEffectKeys", PotionEffectType.class, Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, false), + simpleKey("BlockTypeKeys", BlockType.class, Registries.BLOCK, RegistryKey.BLOCK, false), + simpleKey("ItemTypeKeys", ItemType.class, Registries.ITEM, RegistryKey.ITEM, false), + simpleKey("CatVariantKeys", Cat.Type.class, Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, false), + simpleKey("FrogVariantKeys", Frog.Variant.class, Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, false), + simpleKey("VillagerProfessionKeys", Villager.Profession.class, Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, false), + simpleKey("VillagerTypeKeys", Villager.Type.class, Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, false), + simpleKey("MapDecorationTypeKeys", MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, false), + simpleKey("MenuTypeKeys", MenuType.class, Registries.MENU, RegistryKey.MENU, false), + simpleKey("AttributeKeys", Attribute.class, Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, false), + simpleKey("FluidKeys", Fluid.class, Registries.FLUID, RegistryKey.FLUID, false), + simpleKey("SoundEventKeys", Sound.class, Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, false), + + // data-driven + simpleKey("BiomeKeys", Biome.class, Registries.BIOME, RegistryKey.BIOME, true), + simpleKey("StructureKeys", Structure.class, Registries.STRUCTURE, RegistryKey.STRUCTURE, true), + simpleKey("TrimMaterialKeys", TrimMaterial.class, Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, true), + simpleKey("TrimPatternKeys", TrimPattern.class, Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, true), + simpleKey("DamageTypeKeys", DamageType.class, Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, true), + simpleKey("WolfVariantKeys", Wolf.Variant.class, Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, true), + simpleKey("EnchantmentKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, true), + simpleKey("JukeboxSongKeys", JukeboxSong.class, Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG, true), + simpleKey("BannerPatternKeys", PatternType.class, Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, true), + simpleKey("PaintingVariantKeys", Art.class, Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, true), + simpleKey("InstrumentKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT, true), + + // tags + simpleTagKey("GameEventTagKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT), + simpleTagKey("BlockTypeTagKeys", BlockType.class, Registries.BLOCK, RegistryKey.BLOCK), + simpleTagKey("ItemTypeTagKeys", ItemType.class, Registries.ITEM, RegistryKey.ITEM), + simpleTagKey("CatVariantTagKeys", Cat.Type.class, Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT), + simpleTagKey("FluidTagKeys", Fluid.class, Registries.FLUID, RegistryKey.FLUID), + + simpleTagKey("BiomeTagKeys", Biome.class, Registries.BIOME, RegistryKey.BIOME), + simpleTagKey("StructureTagKeys", Structure.class, Registries.STRUCTURE, RegistryKey.STRUCTURE), + simpleTagKey("DamageTypeTagKeys", DamageType.class, Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE), + simpleTagKey("EnchantmentTagKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT), + simpleTagKey("BannerPatternTagKeys", PatternType.class, Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN), + simpleTagKey("PaintingVariantTagKeys", Art.class, Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT), + simpleTagKey("InstrumentTagKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT), + new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai") + }; + + private static SourceGenerator simpleKey(final String className, final Class apiType, final ResourceKey> registryKey, final RegistryKey apiRegistryKey, final boolean publicCreateKeyMethod) { + return new GeneratedKeyType<>(className, apiType, "io.papermc.paper.registry.keys", registryKey, apiRegistryKey, publicCreateKeyMethod); + } + + private static SourceGenerator simpleTagKey(final String className, final Class apiType, final ResourceKey> registryKey, final RegistryKey apiRegistryKey) { + return new GeneratedTagKeyType<>(className, apiType, "io.papermc.paper.registry.keys.tags", registryKey, apiRegistryKey, true); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/Main.java b/paper-api-generator/src/main/java/io/papermc/generator/Main.java new file mode 100644 index 000000000000..129009f519f1 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/Main.java @@ -0,0 +1,93 @@ +package io.papermc.generator; + +import com.google.common.util.concurrent.MoreExecutors; +import com.mojang.logging.LogUtils; +import io.papermc.generator.types.SourceGenerator; +import io.papermc.generator.utils.TagCollector; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import net.minecraft.SharedConstants; +import net.minecraft.commands.Commands; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.server.Bootstrap; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.repository.Pack; +import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.server.packs.repository.ServerPacksSource; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import net.minecraft.tags.TagKey; +import net.minecraft.tags.TagLoader; +import net.minecraft.world.flag.FeatureFlags; +import org.apache.commons.io.file.PathUtils; +import org.slf4j.Logger; + +public final class Main { + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final RegistryAccess.Frozen REGISTRY_ACCESS; + public static final Map, String> EXPERIMENTAL_TAGS; + + static { + SharedConstants.tryDetectVersion(); + Bootstrap.bootStrap(); + Bootstrap.validate(); + + final PackRepository resourceRepository = ServerPacksSource.createVanillaTrustedRepository(); + resourceRepository.reload(); + final MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().map(Pack::open).toList()); + LayeredRegistryAccess layers = RegistryLayer.createRegistryAccess(); + final List> pendingTags = TagLoader.loadTagsForExistingRegistries(resourceManager, layers.getLayer(RegistryLayer.STATIC)); + final List> worldGenLayer = TagLoader.buildUpdatedLookups(layers.getAccessForLoading(RegistryLayer.WORLDGEN), pendingTags); + final RegistryAccess.Frozen frozenWorldgenRegistries = RegistryDataLoader.load(resourceManager, worldGenLayer, RegistryDataLoader.WORLDGEN_REGISTRIES); + layers = layers.replaceFrom(RegistryLayer.WORLDGEN, frozenWorldgenRegistries); + REGISTRY_ACCESS = layers.compositeAccess().freeze(); + final ReloadableServerResources reloadableServerResources = ReloadableServerResources.loadResources( + resourceManager, + layers, + pendingTags, + FeatureFlags.VANILLA_SET, + Commands.CommandSelection.DEDICATED, + 0, + MoreExecutors.directExecutor(), + MoreExecutors.directExecutor() + ).join(); + reloadableServerResources.updateStaticRegistryTags(); + EXPERIMENTAL_TAGS = TagCollector.grabExperimental(resourceManager); + } + + private Main() { + } + + public static void main(final String[] args) { + LOGGER.info("Running API generators..."); + generate(Paths.get(args[0]), Generators.API); + // LOGGER.info("Running Server generators..."); + // generate(Paths.get(args[1]), Generators.SERVER); + } + + private static void generate(Path output, SourceGenerator[] generators) { + try { + if (Files.exists(output)) { + PathUtils.deleteDirectory(output); + } + Files.createDirectories(output); + + for (final SourceGenerator generator : generators) { + generator.writeToFile(output); + } + + LOGGER.info("Files written to {}", output.toAbsolutePath()); + } catch (final Exception ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java new file mode 100644 index 000000000000..4ef3d3af036d --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java @@ -0,0 +1,207 @@ +package io.papermc.generator.types; + +import com.google.common.collect.Sets; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.Main; +import io.papermc.generator.utils.Annotations; +import io.papermc.generator.utils.CollectingContext; +import io.papermc.generator.utils.Formatting; +import io.papermc.generator.utils.Javadocs; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.lang.model.SourceVersion; +import net.kyori.adventure.key.Key; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.registries.VanillaRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.flag.FeatureElement; +import net.minecraft.world.flag.FeatureFlags; +import org.bukkit.MinecraftExperimental; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; + +import static com.squareup.javapoet.TypeSpec.classBuilder; +import static io.papermc.generator.utils.Annotations.EXPERIMENTAL_API_ANNOTATION; +import static io.papermc.generator.utils.Annotations.experimentalAnnotations; +import static java.util.Objects.requireNonNull; +import static javax.lang.model.element.Modifier.FINAL; +import static javax.lang.model.element.Modifier.PRIVATE; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +@DefaultQualifier(NonNull.class) +public class GeneratedKeyType extends SimpleGenerator { + + private static final Map>, RegistrySetBuilder.RegistryBootstrap> VANILLA_REGISTRY_ENTRIES = VanillaRegistries.BUILDER.entries.stream() + .collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap)); + + private static final Map>, RegistrySetBuilder.RegistryBootstrap> EXPERIMENTAL_REGISTRY_ENTRIES = Map.of(); // Update for Experimental API + private static final Map, String> REGISTRY_KEY_FIELD_NAMES; + static { + final Map, String> map = new HashMap<>(); + try { + for (final Field field : RegistryKey.class.getFields()) { + if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || field.getType() != RegistryKey.class) { + continue; + } + map.put((RegistryKey) field.get(null), field.getName()); + } + REGISTRY_KEY_FIELD_NAMES = Map.copyOf(map); + } catch (final ReflectiveOperationException ex) { + throw new RuntimeException(ex); + } + } + + private static final String CREATE_JAVADOC = """ + Creates a key for {@link $T} in the registry {@code $L}. + + @param key the value's key in the registry + @return a new typed key + """; + + private final Class apiType; + private final ResourceKey> registryKey; + private final RegistryKey apiRegistryKey; + private final boolean publicCreateKeyMethod; + + public GeneratedKeyType(final String keysClassName, final Class apiType, final String pkg, final ResourceKey> registryKey, final RegistryKey apiRegistryKey, final boolean publicCreateKeyMethod) { + super(keysClassName, pkg); + this.apiType = apiType; + this.registryKey = registryKey; + this.apiRegistryKey = apiRegistryKey; + this.publicCreateKeyMethod = publicCreateKeyMethod; + } + + private MethodSpec.Builder createMethod(final TypeName returnType) { + final TypeName keyType = TypeName.get(Key.class); + + final ParameterSpec keyParam = ParameterSpec.builder(keyType, "key", FINAL).build(); + final MethodSpec.Builder create = MethodSpec.methodBuilder("create") + .addModifiers(this.publicCreateKeyMethod ? PUBLIC : PRIVATE, STATIC) + .addParameter(keyParam) + .addCode("return $T.create($T.$L, $N);", TypedKey.class, RegistryKey.class, requireNonNull(REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey), "Missing field for " + this.apiRegistryKey), keyParam) + .returns(returnType); + if (this.publicCreateKeyMethod) { + create.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO remove once not experimental + create.addJavadoc(CREATE_JAVADOC, this.apiType, this.registryKey.location().toString()); + } + return create; + } + + private TypeSpec.Builder keyHolderType() { + return classBuilder(this.className) + .addModifiers(PUBLIC, FINAL) + .addJavadoc(Javadocs.getVersionDependentClassHeader("{@link $T#$L}"), RegistryKey.class, REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey)) + .addAnnotations(Annotations.CLASS_HEADER) + .addMethod(MethodSpec.constructorBuilder() + .addModifiers(PRIVATE) + .build() + ); + } + + @Deprecated + private static final Map JUKEBOX_SONG_NAMES = Map.of( + "5", "FIVE", + "11", "ELEVEN", + "13", "THIRTEEN" + ); + + @Override + protected TypeSpec getTypeSpec() { + final TypeName typedKey = ParameterizedTypeName.get(TypedKey.class, this.apiType); + + final TypeSpec.Builder typeBuilder = this.keyHolderType(); + final MethodSpec.Builder createMethod = this.createMethod(typedKey); + + final Registry registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey); + final Set> experimental = this.collectExperimentalKeys(registry); + + boolean allExperimental = true; + for (final Holder.Reference reference : registry.listElements().sorted(Formatting.alphabeticKeyOrder(reference -> reference.key().location().getPath())).toList()) { + final ResourceKey key = reference.key(); + final String keyPath = key.location().getPath(); + String fieldName = Formatting.formatKeyAsField(keyPath); + if (!SourceVersion.isIdentifier(fieldName) && this.registryKey.equals(Registries.JUKEBOX_SONG) && JUKEBOX_SONG_NAMES.containsKey(fieldName)) { + fieldName = JUKEBOX_SONG_NAMES.get(fieldName); + } + + final FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL) + .initializer("$N(key($S))", createMethod.build(), keyPath) + .addJavadoc(Javadocs.getVersionDependentField("{@code $L}"), key.location().toString()); + if (experimental.contains(key)) { + fieldBuilder.addAnnotations(experimentalAnnotations(null)); // Update for Experimental API + } else { + allExperimental = false; + } + typeBuilder.addField(fieldBuilder.build()); + } + if (allExperimental) { + typeBuilder.addAnnotations(experimentalAnnotations(null)); // Update for Experimental API + createMethod.addAnnotations(experimentalAnnotations(null)); // Update for Experimental API + } else { + typeBuilder.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO experimental API + } + return typeBuilder.addMethod(createMethod.build()).build(); + } + + // todo at some point this should be per feature data pack not all merged + private Set> collectExperimentalKeys(final Registry registry) { + if (FeatureElement.FILTERED_REGISTRIES.contains(registry.key())) { + return this.collectExperimentalKeysBuiltIn(registry); + } else { + return this.collectExperimentalKeysDataDriven(registry); + } + } + + private Set> collectExperimentalKeysBuiltIn(final Registry registry) { + final HolderLookup.RegistryLookup filteredLookup = registry.filterElements(v -> { + return v instanceof final FeatureElement featureElement && FeatureFlags.isExperimental(featureElement.requiredFeatures()); // Update for Experimental API + }); + return filteredLookup.listElementIds().collect(Collectors.toUnmodifiableSet()); + } + + @SuppressWarnings("unchecked") + private Set> collectExperimentalKeysDataDriven(final Registry registry) { + final RegistrySetBuilder.@Nullable RegistryBootstrap experimentalBootstrap = (RegistrySetBuilder.RegistryBootstrap) EXPERIMENTAL_REGISTRY_ENTRIES.get(this.registryKey); + if (experimentalBootstrap == null) { + return Collections.emptySet(); + } + final Set> experimental = Collections.newSetFromMap(new IdentityHashMap<>()); + final CollectingContext experimentalCollector = new CollectingContext<>(experimental, registry); + experimentalBootstrap.run(experimentalCollector); + + final RegistrySetBuilder.@Nullable RegistryBootstrap vanillaBootstrap = (RegistrySetBuilder.RegistryBootstrap) VANILLA_REGISTRY_ENTRIES.get(this.registryKey); + if (vanillaBootstrap != null) { + final Set> vanilla = Collections.newSetFromMap(new IdentityHashMap<>()); + final CollectingContext vanillaCollector = new CollectingContext<>(vanilla, registry); + vanillaBootstrap.run(vanillaCollector); + return Sets.difference(experimental, vanilla); + } + return experimental; + } + + @Override + protected JavaFile.Builder file(final JavaFile.Builder builder) { + return builder + .addStaticImport(Key.class, "key"); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedTagKeyType.java b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedTagKeyType.java new file mode 100644 index 000000000000..60e15ea64a82 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedTagKeyType.java @@ -0,0 +1,138 @@ +package io.papermc.generator.types; + +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.Main; +import io.papermc.generator.utils.Annotations; +import io.papermc.generator.utils.Formatting; +import io.papermc.generator.utils.Javadocs; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.tag.TagKey; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import net.kyori.adventure.key.Key; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.bukkit.MinecraftExperimental; + +import static com.squareup.javapoet.TypeSpec.classBuilder; +import static io.papermc.generator.utils.Annotations.EXPERIMENTAL_API_ANNOTATION; +import static io.papermc.generator.utils.Annotations.experimentalAnnotations; +import static java.util.Objects.requireNonNull; +import static javax.lang.model.element.Modifier.FINAL; +import static javax.lang.model.element.Modifier.PRIVATE; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +public class GeneratedTagKeyType extends SimpleGenerator { + + private static final Map, String> REGISTRY_KEY_FIELD_NAMES; + static { + final Map, String> map = new HashMap<>(); + try { + for (final Field field : RegistryKey.class.getFields()) { + if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || field.getType() != RegistryKey.class) { + continue; + } + map.put((RegistryKey) field.get(null), field.getName()); + } + REGISTRY_KEY_FIELD_NAMES = Map.copyOf(map); + } catch (final ReflectiveOperationException ex) { + throw new RuntimeException(ex); + } + } + + private static final String CREATE_JAVADOC = """ + Creates a tag key for {@link $T} in the registry {@code $L}. + + @param key the tag key's key + @return a new tag key + """; + + private final Class apiType; + private final ResourceKey> registryKey; + private final RegistryKey apiRegistryKey; + private final boolean publicCreateKeyMethod; + + public GeneratedTagKeyType(final String keysClassName, final Class apiType, final String pkg, final ResourceKey> registryKey, final RegistryKey apiRegistryKey, final boolean publicCreateKeyMethod) { + super(keysClassName, pkg); + this.apiType = apiType; + this.registryKey = registryKey; + this.apiRegistryKey = apiRegistryKey; + this.publicCreateKeyMethod = publicCreateKeyMethod; + } + + private MethodSpec.Builder createMethod(final TypeName returnType) { + final TypeName keyType = TypeName.get(Key.class); + + final ParameterSpec keyParam = ParameterSpec.builder(keyType, "key", FINAL).build(); + final MethodSpec.Builder create = MethodSpec.methodBuilder("create") + .addModifiers(this.publicCreateKeyMethod ? PUBLIC : PRIVATE, STATIC) + .addParameter(keyParam) + .addCode("return $T.create($T.$L, $N);", TagKey.class, RegistryKey.class, requireNonNull(REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey), "Missing field for " + this.apiRegistryKey), keyParam) + .returns(returnType); + if (this.publicCreateKeyMethod) { + create.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO remove once not experimental + create.addJavadoc(CREATE_JAVADOC, this.apiType, this.registryKey.location().toString()); + } + return create; + } + + private TypeSpec.Builder keyHolderType() { + return classBuilder(this.className) + .addModifiers(PUBLIC, FINAL) + .addJavadoc(Javadocs.getVersionDependentClassHeader("{@link $T#$L}"), RegistryKey.class, REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey)) + .addAnnotations(Annotations.CLASS_HEADER) + .addMethod(MethodSpec.constructorBuilder() + .addModifiers(PRIVATE) + .build() + ); + } + + @Override + protected TypeSpec getTypeSpec() { + final TypeName tagKey = ParameterizedTypeName.get(TagKey.class, this.apiType); + + final TypeSpec.Builder typeBuilder = this.keyHolderType(); + final MethodSpec.Builder createMethod = this.createMethod(tagKey); + + final Registry registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey); + + final AtomicBoolean allExperimental = new AtomicBoolean(true); + registry.listTagIds().sorted(Formatting.alphabeticKeyOrder(nmsTagKey -> nmsTagKey.location().getPath())).forEach(nmsTagKey -> { + final String fieldName = Formatting.formatKeyAsField(nmsTagKey.location().getPath()); + final FieldSpec.Builder fieldBuilder = FieldSpec.builder(tagKey, fieldName, PUBLIC, STATIC, FINAL) + .initializer("$N(key($S))", createMethod.build(), nmsTagKey.location().getPath()) + .addJavadoc(Javadocs.getVersionDependentField("{@code $L}"), "#" + nmsTagKey.location()); + final String featureFlagName = Main.EXPERIMENTAL_TAGS.get(nmsTagKey); + if (featureFlagName != null) { + fieldBuilder.addAnnotations(experimentalAnnotations(MinecraftExperimental.Requires.valueOf(featureFlagName.toUpperCase(Locale.ENGLISH)))); // Update for Experimental API + } else { + allExperimental.set(false); + } + typeBuilder.addField(fieldBuilder.build()); + }); + if (allExperimental.get()) { + typeBuilder.addAnnotations(experimentalAnnotations(null)); // Update for Experimental API + createMethod.addAnnotations(experimentalAnnotations(null)); // Update for Experimental API + } else { + typeBuilder.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO experimental API + } + return typeBuilder.addMethod(createMethod.build()).build(); + } + + @Override + protected JavaFile.Builder file(final JavaFile.Builder builder) { + return builder + .addStaticImport(Key.class, "key"); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java new file mode 100644 index 000000000000..3608b449f821 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java @@ -0,0 +1,34 @@ +package io.papermc.generator.types; + +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; + +public abstract class SimpleGenerator implements SourceGenerator { + + protected final String className; + protected final String packageName; + + protected SimpleGenerator(String className, String packageName) { + this.className = className; + this.packageName = packageName; + } + + protected abstract TypeSpec getTypeSpec(); + + protected abstract JavaFile.Builder file(JavaFile.Builder builder); + + @Override + public void writeToFile(Path parent) throws IOException { + + JavaFile.Builder builder = JavaFile.builder(this.packageName, this.getTypeSpec()); + this.file(builder) + .indent(" ") + .skipJavaLangImports(true); + + builder.build().writeTo(parent, StandardCharsets.UTF_8); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java new file mode 100644 index 000000000000..2d550fa4218c --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java @@ -0,0 +1,9 @@ +package io.papermc.generator.types; + +import java.io.IOException; +import java.nio.file.Path; + +public interface SourceGenerator { + + void writeToFile(Path parent) throws IOException; +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java new file mode 100644 index 000000000000..abcc93e61acb --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java @@ -0,0 +1,100 @@ +package io.papermc.generator.types.goal; + +import com.destroystokyo.paper.entity.ai.GoalKey; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeVariableName; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; +import io.papermc.generator.types.SimpleGenerator; +import io.papermc.generator.utils.Annotations; +import io.papermc.generator.utils.Formatting; +import io.papermc.generator.utils.Javadocs; +import java.util.Comparator; +import java.util.List; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.WrappedGoal; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Mob; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.jetbrains.annotations.Nullable; + +import static javax.lang.model.element.Modifier.FINAL; +import static javax.lang.model.element.Modifier.PRIVATE; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +@DefaultQualifier(NonNull.class) +public class MobGoalGenerator extends SimpleGenerator { + + private static final String CLASS_HEADER = Javadocs.getVersionDependentClassHeader("Mob Goals"); + + public MobGoalGenerator(final String keysClassName, final String pkg) { + super(keysClassName, pkg); + } + + @Override + protected TypeSpec getTypeSpec() { + TypeVariableName type = TypeVariableName.get("T", Mob.class); + TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(this.className) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(com.destroystokyo.paper.entity.ai.Goal.class), type)) + .addModifiers(PUBLIC) + .addTypeVariable(type) + .addAnnotations(Annotations.CLASS_HEADER) + .addJavadoc(CLASS_HEADER); + + TypeName mobType = ParameterizedTypeName.get(ClassName.get(Class.class), type); + TypeName keyType = TypeName.get(String.class); + + ParameterSpec keyParam = ParameterSpec.builder(keyType, "key", FINAL).build(); + ParameterSpec typeParam = ParameterSpec.builder(mobType, "type", FINAL).build(); + MethodSpec.Builder createMethod = MethodSpec.methodBuilder("create") + .addModifiers(PRIVATE, STATIC) + .addParameter(keyParam) + .addParameter(typeParam) + .addCode("return $T.of($N, $T.minecraft($N));", GoalKey.class, typeParam, NamespacedKey.class, keyParam) + .addTypeVariable(type) + .returns(ParameterizedTypeName.get(ClassName.get(GoalKey.class), type)); + + List> classes; + try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { + classes = scanResult.getSubclasses(Goal.class.getName()).loadClasses(Goal.class); + } + + List> vanillaNames = classes.stream() + .filter(clazz -> !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) + .filter(clazz -> !WrappedGoal.class.equals(clazz)) // TODO - properly fix + .map(goalClass -> MobGoalNames.getKey(goalClass.getName(), goalClass)) + .filter((key) -> !MobGoalNames.isIgnored(key.getNamespacedKey().getKey())) + .sorted(Comparator., String>comparing(o -> o.getEntityClass().getSimpleName()) + .thenComparing(vanillaGoalKey -> vanillaGoalKey.getNamespacedKey().getKey()) + ) + .toList(); + + + for (final GoalKey goalKey : vanillaNames) { + TypeName typedKey = ParameterizedTypeName.get(GoalKey.class, goalKey.getEntityClass()); + NamespacedKey key = goalKey.getNamespacedKey(); + + String keyPath = key.getKey(); + String fieldName = Formatting.formatKeyAsField(keyPath); + FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL) + .initializer("$N($S, $T.class)", createMethod.build(), keyPath, goalKey.getEntityClass()); + typeBuilder.addField(fieldBuilder.build()); + } + + return typeBuilder.addMethod(createMethod.build()).build(); + } + + @Override + protected JavaFile.Builder file(JavaFile.Builder builder) { + return builder; + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java new file mode 100644 index 000000000000..047b9af5f716 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java @@ -0,0 +1,336 @@ +package io.papermc.generator.types.goal; + +import com.destroystokyo.paper.entity.RangedEntity; +import com.destroystokyo.paper.entity.ai.GoalKey; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import net.minecraft.world.entity.FlyingMob; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ambient.AmbientCreature; +import net.minecraft.world.entity.animal.AbstractFish; +import net.minecraft.world.entity.animal.AbstractGolem; +import net.minecraft.world.entity.animal.AbstractSchoolingFish; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.ShoulderRidingEntity; +import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.entity.animal.WaterAnimal; +import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.entity.monster.AbstractIllager; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.PatrollingMonster; +import net.minecraft.world.entity.monster.RangedAttackMob; +import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.monster.piglin.AbstractPiglin; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.AbstractSkeleton; +import org.bukkit.entity.AbstractVillager; +import org.bukkit.entity.Ageable; +import org.bukkit.entity.Ambient; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Bee; +import org.bukkit.entity.Blaze; +import org.bukkit.entity.Cat; +import org.bukkit.entity.CaveSpider; +import org.bukkit.entity.ChestedHorse; +import org.bukkit.entity.Chicken; +import org.bukkit.entity.Cod; +import org.bukkit.entity.Cow; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Dolphin; +import org.bukkit.entity.Donkey; +import org.bukkit.entity.Drowned; +import org.bukkit.entity.ElderGuardian; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Enderman; +import org.bukkit.entity.Endermite; +import org.bukkit.entity.Evoker; +import org.bukkit.entity.Fish; +import org.bukkit.entity.Flying; +import org.bukkit.entity.Fox; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.Giant; +import org.bukkit.entity.Golem; +import org.bukkit.entity.Guardian; +import org.bukkit.entity.Hoglin; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Husk; +import org.bukkit.entity.Illager; +import org.bukkit.entity.Illusioner; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Llama; +import org.bukkit.entity.MagmaCube; +import org.bukkit.entity.Mob; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Mule; +import org.bukkit.entity.MushroomCow; +import org.bukkit.entity.Ocelot; +import org.bukkit.entity.Panda; +import org.bukkit.entity.Parrot; +import org.bukkit.entity.Phantom; +import org.bukkit.entity.Pig; +import org.bukkit.entity.PigZombie; +import org.bukkit.entity.Piglin; +import org.bukkit.entity.PiglinAbstract; +import org.bukkit.entity.PiglinBrute; +import org.bukkit.entity.Pillager; +import org.bukkit.entity.PolarBear; +import org.bukkit.entity.PufferFish; +import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Raider; +import org.bukkit.entity.Ravager; +import org.bukkit.entity.Salmon; +import org.bukkit.entity.Sheep; +import org.bukkit.entity.Shulker; +import org.bukkit.entity.Silverfish; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.SkeletonHorse; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Snowman; +import org.bukkit.entity.Spellcaster; +import org.bukkit.entity.Spider; +import org.bukkit.entity.Squid; +import org.bukkit.entity.Stray; +import org.bukkit.entity.Strider; +import org.bukkit.entity.Tameable; +import org.bukkit.entity.TraderLlama; +import org.bukkit.entity.TropicalFish; +import org.bukkit.entity.Turtle; +import org.bukkit.entity.Vex; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Vindicator; +import org.bukkit.entity.WanderingTrader; +import org.bukkit.entity.WaterMob; +import org.bukkit.entity.Witch; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkeleton; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.Zoglin; +import org.bukkit.entity.Zombie; +import org.bukkit.entity.ZombieHorse; +import org.bukkit.entity.ZombieVillager; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +public class MobGoalNames { + + private static final Map, Class> entityClassCache = new HashMap<>(); + public static final Map, Class> bukkitMap = new HashMap<>(); + + + static { + // + bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); + bukkitMap.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class); + bukkitMap.put(AmbientCreature.class, Ambient.class); + bukkitMap.put(Animal.class, Animals.class); + bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); + bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); + bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); + bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); + bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); + bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); + bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); + bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); + bukkitMap.put(PathfinderMob.class, Creature.class); + bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); + bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); + bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); + bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); + bukkitMap.put(EnderMan.class, Enderman.class); + bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); + bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); + bukkitMap.put(AbstractFish.class, Fish.class); + bukkitMap.put(AbstractSchoolingFish.class, io.papermc.paper.entity.SchoolableFish.class); + bukkitMap.put(FlyingMob.class, Flying.class); + bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); + bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); + bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); + bukkitMap.put(AbstractGolem.class, Golem.class); + bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); + bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); + bukkitMap.put(AbstractChestedHorse.class, ChestedHorse.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); + bukkitMap.put(net.minecraft.world.entity.animal.camel.Camel.class, org.bukkit.entity.Camel.class); + bukkitMap.put(AbstractIllager.class, Illager.class); + bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); + bukkitMap.put(SpellcasterIllager.class, Spellcaster.class); + bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); + bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); + bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); + bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); + bukkitMap.put(PatrollingMonster.class, Raider.class); // close enough + bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); + bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); + bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); + bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); + bukkitMap.put(ShoulderRidingEntity.class, Parrot.class); // close enough + bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); + bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); + bukkitMap.put(ZombifiedPiglin.class, PigZombie.class); + bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); + bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); + bukkitMap.put(Pufferfish.class, PufferFish.class); + bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); + bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); + bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); + bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); + bukkitMap.put(net.minecraft.world.entity.animal.Sheep.class, Sheep.class); + bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); + bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); + bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); + bukkitMap.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class); + bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); + bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); + bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); + bukkitMap.put(SnowGolem.class, Snowman.class); + bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); + bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); + bukkitMap.put(TamableAnimal.class, Tameable.class); + bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); + bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); + bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); + bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); + bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); + bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); + bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); + bukkitMap.put(WaterAnimal.class, WaterMob.class); + bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); + bukkitMap.put(WitherBoss.class, Wither.class); + bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.class); + bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); + bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); + bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); + bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); + bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); + bukkitMap.put(AbstractPiglin.class, PiglinAbstract.class); + bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); + bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); + bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); + bukkitMap.put(net.minecraft.world.entity.GlowSquid.class, org.bukkit.entity.GlowSquid.class); + bukkitMap.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, org.bukkit.entity.Axolotl.class); + bukkitMap.put(net.minecraft.world.entity.animal.goat.Goat.class, org.bukkit.entity.Goat.class); + bukkitMap.put(net.minecraft.world.entity.animal.frog.Frog.class, org.bukkit.entity.Frog.class); + bukkitMap.put(net.minecraft.world.entity.animal.frog.Tadpole.class, org.bukkit.entity.Tadpole.class); + bukkitMap.put(net.minecraft.world.entity.monster.warden.Warden.class, org.bukkit.entity.Warden.class); + bukkitMap.put(net.minecraft.world.entity.animal.allay.Allay.class, org.bukkit.entity.Allay.class); + bukkitMap.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, org.bukkit.entity.Sniffer.class); + bukkitMap.put(net.minecraft.world.entity.monster.breeze.Breeze.class, org.bukkit.entity.Breeze.class); + bukkitMap.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, org.bukkit.entity.Armadillo.class); + bukkitMap.put(net.minecraft.world.entity.monster.Bogged.class, org.bukkit.entity.Bogged.class); + bukkitMap.put(net.minecraft.world.entity.monster.creaking.Creaking.class, org.bukkit.entity.Creaking.class); + bukkitMap.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, org.bukkit.entity.Squid.class); // close enough + // + } + + private static final BiMap deobfuscationMap = HashBiMap.create(); + static final Set ignored = new HashSet<>(); + + static { + deobfuscationMap.put("abstract_skeleton_1", "abstract_skeleton_melee"); + + ignored.add("goal_selector_1"); + ignored.add("goal_selector_2"); + ignored.add("selector_1"); + ignored.add("selector_2"); + ignored.add("wrapped"); + } + + public static String getUsableName(String name) { + final String original = name; + name = name.substring(name.lastIndexOf(".") + 1); + boolean flag = false; + // inner classes + if (name.contains("$")) { + String cut = name.substring(name.indexOf("$") + 1); + if (cut.length() <= 2) { + name = name.replace("Entity", ""); + name = name.replace("$", "_"); + flag = true; + } else { + // mapped, wooo + name = cut; + } + } + + name = name.replace("PathfinderGoal", ""); + name = name.replace("TargetGoal", ""); + name = name.replace("Goal", ""); + StringBuilder sb = new StringBuilder(); + for (char c : name.toCharArray()) { + if (c >= 'A' && c <= 'Z') { + sb.append("_"); + sb.append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + name = sb.toString(); + name = name.replaceFirst("_", ""); + + if (flag && !deobfuscationMap.containsKey(name.toLowerCase(Locale.ROOT)) && !ignored.contains(name)) { + System.out.println("need to map " + original + " (" + name.toLowerCase(Locale.ROOT) + ")"); + } + + // did we rename this key? + return deobfuscationMap.getOrDefault(name, name); + } + + public static boolean isIgnored(String name) { + return ignored.contains(name); + } + + + public static GoalKey getKey(String clazzName, Class goalClass) { + String name = getUsableName(clazzName); + if (MobGoalNames.isIgnored(name)) { + //noinspection unchecked + return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); + } + return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); + } + + public static Class getEntity(Class goalClass) { + //noinspection unchecked + return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { + for (Constructor ctor : key.getDeclaredConstructors()) { + for (int i = 0; i < ctor.getParameterCount(); i++) { + Class param = ctor.getParameterTypes()[i]; + if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { + //noinspection unchecked + return toBukkitClass((Class) param); + } else if (RangedAttackMob.class.isAssignableFrom(param)) { + return RangedEntity.class; + } + } + } + throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? + }); + } + + public static Class toBukkitClass(Class nmsClass) { + Class bukkitClass = bukkitMap.get(nmsClass); + if (bukkitClass == null) { + throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? + } + return bukkitClass; + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java new file mode 100644 index 000000000000..977e4a133409 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java @@ -0,0 +1,65 @@ +package io.papermc.generator.utils; + +import com.squareup.javapoet.AnnotationSpec; +import java.util.ArrayList; +import java.util.List; + +import io.papermc.paper.generated.GeneratedFrom; +import net.minecraft.SharedConstants; +import org.bukkit.MinecraftExperimental; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; + +public final class Annotations { + + public static List experimentalAnnotations(final MinecraftExperimental.@Nullable Requires requiredFeatureFlag) { + final List annotationSpecs = new ArrayList<>(); + annotationSpecs.add(AnnotationSpec.builder(ApiStatus.Experimental.class).build()); + if (requiredFeatureFlag != null) { + annotationSpecs.add(AnnotationSpec.builder(MinecraftExperimental.class) + .addMember("value", "$T.$L", MinecraftExperimental.Requires.class, requiredFeatureFlag.name()) + .build()); + } else { + annotationSpecs.add(AnnotationSpec.builder(MinecraftExperimental.class).build()); + } + return annotationSpecs; + } + + public static AnnotationSpec deprecatedVersioned(final @Nullable String version, final boolean forRemoval) { + final AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(Deprecated.class); + if (forRemoval) { + annotationSpec.addMember("forRemoval", "$L", true); + } + if (version != null) { + annotationSpec.addMember("since", "$S", version); + } + + return annotationSpec.build(); + } + + public static AnnotationSpec scheduledRemoval(final @Nullable String version) { + return AnnotationSpec.builder(ApiStatus.ScheduledForRemoval.class) + .addMember("inVersion", "$S", version) + .build(); + } + + @ApiStatus.Experimental + public static final AnnotationSpec EXPERIMENTAL_API_ANNOTATION = AnnotationSpec.builder(ApiStatus.Experimental.class).build(); + public static final AnnotationSpec NULL_MARKED = AnnotationSpec.builder(NullMarked.class).build(); + private static final AnnotationSpec SUPPRESS_WARNINGS = AnnotationSpec.builder(SuppressWarnings.class) + .addMember("value", "$S", "unused") + .addMember("value", "$S", "SpellCheckingInspection") + .build(); + private static final AnnotationSpec GENERATED_FROM = AnnotationSpec.builder(GeneratedFrom.class) + .addMember("value", "$S", SharedConstants.getCurrentVersion().getName()) + .build(); + public static final Iterable CLASS_HEADER = List.of( + SUPPRESS_WARNINGS, + GENERATED_FROM, + NULL_MARKED + ); + + private Annotations() { + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java new file mode 100644 index 000000000000..c2fbaa2a0518 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java @@ -0,0 +1,28 @@ +package io.papermc.generator.utils; + +import com.mojang.serialization.Lifecycle; +import io.papermc.generator.Main; +import java.util.Set; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.Registry; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public record CollectingContext(Set> registered, + Registry registry) implements BootstrapContext { + + @Override + public Holder.Reference register(final ResourceKey resourceKey, final @NonNull T t, final Lifecycle lifecycle) { + this.registered.add(resourceKey); + return Holder.Reference.createStandAlone(this.registry, resourceKey); + } + + @Override + public HolderGetter lookup(final ResourceKey> resourceKey) { + return Main.REGISTRY_ACCESS.lookupOrThrow(resourceKey); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java new file mode 100644 index 000000000000..b703a32455b3 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java @@ -0,0 +1,59 @@ +package io.papermc.generator.utils; + +import java.util.Optional; +import org.apache.commons.lang3.math.NumberUtils; +import java.util.Comparator; +import java.util.Locale; +import java.util.OptionalInt; +import java.util.function.Function; +import java.util.regex.Pattern; + +public final class Formatting { + + private static final Pattern ILLEGAL_FIELD_CHARACTERS = Pattern.compile("[.-/]"); + + public static String formatKeyAsField(String path) { + return ILLEGAL_FIELD_CHARACTERS.matcher(path.toUpperCase(Locale.ROOT)).replaceAll("_"); + } + + public static Optional formatTagKey(String tagDir, String resourcePath) { + int tagsIndex = resourcePath.indexOf(tagDir); + int dotIndex = resourcePath.lastIndexOf('.'); + if (tagsIndex == -1 || dotIndex == -1) { + return Optional.empty(); + } + return Optional.of(resourcePath.substring(tagsIndex + tagDir.length() + 1, dotIndex)); // namespace/tags/registry_key/[tag_key].json + } + + public static Comparator ALPHABETIC_KEY_ORDER = alphabeticKeyOrder(path -> path); + + public static Comparator alphabeticKeyOrder(Function mapper) { + return (o1, o2) -> { + String path1 = mapper.apply(o1); + String path2 = mapper.apply(o2); + + OptionalInt trailingInt1 = tryParseTrailingInt(path1); + OptionalInt trailingInt2 = tryParseTrailingInt(path2); + + if (trailingInt1.isPresent() && trailingInt2.isPresent()) { + return Integer.compare(trailingInt1.getAsInt(), trailingInt2.getAsInt()); + } + + return path1.compareTo(path2); + }; + } + + private static OptionalInt tryParseTrailingInt(String path) { + int delimiterIndex = path.lastIndexOf('_'); + if (delimiterIndex != -1) { + String score = path.substring(delimiterIndex + 1); + if (NumberUtils.isDigits(score)) { + return OptionalInt.of(Integer.parseInt(score)); + } + } + return OptionalInt.empty(); + } + + private Formatting() { + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/Javadocs.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/Javadocs.java new file mode 100644 index 000000000000..33536c8311d6 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/Javadocs.java @@ -0,0 +1,27 @@ +package io.papermc.generator.utils; + +public final class Javadocs { + + public static String getVersionDependentClassHeader(String headerIdentifier) { + return """ + Vanilla keys for %s. + + @apiNote The fields provided here are a direct representation of + what is available from the vanilla game source. They may be + changed (including removals) on any Minecraft version + bump, so cross-version compatibility is not provided on the + same level as it is on most of the other API. + """.formatted(headerIdentifier); + } + + public static String getVersionDependentField(String headerIdentifier) { + return """ + %s + + @apiNote This field is version-dependant and may be removed in future Minecraft versions + """.formatted(headerIdentifier); + } + + private Javadocs() { + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/TagCollector.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/TagCollector.java new file mode 100644 index 000000000000..546e136b4a74 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/TagCollector.java @@ -0,0 +1,79 @@ +package io.papermc.generator.utils; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.mojang.logging.LogUtils; +import io.papermc.generator.Main; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.packs.PackResources; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.repository.BuiltInPackSource; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import net.minecraft.tags.TagKey; +import org.slf4j.Logger; + +// collect all the tags by grabbing the json from the data-packs +// another (probably) way is to hook into the data generator like the typed keys generator +public final class TagCollector { + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static Map, String> grabExperimental(final MultiPackResourceManager resourceManager) { + Map, String> result = new IdentityHashMap<>(); + + // collect all vanilla tags + Multimap>, String> vanillaTags = HashMultimap.create(); + PackResources vanillaPack = resourceManager.listPacks() + .filter(packResources -> packResources.packId().equals(BuiltInPackSource.VANILLA_ID)) + .findFirst() + .orElseThrow(); + collectFromPack(vanillaPack, (entry, path) -> vanillaTags.put(entry.key(), path)); + + // then distinct with other data-pack tags to know for sure newly created tags and so experimental one + resourceManager.listPacks().forEach(pack -> { + String packId = pack.packId(); + if (packId.equals(BuiltInPackSource.VANILLA_ID)) return; + + collectFromPack(pack, (entry, path) -> { + if (vanillaTags.get(entry.key()).contains(path)) { + return; + } + + result.put(entry.value().listTagIds() + .filter(tagKey -> tagKey.location().getPath().equals(path)) + .findFirst() + .orElseThrow(), packId); + }); + }); + return Collections.unmodifiableMap(result); + } + + private static void collectFromPack(PackResources pack, BiConsumer, String> output) { + Set namespaces = pack.getNamespaces(PackType.SERVER_DATA); + + for (String namespace : namespaces) { + Main.REGISTRY_ACCESS.registries().forEach(entry -> { + // this is probably expensive but can't find another way around and data-pack loader has similar logic + // the issue is that registry key can have parent/key (and custom folder too) but tag key can also have parent/key so parsing become a mess + // without having at least one of the two values + String tagDir = Registries.tagsDirPath(entry.key()); + pack.listResources(PackType.SERVER_DATA, namespace, tagDir, (id, supplier) -> { + Formatting.formatTagKey(tagDir, id.getPath()).ifPresentOrElse(path -> output.accept(entry, path), () -> { + LOGGER.warn("Unable to parse the path: {}/{}/{}.json in the data-pack {} into a tag key", namespace, tagDir, id.getPath(), pack.packId()); + }); + }); + }); + } + } + + private TagCollector() { + } +} diff --git a/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java b/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java new file mode 100644 index 000000000000..9bc9f6b400da --- /dev/null +++ b/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java @@ -0,0 +1,37 @@ +package io.papermc.generator; + +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; +import io.papermc.generator.types.goal.MobGoalNames; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Mob; +import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.fail; + +public class MobGoalConverterTest { + + @Test + public void testBukkitMap() { + final List> classes; + try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages(Entity.class.getPackageName()).scan()) { + classes = scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class); + } + + assertFalse(classes.isEmpty(), "There are supposed to be more than 0 mob classes!"); + + List missingClasses = new ArrayList<>(); + for (Class nmsClass : classes) { + if (!MobGoalNames.bukkitMap.containsKey(nmsClass)) { + missingClasses.add(nmsClass.getCanonicalName()); + } + } + + if (!missingClasses.isEmpty()) { + fail("Missing some entity classes in the bukkit map: " + String.join(", ", missingClasses)); + } + } +} diff --git a/paper-api-generator/wideners.at b/paper-api-generator/wideners.at new file mode 100644 index 000000000000..6c8ce1529e1f --- /dev/null +++ b/paper-api-generator/wideners.at @@ -0,0 +1,6 @@ +# for auto-marking experimental stuff +public net/minecraft/core/RegistrySetBuilder entries +public net/minecraft/core/RegistrySetBuilder$RegistryStub +public net/minecraft/data/registries/VanillaRegistries BUILDER +public net/minecraft/data/registries/WinterDropRegistries BUILDER +public net/minecraft/data/registries/TradeRebalanceRegistries BUILDER diff --git a/patches/api/0001-Convert-project-to-Gradle.patch b/patches/api/0001-Convert-project-to-Gradle.patch new file mode 100644 index 000000000000..82d092d45600 --- /dev/null +++ b/patches/api/0001-Convert-project-to-Gradle.patch @@ -0,0 +1,399 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:50:33 -0800 +Subject: [PATCH] Convert project to Gradle + +The pom.xml file is deleted in this patch so the patch will fail to +apply if there are changes made to it from upstream - thus notifying us +that changes were made. + +diff --git a/.gitignore b/.gitignore +index 5dd700a956e915c00b25d91dea8d6f285ddab72b..97e78e27ee0eea2c8b24886eeb19164d552323fe 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,5 @@ ++.gradle/ ++ + # Eclipse stuff + /.classpath + /.project +@@ -32,3 +34,7 @@ + *.ipr + *.iws + .idea/ ++ ++# vs code ++/.vscode ++/.factorypath +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..dfb490fe94c1f543cc75e9f5ca76f8254bff9159 +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +1,93 @@ ++plugins { ++ `java-library` ++ `maven-publish` ++} ++ ++java { ++ withSourcesJar() ++ withJavadocJar() ++} ++ ++val annotationsVersion = "24.1.0" ++val bungeeCordChatVersion = "1.20-R0.2" ++ ++dependencies { ++ // api dependencies are listed transitively to API consumers ++ api("com.google.guava:guava:33.3.1-jre") ++ api("com.google.code.gson:gson:2.11.0") ++ api("net.md-5:bungeecord-chat:$bungeeCordChatVersion") ++ api("org.yaml:snakeyaml:2.2") ++ api("org.joml:joml:1.10.8") { ++ isTransitive = false // https://github.com/JOML-CI/JOML/issues/352 ++ } ++ ++ compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") ++ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") ++ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") ++ ++ val annotations = "org.jetbrains:annotations-java5:$annotationsVersion" ++ compileOnly(annotations) ++ testCompileOnly(annotations) ++ ++ testImplementation("org.apache.commons:commons-lang3:3.12.0") ++ testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") ++ testImplementation("org.hamcrest:hamcrest:2.2") ++ testImplementation("org.mockito:mockito-core:5.14.1") ++ testImplementation("org.ow2.asm:asm-tree:9.7.1") ++} ++ ++configure { ++ publications.create("maven") { ++ from(components["java"]) ++ } ++} ++ ++val generateApiVersioningFile by tasks.registering { ++ inputs.property("version", project.version) ++ val pomProps = layout.buildDirectory.file("pom.properties") ++ outputs.file(pomProps) ++ val projectVersion = project.version ++ doLast { ++ pomProps.get().asFile.writeText("version=$projectVersion") ++ } ++} ++ ++tasks.jar { ++ from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { ++ into("META-INF/maven/${project.group}/${project.name}") ++ } ++ manifest { ++ attributes( ++ "Automatic-Module-Name" to "org.bukkit" ++ ) ++ } ++} ++ ++tasks.withType { ++ val options = options as StandardJavadocDocletOptions ++ options.overview = "src/main/javadoc/overview.html" ++ options.use() ++ options.isDocFilesSubDirs = true ++ options.links( ++ "https://guava.dev/releases/33.3.1-jre/api/docs/", ++ "https://javadoc.io/doc/org.yaml/snakeyaml/2.2/", ++ "https://javadoc.io/doc/org.jetbrains/annotations-java5/$annotationsVersion/", ++ "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", ++ ) ++ options.tags("apiNote:a:API Note:") ++ ++ // workaround for https://github.com/gradle/gradle/issues/4046 ++ inputs.dir("src/main/javadoc").withPropertyName("javadoc-sourceset") ++ doLast { ++ copy { ++ from("src/main/javadoc") { ++ include("**/doc-files/**") ++ } ++ into("build/docs/javadoc") ++ } ++ } ++} ++ ++tasks.test { ++ useJUnitPlatform() ++} +diff --git a/pom.xml b/pom.xml +deleted file mode 100644 +index 25a8f7daaf393f3306ca5c6c0c79d3de7bc983db..0000000000000000000000000000000000000000 +--- a/pom.xml ++++ /dev/null +@@ -1,267 +0,0 @@ +- +- +- 4.0.0 +- +- org.spigotmc +- spigot-api +- 1.21.4-R0.1-SNAPSHOT +- jar +- +- Spigot-API +- https://www.spigotmc.org/ +- An enhanced plugin API for Minecraft servers. +- +- +- true +- 17 +- UTF-8 +- +- +- +- +- spigotmc-releases +- https://hub.spigotmc.org/nexus/content/repositories/releases/ +- +- +- spigotmc-snapshots +- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ +- +- +- +- +- +- +- com.google.guava +- guava +- 33.3.1-jre +- compile +- +- +- +- com.google.code.gson +- gson +- 2.11.0 +- compile +- +- +- +- org.joml +- joml +- 1.10.8 +- compile +- +- +- net.md-5 +- bungeecord-chat +- 1.20-R0.2 +- jar +- compile +- +- +- org.yaml +- snakeyaml +- 2.2 +- compile +- +- +- +- org.apache.maven +- maven-resolver-provider +- 3.9.6 +- provided +- +- +- org.apache.maven.resolver +- maven-resolver-connector-basic +- 1.9.18 +- provided +- +- +- org.apache.maven.resolver +- maven-resolver-transport-http +- 1.9.18 +- provided +- +- +- +- org.jetbrains +- annotations-java5 +- 24.1.0 +- provided +- +- +- +- org.junit.jupiter +- junit-jupiter +- 5.10.2 +- test +- +- +- org.hamcrest +- hamcrest +- 2.2 +- test +- +- +- org.mockito +- mockito-core +- 5.14.1 +- test +- +- +- org.ow2.asm +- asm-tree +- 9.7.1 +- test +- +- +- +- +- +- +- net.md-5 +- scriptus +- 0.5.0 +- +- +- initialize +- +- describe +- +- +- +- +- +- org.apache.maven.plugins +- maven-compiler-plugin +- 3.13.0 +- +- +- false +- +- +- +- org.apache.maven.plugins +- maven-jar-plugin +- 3.4.1 +- +- +- +- false +- +- +- org.bukkit +- +- +- +- +- +- org.apache.maven.plugins +- maven-shade-plugin +- 3.5.3 +- +- +- package +- +- shade +- +- +- +- +- +- +- *:* +- +- META-INF/MANIFEST.MF +- +- +- +- +- true +- +- false +- +- +- +- org.apache.maven.plugins +- maven-javadoc-plugin +- 3.6.3 +- +- +- https://guava.dev/releases/32.1.2-jre/api/docs/ +- +- +- +- apiNote +- a +- API Note: +- +- +- +- +- +- org.apache.maven.plugins +- maven-surefire-plugin +- 3.2.5 +- +- +- +- +- +- +- development +- +- false +- +- +- +- +- org.apache.maven.plugins +- maven-checkstyle-plugin +- 3.3.1 +- +- +- process-classes +- +- check +- +- +- +- +- checkstyle.xml +- true +- +- +- +- com.puppycrawl.tools +- checkstyle +- 8.45.1 +- +- +- +- +- org.codehaus.mojo +- animal-sniffer-maven-plugin +- 1.23 +- +- +- process-classes +- +- check +- +- +- +- +- +- org.codehaus.mojo.signature +- java18 +- 1.0 +- +- +- +- +- +- +- +- diff --git a/patches/api/0002-Build-system-changes.patch b/patches/api/0002-Build-system-changes.patch new file mode 100644 index 000000000000..8ef831d434b8 --- /dev/null +++ b/patches/api/0002-Build-system-changes.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 1 Mar 2016 00:16:08 +0100 +Subject: [PATCH] Build system changes + + +diff --git a/build.gradle.kts b/build.gradle.kts +index dfb490fe94c1f543cc75e9f5ca76f8254bff9159..3667f27baa87c82e071cc14ca20491d38feee255 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -20,15 +20,27 @@ dependencies { + api("org.joml:joml:1.10.8") { + isTransitive = false // https://github.com/JOML-CI/JOML/issues/352 + } ++ // Paper start ++ api("com.googlecode.json-simple:json-simple:1.1.1") { ++ isTransitive = false // includes junit ++ } ++ // Paper end + + compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") + compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") + +- val annotations = "org.jetbrains:annotations-java5:$annotationsVersion" ++ val annotations = "org.jetbrains:annotations:$annotationsVersion" // Paper - we don't want Java 5 annotations... + compileOnly(annotations) + testCompileOnly(annotations) + ++ // Paper start - add checker ++ val checkerQual = "org.checkerframework:checker-qual:3.33.0" ++ compileOnlyApi(checkerQual) ++ testCompileOnly(checkerQual) ++ // Paper end ++ api("org.jspecify:jspecify:1.0.0") // Paper - add jspecify ++ + testImplementation("org.apache.commons:commons-lang3:3.12.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") + testImplementation("org.hamcrest:hamcrest:2.2") +@@ -71,8 +83,13 @@ tasks.withType { + options.links( + "https://guava.dev/releases/33.3.1-jre/api/docs/", + "https://javadoc.io/doc/org.yaml/snakeyaml/2.2/", +- "https://javadoc.io/doc/org.jetbrains/annotations-java5/$annotationsVersion/", ++ "https://javadoc.io/doc/org.jetbrains/annotations/$annotationsVersion/", // Paper - we don't want Java 5 annotations + "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", ++ // Paper start - add missing javadoc links ++ "https://javadoc.io/doc/org.joml/joml/1.10.8/index.html", ++ "https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0", ++ "https://jspecify.dev/docs/api/", ++ // Paper end + ) + options.tags("apiNote:a:API Note:") + +@@ -91,3 +108,14 @@ tasks.withType { + tasks.test { + useJUnitPlatform() + } ++ ++// Paper start ++val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) { ++ badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;") ++ jarToScan.set(tasks.jar.flatMap { it.archiveFile }) ++ classpath.from(configurations.compileClasspath) ++} ++tasks.check { ++ dependsOn(scanJar) ++} ++// Paper end +diff --git a/src/main/java/io/papermc/paper/annotation/DoNotUse.java b/src/main/java/io/papermc/paper/annotation/DoNotUse.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4766e49d819e75e5c2127c698b44078bf2fd6219 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/annotation/DoNotUse.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.annotation; ++ ++import java.lang.annotation.ElementType; ++import java.lang.annotation.Retention; ++import java.lang.annotation.RetentionPolicy; ++import java.lang.annotation.Target; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * Annotation used to mark methods or constructors which should not be called. ++ * ++ *

    Separate from {@link Deprecated} to differentiate from the large amount of deprecations.

    ++ */ ++@ApiStatus.Internal ++@Retention(RetentionPolicy.RUNTIME) ++@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) ++public @interface DoNotUse { ++} diff --git a/patches/api/0003-Test-changes.patch b/patches/api/0003-Test-changes.patch new file mode 100644 index 000000000000..7649a1904f68 --- /dev/null +++ b/patches/api/0003-Test-changes.patch @@ -0,0 +1,349 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sun, 17 Mar 2019 23:04:30 +0000 +Subject: [PATCH] Test changes + +- Allow use of TYPE_USE annotations +- Ignore package-private methods for nullability annotations +- Add excludes for classes which don't pass +- Disable stupid BukkitMirrorTest +- configure mockito agent to address changes in newer java versions see https://openjdk.org/jeps/451 + +Co-authored-by: Riley Park +Co-authored-by: Jake Potrebic +Co-authored-by: Yannick Lamprecht + +diff --git a/build.gradle.kts b/build.gradle.kts +index 3667f27baa87c82e071cc14ca20491d38feee255..73aaa8a341565626556327cda6a73f98c318863a 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -11,6 +11,18 @@ java { + val annotationsVersion = "24.1.0" + val bungeeCordChatVersion = "1.20-R0.2" + ++// Paper start - configure mockito agent that is needed in newer java versions ++val mockitoAgent = configurations.register("mockitoAgent") ++abstract class MockitoAgentProvider : CommandLineArgumentProvider { ++ @get:CompileClasspath ++ abstract val fileCollection: ConfigurableFileCollection ++ ++ override fun asArguments(): Iterable { ++ return listOf("-javaagent:" + fileCollection.files.single().absolutePath) ++ } ++} ++// Paper end - configure mockito agent that is needed in newer java versions ++ + dependencies { + // api dependencies are listed transitively to API consumers + api("com.google.guava:guava:33.3.1-jre") +@@ -46,6 +58,7 @@ dependencies { + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.mockito:mockito-core:5.14.1") + testImplementation("org.ow2.asm:asm-tree:9.7.1") ++ mockitoAgent("org.mockito:mockito-core:5.14.1") { isTransitive = false } // Paper - configure mockito agent that is needed in newer java versions + } + + configure { +@@ -107,8 +120,19 @@ tasks.withType { + + tasks.test { + useJUnitPlatform() ++ // Paper start - configure mockito agent that is needed in newer java versions ++ val provider = objects.newInstance() ++ provider.fileCollection.from(mockitoAgent) ++ jvmArgumentProviders.add(provider) ++ // Paper end - configure mockito agent that is needed in newer java versions + } + ++// Paper start - compile tests with -parameters for better junit parameterized test names ++tasks.compileTestJava { ++ options.compilerArgs.add("-parameters") ++} ++// Paper end ++ + // Paper start + val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.ScanJarForBadCalls::class) { + badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;") +diff --git a/src/test/java/io/papermc/paper/testing/EmptyTag.java b/src/test/java/io/papermc/paper/testing/EmptyTag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..77154095cfb8b259bdb318e8ff40cb6f559ebc18 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/testing/EmptyTag.java +@@ -0,0 +1,31 @@ ++package io.papermc.paper.testing; ++ ++import java.util.Collections; ++import java.util.Set; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Tag; ++import org.jetbrains.annotations.NotNull; ++ ++public record EmptyTag(NamespacedKey key) implements Tag { ++ ++ @SuppressWarnings("deprecation") ++ public EmptyTag() { ++ this(NamespacedKey.randomKey()); ++ } ++ ++ @Override ++ public @NotNull NamespacedKey getKey() { ++ return this.key; ++ } ++ ++ @Override ++ public boolean isTagged(@NotNull final Keyed item) { ++ return false; ++ } ++ ++ @Override ++ public @NotNull Set getValues() { ++ return Collections.emptySet(); ++ } ++} +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 64e7aef6220097edefdff3b98a771b988365930d..07f904a78f51b220a5891aca1afffac4f46d58b4 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -29,7 +29,13 @@ public class AnnotationTest { + "Lorg/jetbrains/annotations/Nullable;", + "Lorg/jetbrains/annotations/NotNull;", + "Lorg/jetbrains/annotations/Contract;", +- "Lorg/bukkit/UndefinedNullability;" ++ "Lorg/bukkit/UndefinedNullability;", ++ // Paper start ++ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", ++ "Lorg/checkerframework/checker/nullness/qual/NonNull;", ++ "Lorg/checkerframework/checker/nullness/qual/Nullable;", ++ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", ++ // Paper end + }; + + private static final String[] EXCLUDED_CLASSES = { +@@ -40,7 +46,17 @@ public class AnnotationTest { + "org/bukkit/util/io/Wrapper", + "org/bukkit/plugin/java/PluginClassLoader", + // Generic functional interface +- "org/bukkit/util/Consumer" ++ "org/bukkit/util/Consumer", ++ // Paper start ++ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull ++ "co/aikar/timings/TimingHistory$2", ++ "co/aikar/timings/TimingHistory$2$1", ++ "co/aikar/timings/TimingHistory$2$1$1", ++ "co/aikar/timings/TimingHistory$2$1$2", ++ "co/aikar/timings/TimingHistory$3", ++ "co/aikar/timings/TimingHistory$4", ++ "co/aikar/timings/TimingHistoryEntry$1" ++ // Paper end + }; + + @Test +@@ -61,20 +77,60 @@ public class AnnotationTest { + continue; + } + ++ // Paper start - skip class if it's @NullMarked ++ if (isClassNullMarked(clazz, foundClasses)) { ++ continue; ++ } ++ // Paper end - skip class if it's @NullMarked ++ + for (MethodNode method : clazz.methods) { + if (!isMethodIncluded(clazz, method, foundClasses)) { + continue; + } + + if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) { ++ // Paper start - Allow use of TYPE_USE annotations ++ boolean warn = true; ++ if (isWellAnnotated(method.visibleTypeAnnotations)) { ++ warn = false; ++ } else if (method.invisibleTypeAnnotations != null) { ++ dance: for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) { ++ final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); ++ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_RETURN && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { ++ warn = false; ++ break dance; // cha cha real smooth ++ } ++ } ++ } ++ if (warn) ++ // Paper end + warn(errors, clazz, method, "return value"); + } + + Type[] paramTypes = Type.getArgumentTypes(method.desc); + List parameters = method.parameters; + ++ dancing: // Paper + for (int i = 0; i < paramTypes.length; i++) { + if (mustBeAnnotated(paramTypes[i]) ^ isWellAnnotated(method.invisibleParameterAnnotations == null ? null : method.invisibleParameterAnnotations[i])) { ++ // Paper start ++ if (method.invisibleTypeAnnotations != null) { ++ for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) { ++ final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); ++ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { ++ continue dancing; ++ } ++ } ++ } ++ if (method.visibleTypeAnnotations != null) { ++ for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.visibleTypeAnnotations) { ++ final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); ++ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { ++ continue dancing; ++ } ++ } ++ } ++ // Paper end - Allow use of TYPE_USE annotations + ParameterNode paramNode = parameters == null ? null : parameters.get(i); + String paramName = paramNode == null ? null : paramNode.name; + +@@ -91,17 +147,37 @@ public class AnnotationTest { + + Collections.sort(errors); + +- System.out.println(errors.size() + " missing annotation(s):"); ++ StringBuilder builder = new StringBuilder() ++ .append("There ") ++ .append(errors.size() != 1 ? "are " : "is ") ++ .append(errors.size()) ++ .append(" missing annotation") ++ .append(errors.size() != 1 ? "s:\n" : ":\n"); ++ + for (String message : errors) { +- System.out.print("\t"); +- System.out.println(message); ++ builder.append("\t").append(message).append("\n"); + } + +- fail("There " + errors.size() + " are missing annotation(s)"); ++ fail(builder.toString()); + } + + private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { + if (from.isDirectory()) { ++ // Paper start - skip packages with @NullMarked ++ final File packageInfo = new File(from, "package-info.class"); ++ if (packageInfo.exists()) { ++ try (final FileInputStream in = new FileInputStream(packageInfo)) { ++ final ClassReader cr = new ClassReader(in); ++ ++ final ClassNode node = new ClassNode(); ++ cr.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); ++ ++ if (isClassNullMarked0(node)) { ++ return; // skip packages with @NullMarked ++ } ++ } ++ } ++ // Paper end - skip packages with @NullMarked + final File[] files = from.listFiles(); + assert files != null; + +@@ -125,6 +201,23 @@ public class AnnotationTest { + } + } + ++ // Paper start - skip class if it's @NullMarked ++ private static boolean isClassNullMarked(@NotNull ClassNode clazz, @NotNull Map allClasses) { ++ if (clazz.nestHostClass != null) { ++ final ClassNode nestHostNode = allClasses.get(clazz.nestHostClass); ++ if (nestHostNode != null) { ++ return isClassNullMarked0(nestHostNode); ++ } ++ } ++ ++ return isClassNullMarked0(clazz); ++ } ++ ++ private static boolean isClassNullMarked0(@NotNull ClassNode clazz) { ++ return clazz.visibleAnnotations != null && clazz.visibleAnnotations.stream().anyMatch(node -> "Lorg/jspecify/annotations/NullMarked;".equals(node.desc)); ++ } ++ // Paper end - skip class if it's @NullMarked ++ + private static boolean isClassIncluded(@NotNull ClassNode clazz, @NotNull Map allClasses) { + // Exclude private, synthetic or deprecated classes and annotations, since their members can't be null + if ((clazz.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ANNOTATION)) != 0) { +@@ -140,6 +233,11 @@ public class AnnotationTest { + // Exceptions are excluded + return false; + } ++ // Paper start ++ if (isInternal(clazz.invisibleAnnotations)) { ++ return false; ++ } ++ // Paper end + + for (String excludedClass : EXCLUDED_CLASSES) { + if (excludedClass.equals(clazz.name)) { +@@ -152,7 +250,7 @@ public class AnnotationTest { + + private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { + // Exclude private, synthetic and deprecated methods +- if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0) { ++ if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private + return false; + } + +@@ -170,11 +268,30 @@ public class AnnotationTest { + if ("".equals(method.name) && isAnonymous(clazz)) { + return false; + } ++ // Paper start ++ if (isInternal(method.invisibleAnnotations)) { ++ return false; ++ } ++ // Paper end + + return true; + } ++ // Paper start ++ private static boolean isInternal(List annotations) { ++ if (annotations == null) { ++ return false; ++ } ++ for (AnnotationNode node : annotations) { ++ if (node.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;")) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Paper end + +- private static boolean isWellAnnotated(@Nullable List annotations) { ++ private static boolean isWellAnnotated(@Nullable List annotations) { // Paper + if (annotations == null) { + return false; + } +diff --git a/src/test/java/org/bukkit/BukkitMirrorTest.java b/src/test/java/org/bukkit/BukkitMirrorTest.java +index 89ca06ebecdaadd5dfc7bc74473ca15ad36f6eff..5974ceea58940e1799f3589eac0e39b925a42c3b 100644 +--- a/src/test/java/org/bukkit/BukkitMirrorTest.java ++++ b/src/test/java/org/bukkit/BukkitMirrorTest.java +@@ -9,6 +9,7 @@ import org.junit.jupiter.params.ParameterizedTest; + import org.junit.jupiter.params.provider.Arguments; + import org.junit.jupiter.params.provider.MethodSource; + ++@org.junit.jupiter.api.Disabled // Paper + public class BukkitMirrorTest { + + public static Stream data() { +diff --git a/src/test/java/org/bukkit/support/TestServer.java b/src/test/java/org/bukkit/support/TestServer.java +index c67e0784c043ed194f6acde32411e156412a9b24..eb1fd4b911c4af76cdd3eac85d5365e7941a4a2e 100644 +--- a/src/test/java/org/bukkit/support/TestServer.java ++++ b/src/test/java/org/bukkit/support/TestServer.java +@@ -83,6 +83,11 @@ public final class TestServer { + UnsafeValues unsafeValues = mock(withSettings().stubOnly()); + when(instance.getUnsafe()).thenReturn(unsafeValues); + ++ // Paper start - testing changes ++ when(instance.getTag(anyString(), any(NamespacedKey.class), any())).thenAnswer(ignored -> new io.papermc.paper.testing.EmptyTag()); ++ when(instance.getScoreboardCriteria(anyString())).thenReturn(null); ++ // Paper end - testing changes ++ + Bukkit.setServer(instance); + } + diff --git a/patches/api/0004-Code-Generation.patch b/patches/api/0004-Code-Generation.patch new file mode 100644 index 000000000000..2cb22cc016d9 --- /dev/null +++ b/patches/api/0004-Code-Generation.patch @@ -0,0 +1,414 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 26 May 2023 18:14:44 -0700 +Subject: [PATCH] Code Generation + +Currently includes generated key holder classes for types +used in the Registry Modification API + +diff --git a/build.gradle.kts b/build.gradle.kts +index 73aaa8a341565626556327cda6a73f98c318863a..a214483db535890a4b89e35a8c50cfd709df36d4 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -1,6 +1,7 @@ + plugins { + `java-library` + `maven-publish` ++ idea // Paper + } + + java { +@@ -61,6 +62,22 @@ dependencies { + mockitoAgent("org.mockito:mockito-core:5.14.1") { isTransitive = false } // Paper - configure mockito agent that is needed in newer java versions + } + ++// Paper start ++val generatedApiPath: java.nio.file.Path = rootProject.projectDir.toPath().resolve("paper-api-generator/generated") ++idea { ++ module { ++ generatedSourceDirs.add(generatedApiPath.toFile()) ++ } ++} ++sourceSets { ++ main { ++ java { ++ srcDir(generatedApiPath) ++ } ++ } ++} ++// Paper end ++ + configure { + publications.create("maven") { + from(components["java"]) +@@ -143,3 +160,14 @@ tasks.check { + dependsOn(scanJar) + } + // Paper end ++// Paper start ++val scanJarForOldGeneratedCode = tasks.register("scanJarForOldGeneratedCode", io.papermc.paperweight.tasks.ScanJarForOldGeneratedCode::class) { ++ mcVersion.set(providers.gradleProperty("mcVersion")) ++ annotation.set("Lio/papermc/paper/generated/GeneratedFrom;") ++ jarToScan.set(tasks.jar.flatMap { it.archiveFile }) ++ classpath.from(configurations.compileClasspath) ++} ++tasks.check { ++ dependsOn(scanJarForOldGeneratedCode) ++} ++// Paper end +diff --git a/src/main/java/io/papermc/paper/generated/GeneratedFrom.java b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2512dba27edfdccbc4430815b6cba048e3d93484 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.generated; ++ ++import java.lang.annotation.Documented; ++import java.lang.annotation.ElementType; ++import java.lang.annotation.Retention; ++import java.lang.annotation.RetentionPolicy; ++import java.lang.annotation.Target; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * Used to mark classes which are generated from ++ * a specific version of minecraft. ++ */ ++@ApiStatus.Internal ++@Documented ++@Retention(RetentionPolicy.RUNTIME) ++@Target(ElementType.TYPE) ++public @interface GeneratedFrom { ++ ++ String value(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java +new file mode 100644 +index 0000000000000000000000000000000000000000..647f6a1ec1f9d3c203b41f90a99bfd415bf67366 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java +@@ -0,0 +1,196 @@ ++package io.papermc.paper.registry; ++ ++import net.kyori.adventure.key.Keyed; ++import org.bukkit.Art; ++import org.bukkit.Fluid; ++import org.bukkit.GameEvent; ++import org.bukkit.JukeboxSong; ++import org.bukkit.MusicInstrument; ++import org.bukkit.Particle; ++import org.bukkit.Sound; ++import org.bukkit.attribute.Attribute; ++import org.bukkit.block.Biome; ++import org.bukkit.block.BlockType; ++import org.bukkit.block.banner.PatternType; ++import org.bukkit.damage.DamageType; ++import org.bukkit.enchantments.Enchantment; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Frog; ++import org.bukkit.entity.Villager; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.memory.MemoryKey; ++import org.bukkit.generator.structure.Structure; ++import org.bukkit.generator.structure.StructureType; ++import org.bukkit.inventory.ItemType; ++import org.bukkit.inventory.MenuType; ++import org.bukkit.inventory.meta.trim.TrimMaterial; ++import org.bukkit.inventory.meta.trim.TrimPattern; ++import org.bukkit.map.MapCursor; ++import org.bukkit.potion.PotionEffectType; ++import org.bukkit.potion.PotionType; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++import static io.papermc.paper.registry.RegistryKeyImpl.create; ++ ++/** ++ * Identifier for a specific registry. For use with ++ * {@link TypedKey} and the registry modification API. ++ *

    ++ * There are 2 types of registries, identified as "built-in" ++ * or "data-driven". The former are not changeable by datapacks (which ++ * doesn't necessarily mean they aren't changeable in the API) and ++ * are loaded first. "Data-driven" registries are all created by ++ * reading in data from the vanilla and other datapacks. ++ * ++ * @param the value type ++ */ ++@SuppressWarnings("unused") ++@NullMarked ++public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl { ++ ++ /* ******************* * ++ * Built-in Registries * ++ * ******************* */ ++ /** ++ * Built-in registry for game events ++ * @see io.papermc.paper.registry.keys.GameEventKeys ++ */ ++ RegistryKey GAME_EVENT = create("game_event"); ++ /** ++ * Built-in registry for structure types. ++ * @see io.papermc.paper.registry.keys.StructureTypeKeys ++ */ ++ RegistryKey STRUCTURE_TYPE = create("worldgen/structure_type"); ++ /** ++ * Built-in registry for potion effect types (mob effects). ++ * @see io.papermc.paper.registry.keys.MobEffectKeys ++ */ ++ RegistryKey MOB_EFFECT = create("mob_effect"); ++ /** ++ * @apiNote DO NOT USE ++ */ ++ @ApiStatus.Internal ++ RegistryKey BLOCK = create("block"); ++ /** ++ * @apiNote DO NOT USE ++ */ ++ @ApiStatus.Internal ++ RegistryKey ITEM = create("item"); ++ /** ++ * Built-in registry for cat variants. ++ * @see io.papermc.paper.registry.keys.CatVariantKeys ++ */ ++ RegistryKey CAT_VARIANT = create("cat_variant"); ++ /** ++ * Built-in registry for frog variants. ++ * @see io.papermc.paper.registry.keys.FrogVariantKeys ++ */ ++ RegistryKey FROG_VARIANT = create("frog_variant"); ++ /** ++ * Built-in registry for villager professions. ++ * @see io.papermc.paper.registry.keys.VillagerProfessionKeys ++ */ ++ RegistryKey VILLAGER_PROFESSION = create("villager_profession"); ++ /** ++ * Built-in registry for villager types. ++ * @see io.papermc.paper.registry.keys.VillagerTypeKeys ++ */ ++ RegistryKey VILLAGER_TYPE = create("villager_type"); ++ /** ++ * Built-in registry for map decoration types. ++ * @see io.papermc.paper.registry.keys.MapDecorationTypeKeys ++ */ ++ RegistryKey MAP_DECORATION_TYPE = create("map_decoration_type"); ++ /** ++ * Built-in registry for menu types. ++ * @see io.papermc.paper.registry.keys.MenuTypeKeys ++ */ ++ RegistryKey MENU = create("menu"); ++ /** ++ * Built-in registry for attributes. ++ * @see io.papermc.paper.registry.keys.AttributeKeys ++ */ ++ RegistryKey ATTRIBUTE = create("attribute"); ++ /** ++ * Built-in registry for fluids. ++ * @see io.papermc.paper.registry.keys.FluidKeys ++ */ ++ RegistryKey FLUID = create("fluid"); ++ /** ++ * Built-in registry for sound events. ++ * @see io.papermc.paper.registry.keys.SoundEventKeys ++ */ ++ RegistryKey SOUND_EVENT = create("sound_event"); ++ ++ ++ ++ /* ********************** * ++ * Data-driven Registries * ++ * ********************** */ ++ /** ++ * Data-driven registry for biomes. ++ * @see io.papermc.paper.registry.keys.BiomeKeys ++ */ ++ RegistryKey BIOME = create("worldgen/biome"); ++ /** ++ * Data-driven registry for structures. ++ * @see io.papermc.paper.registry.keys.StructureKeys ++ */ ++ RegistryKey STRUCTURE = create("worldgen/structure"); ++ /** ++ * Data-driven registry for trim materials. ++ * @see io.papermc.paper.registry.keys.TrimMaterialKeys ++ */ ++ RegistryKey TRIM_MATERIAL = create("trim_material"); ++ /** ++ * Data-driven registry for trim patterns. ++ * @see io.papermc.paper.registry.keys.TrimPatternKeys ++ */ ++ RegistryKey TRIM_PATTERN = create("trim_pattern"); ++ /** ++ * Data-driven registry for damage types. ++ * @see io.papermc.paper.registry.keys.DamageTypeKeys ++ */ ++ RegistryKey DAMAGE_TYPE = create("damage_type"); ++ /** ++ * Data-driven registry for wolf variants. ++ * @see io.papermc.paper.registry.keys.WolfVariantKeys ++ */ ++ RegistryKey WOLF_VARIANT = create("wolf_variant"); ++ /** ++ * Data-driven registry for enchantments. ++ * @see io.papermc.paper.registry.keys.EnchantmentKeys ++ */ ++ RegistryKey ENCHANTMENT = create("enchantment"); ++ /** ++ * Data-driven registry for jukebox songs. ++ * @see io.papermc.paper.registry.keys.JukeboxSongKeys ++ */ ++ RegistryKey JUKEBOX_SONG = create("jukebox_song"); ++ /** ++ * Data-driven registry for banner patterns. ++ * @see io.papermc.paper.registry.keys.BannerPatternKeys ++ */ ++ RegistryKey BANNER_PATTERN = create("banner_pattern"); ++ /** ++ * Data-driven registry for painting variants. ++ * @see io.papermc.paper.registry.keys.PaintingVariantKeys ++ */ ++ RegistryKey PAINTING_VARIANT = create("painting_variant"); ++ /** ++ * Data-driven registry for instruments. ++ * @see io.papermc.paper.registry.keys.InstrumentKeys ++ */ ++ RegistryKey INSTRUMENT = create("instrument"); ++ ++ ++ /* ******************* * ++ * API-only Registries * ++ * ******************* */ ++ RegistryKey ENTITY_TYPE = create("entity_type"); ++ RegistryKey PARTICLE_TYPE = create("particle_type"); ++ RegistryKey POTION = create("potion"); ++ RegistryKey> MEMORY_MODULE_TYPE = create("memory_module_type"); ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..80e3e64f47ac55a4978c9e5b430e2f2d1c871d1b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.registry; ++ ++import com.google.common.collect.Sets; ++import java.util.Set; ++import net.kyori.adventure.key.Key; ++import org.intellij.lang.annotations.Subst; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@NullMarked ++record RegistryKeyImpl(Key key) implements RegistryKey { ++ ++ static final Set> REGISTRY_KEYS = Sets.newIdentityHashSet(); ++ ++ static RegistryKey create(@Subst("some_key") final String key) { ++ final RegistryKey registryKey = createInternal(key); ++ REGISTRY_KEYS.add(registryKey); ++ return registryKey; ++ } ++ ++ // creates the key without adding to the internal set of keys ++ static RegistryKey createInternal(@Subst("some_key") final String key) { ++ return new RegistryKeyImpl<>(Key.key(Key.MINECRAFT_NAMESPACE, key)); ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java +new file mode 100644 +index 0000000000000000000000000000000000000000..81bee5224196008662ddda528b5dcb8dd7cb9f21 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/TypedKey.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.registry; ++ ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.key.Keyed; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents a key for a value in a specific registry. ++ * ++ * @param the value type for the registry ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public sealed interface TypedKey extends Key permits TypedKeyImpl { ++ ++ /** ++ * Gets the key for the value in the registry. ++ * ++ * @return the value's key ++ */ ++ @Override ++ Key key(); ++ ++ /** ++ * Gets the registry key for the value this key ++ * represents. ++ * ++ * @return the registry key ++ */ ++ RegistryKey registryKey(); ++ ++ /** ++ * Create a typed key from a key and a registry key. ++ * ++ * @param registryKey the registry this key is for ++ * @param key the key for the value in the registry ++ * @param value type ++ * @return a new key for the value key and registry key ++ */ ++ @ApiStatus.Experimental ++ static TypedKey create(final RegistryKey registryKey, final Key key) { ++ return new TypedKeyImpl<>(key, registryKey); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3e29f7007500582cdc3f84b91f11ebeb58f68bbf +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java +@@ -0,0 +1,23 @@ ++package io.papermc.paper.registry; ++ ++import net.kyori.adventure.key.Key; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++record TypedKeyImpl(Key key, RegistryKey registryKey) implements TypedKey { ++ // Wrap key methods to make this easier to use ++ @Override ++ public String namespace() { ++ return this.key.namespace(); ++ } ++ ++ @Override ++ public String value() { ++ return this.key.value(); ++ } ++ ++ @Override ++ public String asString() { ++ return this.key.asString(); ++ } ++} +diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java +index a86b87e4c3332202e40e484c3f9c6562b419c70f..e996a758fc1e4ecfec68641733d69665f30792e8 100644 +--- a/src/main/java/org/bukkit/MinecraftExperimental.java ++++ b/src/main/java/org/bukkit/MinecraftExperimental.java +@@ -47,5 +47,10 @@ public @interface MinecraftExperimental { + @ApiStatus.Internal + public enum Requires { + ++ // Paper start ++ TRADE_REBALANCE, ++ REDSTONE_EXPERIMENTS, ++ MINECART_IMPROVEMENTS ++ // Paper end + } + } diff --git a/patches/api/0005-Add-FastUtil-to-Bukkit.patch b/patches/api/0005-Add-FastUtil-to-Bukkit.patch new file mode 100644 index 000000000000..b5a3ecfd352e --- /dev/null +++ b/patches/api/0005-Add-FastUtil-to-Bukkit.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 1 Apr 2016 00:02:47 -0400 +Subject: [PATCH] Add FastUtil to Bukkit + +Doesn't expose to plugins, just allows Paper-API to use it for optimization + +diff --git a/build.gradle.kts b/build.gradle.kts +index a214483db535890a4b89e35a8c50cfd709df36d4..e1acfa9abed37e5332edf6b6cf66e3b9b926b366 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -37,6 +37,7 @@ dependencies { + api("com.googlecode.json-simple:json-simple:1.1.1") { + isTransitive = false // includes junit + } ++ api("it.unimi.dsi:fastutil:8.5.15") + // Paper end + + compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch new file mode 100644 index 000000000000..43d2ca554749 --- /dev/null +++ b/patches/api/0006-Adventure.patch @@ -0,0 +1,5660 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Riley Park +Date: Fri, 29 Jan 2021 17:21:55 +0100 +Subject: [PATCH] Adventure + +Co-authored-by: zml +Co-authored-by: Jake Potrebic +Co-authored-by: Yannick Lamprecht + +diff --git a/build.gradle.kts b/build.gradle.kts +index e1acfa9abed37e5332edf6b6cf66e3b9b926b366..ed5d58d7569300c917dd52b11953a63fae6878d4 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -11,6 +11,18 @@ java { + + val annotationsVersion = "24.1.0" + val bungeeCordChatVersion = "1.20-R0.2" ++val adventureVersion = "4.17.0" ++val apiAndDocs: Configuration by configurations.creating { ++ attributes { ++ attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION)) ++ attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL)) ++ attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES)) ++ attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) ++ } ++} ++configurations.api { ++ extendsFrom(apiAndDocs) ++} + + // Paper start - configure mockito agent that is needed in newer java versions + val mockitoAgent = configurations.register("mockitoAgent") +@@ -28,7 +40,11 @@ dependencies { + // api dependencies are listed transitively to API consumers + api("com.google.guava:guava:33.3.1-jre") + api("com.google.code.gson:gson:2.11.0") +- api("net.md-5:bungeecord-chat:$bungeeCordChatVersion") ++ // Paper start - adventure ++ api("net.md-5:bungeecord-chat:$bungeeCordChatVersion-deprecated+build.19") { ++ exclude("com.google.guava", "guava") ++ } ++ // Paper - adventure + api("org.yaml:snakeyaml:2.2") + api("org.joml:joml:1.10.8") { + isTransitive = false // https://github.com/JOML-CI/JOML/issues/352 +@@ -38,6 +54,13 @@ dependencies { + isTransitive = false // includes junit + } + api("it.unimi.dsi:fastutil:8.5.15") ++ apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion")) ++ apiAndDocs("net.kyori:adventure-api") ++ apiAndDocs("net.kyori:adventure-text-minimessage") ++ apiAndDocs("net.kyori:adventure-text-serializer-gson") ++ apiAndDocs("net.kyori:adventure-text-serializer-legacy") ++ apiAndDocs("net.kyori:adventure-text-serializer-plain") ++ apiAndDocs("net.kyori:adventure-text-logger-slf4j") + // Paper end + + compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") +@@ -115,15 +138,32 @@ tasks.withType { + "https://guava.dev/releases/33.3.1-jre/api/docs/", + "https://javadoc.io/doc/org.yaml/snakeyaml/2.2/", + "https://javadoc.io/doc/org.jetbrains/annotations/$annotationsVersion/", // Paper - we don't want Java 5 annotations +- "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", ++ // "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", // Paper - don't link to bungee chat + // Paper start - add missing javadoc links + "https://javadoc.io/doc/org.joml/joml/1.10.8/index.html", + "https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0", + "https://jspecify.dev/docs/api/", + // Paper end ++ // Paper start ++ "https://jd.advntr.dev/api/$adventureVersion/", ++ "https://jd.advntr.dev/key/$adventureVersion/", ++ "https://jd.advntr.dev/text-minimessage/$adventureVersion/", ++ "https://jd.advntr.dev/text-serializer-gson/$adventureVersion/", ++ "https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/", ++ "https://jd.advntr.dev/text-serializer-plain/$adventureVersion/", ++ "https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/", ++ // Paper end + ) + options.tags("apiNote:a:API Note:") + ++ inputs.files(apiAndDocs).ignoreEmptyDirectories().withPropertyName(apiAndDocs.name + "-configuration") ++ doFirst { ++ options.addStringOption( ++ "sourcepath", ++ apiAndDocs.elements.get().map { it.asFile }.joinToString(separator = File.pathSeparator, transform = File::getPath) ++ ) ++ } ++ + // workaround for https://github.com/gradle/gradle/issues/4046 + inputs.dir("src/main/javadoc").withPropertyName("javadoc-sourceset") + doLast { +diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1288cdeafe587e9e78e7c5087742ea054ba8423d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ChatRenderer.java +@@ -0,0 +1,70 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A chat renderer is responsible for rendering chat messages sent by {@link Player}s to the server. ++ */ ++@NullMarked ++@FunctionalInterface ++public interface ChatRenderer { ++ ++ /** ++ * Renders a chat message. This will be called once for each receiving {@link Audience}. ++ * ++ * @param source the message source ++ * @param sourceDisplayName the display name of the source player ++ * @param message the chat message ++ * @param viewer the receiving {@link Audience} ++ * @return a rendered chat message ++ */ ++ @ApiStatus.OverrideOnly ++ Component render(Player source, Component sourceDisplayName, Component message, Audience viewer); ++ ++ /** ++ * Create a new instance of the default {@link ChatRenderer}. ++ * ++ * @return a new {@link ChatRenderer} ++ */ ++ static ChatRenderer defaultRenderer() { ++ return new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message)); ++ } ++ ++ @ApiStatus.Internal ++ sealed interface Default extends ChatRenderer, ViewerUnaware permits ViewerUnawareImpl.Default { ++ } ++ ++ /** ++ * Creates a new viewer-unaware {@link ChatRenderer}, which will render the chat message a single time, ++ * displaying the same rendered message to every viewing {@link Audience}. ++ * ++ * @param renderer the viewer unaware renderer ++ * @return a new {@link ChatRenderer} ++ */ ++ static ChatRenderer viewerUnaware(final ViewerUnaware renderer) { ++ return new ViewerUnawareImpl(renderer); ++ } ++ ++ /** ++ * Similar to {@link ChatRenderer}, but without knowledge of the message viewer. ++ * ++ * @see ChatRenderer#viewerUnaware(ViewerUnaware) ++ */ ++ interface ViewerUnaware { ++ ++ /** ++ * Renders a chat message. ++ * ++ * @param source the message source ++ * @param sourceDisplayName the display name of the source player ++ * @param message the chat message ++ * @return a rendered chat message ++ */ ++ @ApiStatus.OverrideOnly ++ Component render(Player source, Component sourceDisplayName, Component message); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e1ef23b4bdf60a299d6d37099cef777b3de13ac7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java +@@ -0,0 +1,38 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@ApiStatus.Internal ++@NullMarked ++sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default { ++ private final ViewerUnaware unaware; ++ private @Nullable Component message; ++ ++ ViewerUnawareImpl(final ViewerUnaware unaware) { ++ this.unaware = unaware; ++ } ++ ++ @Override ++ public Component render(final Player source, final Component sourceDisplayName, final Component message, final Audience viewer) { ++ return this.render(source, sourceDisplayName, message); ++ } ++ ++ @Override ++ public Component render(final Player source, final Component sourceDisplayName, final Component message) { ++ if (this.message == null) { ++ this.message = this.unaware.render(source, sourceDisplayName, message); ++ } ++ return this.message; ++ } ++ ++ static final class Default extends ViewerUnawareImpl implements ChatRenderer.Default { ++ Default(final ViewerUnaware unaware) { ++ super(unaware); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9a95d203151d2c91b0eec494e3674f0facfaa305 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java +@@ -0,0 +1,122 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import java.util.Set; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.chat.SignedMessage; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++import static java.util.Objects.requireNonNull; ++ ++/** ++ * An abstract implementation of a chat event, handling shared logic. ++ */ ++@ApiStatus.NonExtendable ++@NullMarked ++public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable { ++ ++ private final Set viewers; ++ private final Component originalMessage; ++ private final SignedMessage signedMessage; ++ private ChatRenderer renderer; ++ private Component message; ++ ++ private boolean cancelled; ++ ++ AbstractChatEvent(final boolean async, final Player player, final Set viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) { ++ super(player, async); ++ this.viewers = viewers; ++ this.renderer = renderer; ++ this.message = message; ++ this.originalMessage = originalMessage; ++ this.signedMessage = signedMessage; ++ } ++ ++ /** ++ * Gets a set of {@link Audience audiences} that this chat message will be displayed to. ++ * ++ *

    The set returned may auto-populate on access. Any listener accessing the returned set should be aware that ++ * it may reduce performance for a lazy set implementation.

    ++ * ++ * @return a mutable set of {@link Audience audiences} who will receive the chat message ++ */ ++ public final Set viewers() { ++ return this.viewers; ++ } ++ ++ /** ++ * Sets the chat renderer. ++ * ++ * @param renderer the chat renderer ++ * @throws NullPointerException if {@code renderer} is {@code null} ++ */ ++ public final void renderer(final ChatRenderer renderer) { ++ this.renderer = requireNonNull(renderer, "renderer"); ++ } ++ ++ /** ++ * Gets the chat renderer. ++ * ++ * @return the chat renderer ++ */ ++ public final ChatRenderer renderer() { ++ return this.renderer; ++ } ++ ++ /** ++ * Gets the user-supplied message. ++ * The return value will reflect changes made using {@link #message(Component)}. ++ * ++ * @return the user-supplied message ++ */ ++ public final Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Sets the user-supplied message. ++ * ++ * @param message the user-supplied message ++ * @throws NullPointerException if {@code message} is {@code null} ++ */ ++ public final void message(final Component message) { ++ this.message = requireNonNull(message, "message"); ++ } ++ ++ /** ++ * Gets the original and unmodified user-supplied message. ++ * The return value will not reflect changes made using ++ * {@link #message(Component)}. ++ * ++ * @return the original user-supplied message ++ */ ++ public final Component originalMessage() { ++ return this.originalMessage; ++ } ++ ++ /** ++ * Gets the signed message. ++ * Changes made in this event will not update ++ * the signed message. ++ * ++ * @return the signed message ++ */ ++ public final SignedMessage signedMessage() { ++ return this.signedMessage; ++ } ++ ++ @Override ++ public final boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public final void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ddd4c90f83b5cb8f069ff53760abb3c4adfd1168 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@ApiStatus.Experimental ++@NullMarked ++public class AsyncChatCommandDecorateEvent extends AsyncChatDecorateEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @ApiStatus.Internal ++ public AsyncChatCommandDecorateEvent(final @Nullable Player player, final Component originalMessage) { ++ super(player, originalMessage); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9e5ea0cd006bd9744b84923620841f07fa40c2cb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java +@@ -0,0 +1,105 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.server.ServerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * This event is fired when the server decorates a component for chat purposes. This is called ++ * before {@link AsyncChatEvent} and the other chat events. It is recommended that you modify the ++ * message here, and use the chat events for modifying receivers and later the chat type. If you ++ * want to keep the message as "signed" for the clients who get it, be sure to include the entire ++ * original message somewhere in the final message. ++ *
    ++ * See {@link AsyncChatCommandDecorateEvent} for the decoration of messages sent via commands ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public class AsyncChatDecorateEvent extends ServerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final @Nullable Player player; ++ private final Component originalMessage; ++ private Component result; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public AsyncChatDecorateEvent(final @Nullable Player player, final Component originalMessage) { ++ super(true); ++ this.player = player; ++ this.originalMessage = originalMessage; ++ this.result = originalMessage; ++ } ++ ++ /** ++ * Gets the player (if available) associated with this event. ++ *

    ++ * Certain commands request decorations without a player context ++ * which is why this is possibly null. ++ * ++ * @return the player or {@code null} ++ */ ++ public @Nullable Player player() { ++ return this.player; ++ } ++ ++ /** ++ * Gets the original decoration input ++ * ++ * @return the input ++ */ ++ public Component originalMessage() { ++ return this.originalMessage; ++ } ++ ++ /** ++ * Gets the decoration result. This may already be different from ++ * {@link #originalMessage()} if some other listener to this event ++ * changed the result. ++ * ++ * @return the result ++ */ ++ public Component result() { ++ return this.result; ++ } ++ ++ /** ++ * Sets the resulting decorated component. ++ * ++ * @param result the result ++ */ ++ public void result(final Component result) { ++ this.result = result; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * A cancelled decorating event means that no changes to the result component ++ * will have any effect. The decorated component will be equal to the original ++ * component. ++ */ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..50c3e117dec63811823b4e6395bf4f090692ee8c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java +@@ -0,0 +1,44 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import java.util.Set; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.chat.SignedMessage; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * An event fired when a {@link Player} sends a chat message to the server. ++ *

    ++ * This event will sometimes fire synchronously, depending on how it was ++ * triggered. ++ *

    ++ * If a player is the direct cause of this event by an incoming packet, this ++ * event will be asynchronous. If a plugin triggers this event by compelling a ++ * player to chat, this event will be synchronous. ++ *

    ++ * Care should be taken to check {@link #isAsynchronous()} and treat the event ++ * appropriately. ++ */ ++@NullMarked ++public final class AsyncChatEvent extends AbstractChatEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @ApiStatus.Internal ++ public AsyncChatEvent(final boolean async, final Player player, final Set viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) { ++ super(async, player, viewers, renderer, message, originalMessage, signedMessage); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..42a82ce2316a4aad2883d24c7e2ff95d95f5881a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.event.player; ++ ++import io.papermc.paper.chat.ChatRenderer; ++import java.util.Set; ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.chat.SignedMessage; ++import net.kyori.adventure.text.Component; ++import org.bukkit.Warning; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * An event fired when a {@link Player} sends a chat message to the server. ++ * ++ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. ++ * It is recommended to use {@link AsyncChatEvent} instead, wherever possible. ++ */ ++@Deprecated ++@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") ++@NullMarked ++public final class ChatEvent extends AbstractChatEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @ApiStatus.Internal ++ public ChatEvent(final Player player, final Set viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) { ++ super(false, player, viewers, renderer, message, originalMessage, signedMessage); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/text/PaperComponents.java b/src/main/java/io/papermc/paper/text/PaperComponents.java +new file mode 100644 +index 0000000000000000000000000000000000000000..934d1d3ca490a8e25c438bc8c57eb6bde50e0147 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/text/PaperComponents.java +@@ -0,0 +1,180 @@ ++package io.papermc.paper.text; ++ ++import java.io.IOException; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.flattener.ComponentFlattener; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; ++import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.entity.Entity; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Paper API-specific methods for working with {@link Component}s and related. ++ */ ++@NullMarked ++public final class PaperComponents { ++ ++ private PaperComponents() { ++ throw new RuntimeException("PaperComponents is not to be instantiated!"); ++ } ++ ++ /** ++ * Resolves a component with a specific command sender and subject. ++ *

    ++ * Note that in Vanilla, elevated permissions are usually required to use ++ * '@' selectors in various component types, but this method should not ++ * check such permissions from the sender. ++ *

    ++ * A {@link CommandSender} argument is required to resolve: ++ *

      ++ *
    • {@link net.kyori.adventure.text.NBTComponent}
    • ++ *
    • {@link net.kyori.adventure.text.ScoreComponent}
    • ++ *
    • {@link net.kyori.adventure.text.SelectorComponent}
    • ++ *
    ++ * A {@link Entity} argument is optional to help resolve: ++ *
      ++ *
    • {@link net.kyori.adventure.text.ScoreComponent}
    • ++ *
    ++ * {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments. ++ * ++ * @param input the component to resolve ++ * @param context the command sender to resolve with ++ * @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s) ++ * @return the resolved component ++ * @throws IOException if a syntax error tripped during resolving ++ */ ++ public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject) throws IOException { ++ return resolveWithContext(input, context, scoreboardSubject, true); ++ } ++ ++ /** ++ * Resolves a component with a specific command sender and subject. ++ *

    ++ * Note that in Vanilla, elevated permissions are required to use ++ * '@' selectors in various component types. If the boolean {@code bypassPermissions} ++ * argument is {@code false}, the {@link CommandSender} argument will be used to query ++ * those permissions. ++ *

    ++ * A {@link CommandSender} argument is required to resolve: ++ *

      ++ *
    • {@link net.kyori.adventure.text.NBTComponent}
    • ++ *
    • {@link net.kyori.adventure.text.ScoreComponent}
    • ++ *
    • {@link net.kyori.adventure.text.SelectorComponent}
    • ++ *
    ++ * A {@link Entity} argument is optional to help resolve: ++ *
      ++ *
    • {@link net.kyori.adventure.text.ScoreComponent}
    • ++ *
    ++ * {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments. ++ * ++ * @param input the component to resolve ++ * @param context the command sender to resolve with ++ * @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s) ++ * @param bypassPermissions true to bypass permissions checks for resolving components ++ * @return the resolved component ++ * @throws IOException if a syntax error tripped during resolving ++ */ ++ @SuppressWarnings("deprecation") // using unsafe as a bridge ++ public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject, final boolean bypassPermissions) throws IOException { ++ return Bukkit.getUnsafe().resolveWithContext(input, context, scoreboardSubject, bypassPermissions); ++ } ++ ++ /** ++ * Return a component flattener that can use game data to resolve extra information about components. ++ * ++ * @return a component flattener ++ */ ++ @SuppressWarnings("deprecation") // using unsafe as a bridge ++ public static ComponentFlattener flattener() { ++ return Bukkit.getUnsafe().componentFlattener(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert components to ++ * a plain-text string. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires access to implementation details.

    ++ * ++ * @return a serializer to plain text ++ * @deprecated will be removed in adventure 5.0.0, use {@link PlainTextComponentSerializer#plainText()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.18.1") ++ public static PlainComponentSerializer plainSerializer() { ++ return Bukkit.getUnsafe().plainComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert components to ++ * a plain-text string. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires access to implementation details.

    ++ * ++ * @return a serializer to plain text ++ * @deprecated use {@link PlainTextComponentSerializer#plainText()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.18.2") ++ public static PlainTextComponentSerializer plainTextSerializer() { ++ return Bukkit.getUnsafe().plainTextSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * standard JSON serialization format using Gson. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires implementation details, such as legacy ++ * (pre-1.16) hover events.

    ++ * ++ * @return a json component serializer ++ * @deprecated use {@link GsonComponentSerializer#gson()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.18.2") ++ public static GsonComponentSerializer gsonSerializer() { ++ return Bukkit.getUnsafe().gsonComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * standard JSON serialization format using Gson, downsampling any RGB colors ++ * to their nearest {@link NamedTextColor} counterpart. ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires implementation details, such as legacy ++ * (pre-1.16) hover events.

    ++ * ++ * @return a json component serializer ++ * @deprecated use {@link GsonComponentSerializer#colorDownsamplingGson()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.18.2") ++ public static GsonComponentSerializer colorDownsamplingGsonSerializer() { ++ return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer(); ++ } ++ ++ /** ++ * Get a serializer for {@link Component}s that will convert to and from the ++ * legacy component format used by Bukkit. This serializer uses the ++ * {@link LegacyComponentSerializer.Builder#useUnusualXRepeatedCharacterHexFormat()} ++ * option to match upstream behavior. ++ * ++ *

    This legacy serializer uses the standard section symbol to mark ++ * formatting characters.

    ++ * ++ *

    Implementations may provide a serializer capable of processing any ++ * information that requires access to implementation details.

    ++ * ++ * @return a section serializer ++ * @deprecated use {@link LegacyComponentSerializer#legacySection()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.18.2") ++ public static LegacyComponentSerializer legacySectionSerializer() { ++ return Bukkit.getUnsafe().legacyComponentSerializer(); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index c869a1c0f658fa8fb6b4d15a4292f9e8b60339a3..6391011464ac0c95d4da7fb9c698f35c58b40922 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -423,7 +423,9 @@ public final class Bukkit { + * + * @param message the message + * @return the number of players ++ * @deprecated in favour of {@link Server#broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public static int broadcastMessage(@NotNull String message) { + return server.broadcastMessage(message); + } +@@ -1227,6 +1229,19 @@ public final class Bukkit { + server.shutdown(); + } + ++ // Paper start ++ /** ++ * Broadcast a message to all players. ++ *

    This value has no effect on players, they will always use their real name.

    ++ * ++ * @return the custom name ++ */ ++ net.kyori.adventure.text.@Nullable Component customName(); ++ ++ /** ++ * Sets the custom name. ++ * ++ *

    This name will be used in death messages and can be sent to the client as a nameplate over the mob.

    ++ * ++ *

    Setting the name to {@code null} will clear it.

    ++ * ++ *

    This value has no effect on players, they will always use their real name.

    ++ * ++ * @param customName the custom name to set ++ */ ++ void customName(final net.kyori.adventure.text.@Nullable Component customName); ++ // Paper end ++ + /** + * Gets the custom name on a mob or block. If there is no name this method + * will return null. +@@ -14,8 +38,10 @@ public interface Nameable { + * This value has no effect on players, they will always use their real + * name. + * ++ * @deprecated in favour of {@link #customName()} + * @return name of the mob/block or null + */ ++ @Deprecated // Paper + @Nullable + public String getCustomName(); + +@@ -28,7 +54,9 @@ public interface Nameable { + * This value has no effect on players, they will always use their real + * name. + * ++ * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} + * @param name the name to set + */ ++ @Deprecated // Paper + public void setCustomName(@Nullable String name); + } +diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java +index dd3c9dfde4152bd832096ac2ddbfe0d2f9204a8c..499c2293fe2eea3eaf7ede476e836704e13e5a02 100644 +--- a/src/main/java/org/bukkit/NamespacedKey.java ++++ b/src/main/java/org/bukkit/NamespacedKey.java +@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; + * underscores, hyphens, and forward slashes. + * + */ +-public final class NamespacedKey { ++public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key + + /** + * The namespace representing all inbuilt keys. +@@ -130,10 +130,11 @@ public final class NamespacedKey { + + @Override + public int hashCode() { +- int hash = 5; +- hash = 47 * hash + this.namespace.hashCode(); +- hash = 47 * hash + this.key.hashCode(); +- return hash; ++ // Paper start ++ int result = this.namespace.hashCode(); ++ result = (31 * result) + this.key.hashCode(); ++ return result; ++ // Paper end + } + + @Override +@@ -141,11 +142,10 @@ public final class NamespacedKey { + if (obj == null) { + return false; + } +- if (getClass() != obj.getClass()) { +- return false; +- } +- final NamespacedKey other = (NamespacedKey) obj; +- return this.namespace.equals(other.namespace) && this.key.equals(other.key); ++ // Paper start ++ if (!(obj instanceof net.kyori.adventure.key.Key key)) return false; ++ return this.namespace.equals(key.namespace()) && this.key.equals(key.value()); ++ // Paper end + } + + @Override +@@ -248,4 +248,24 @@ public final class NamespacedKey { + public static NamespacedKey fromString(@NotNull String key) { + return fromString(key, null); + } ++ ++ // Paper start ++ @NotNull ++ @Override ++ public String namespace() { ++ return this.getNamespace(); ++ } ++ ++ @NotNull ++ @Override ++ public String value() { ++ return this.getKey(); ++ } ++ ++ @NotNull ++ @Override ++ public String asString() { ++ return this.namespace + ':' + this.key; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 1fb51550953866ec9cde931987f8cfab2acc6b9b..01f8e0811f8b337acac31819a85bb44b189b3c21 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -66,13 +66,13 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a server implementation. + */ +-public interface Server extends PluginMessageRecipient { ++public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper + + /** + * Used for all administrative messages, such as an operator using a + * command. + *

    +- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. ++ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. + */ + public static final String BROADCAST_CHANNEL_ADMINISTRATIVE = "bukkit.broadcast.admin"; + +@@ -80,7 +80,7 @@ public interface Server extends PluginMessageRecipient { + * Used for all announcement messages, such as informing users that a + * player has joined. + *

    +- * For use in {@link #broadcast(java.lang.String, java.lang.String)}. ++ * For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}. + */ + public static final String BROADCAST_CHANNEL_USERS = "bukkit.broadcast.user"; + +@@ -356,7 +356,9 @@ public interface Server extends PluginMessageRecipient { + * + * @param message the message + * @return the number of players ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public int broadcastMessage(@NotNull String message); + + /** +@@ -1053,8 +1055,33 @@ public interface Server extends PluginMessageRecipient { + * @param permission the required permission {@link Permissible + * permissibles} must have to receive the broadcast + * @return number of message recipients ++ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} + */ ++ @Deprecated // Paper + public int broadcast(@NotNull String message, @NotNull String permission); ++ // Paper start ++ /** ++ * Broadcast a message to all players. ++ *

    ++ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, ++ * java.lang.String)} with the {@link #BROADCAST_CHANNEL_USERS} permission. ++ * ++ * @param message the message ++ * @return the number of players ++ */ ++ int broadcast(net.kyori.adventure.text.@NotNull Component message); ++ ++ /** ++ * Broadcasts the specified message to every user with the given ++ * permission name. ++ * ++ * @param message message to broadcast ++ * @param permission the required permission {@link Permissible ++ * permissibles} must have to receive the broadcast ++ * @return number of message recipients ++ */ ++ int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission); ++ // Paper end + + /** + * Gets the player by the given name, regardless if they are offline or +@@ -1271,6 +1298,35 @@ public interface Server extends PluginMessageRecipient { + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type); + ++ // Paper start ++ /** ++ * Creates an empty inventory with the specified type and title. If the type ++ * is {@link InventoryType#CHEST}, the new inventory has a size of 27; ++ * otherwise the new inventory has the normal size for its type.
    ++ * It should be noted that some inventory types do not support titles and ++ * may not render with said titles on the Minecraft client. ++ *
    ++ * {@link InventoryType#WORKBENCH} will not process crafting recipes if ++ * created with this method. Use ++ * {@link Player#openWorkbench(Location, boolean)} instead. ++ *
    ++ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s ++ * for possible enchanting results. Use ++ * {@link Player#openEnchanting(Location, boolean)} instead. ++ * ++ * @param owner The holder of the inventory; can be null if there's no holder. ++ * @param type The type of inventory to create. ++ * @param title The title of the inventory, to be displayed when it is viewed. ++ * @return The new inventory. ++ * @throws IllegalArgumentException if the {@link InventoryType} cannot be ++ * viewed. ++ * ++ * @see InventoryType#isCreatable() ++ */ ++ @NotNull ++ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title); ++ // Paper end ++ + /** + * Creates an empty inventory with the specified type and title. If the type + * is {@link InventoryType#CHEST}, the new inventory has a size of 27; +@@ -1292,9 +1348,11 @@ public interface Server extends PluginMessageRecipient { + * @return The new inventory. + * @throws IllegalArgumentException if the {@link InventoryType} cannot be + * viewed. ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} + * + * @see InventoryType#isCreatable() + */ ++ @Deprecated // Paper + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); + +@@ -1310,6 +1368,22 @@ public interface Server extends PluginMessageRecipient { + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; + ++ // Paper start ++ /** ++ * Creates an empty inventory of type {@link InventoryType#CHEST} with the ++ * specified size and title. ++ * ++ * @param owner the holder of the inventory, or null to indicate no holder ++ * @param size a multiple of 9 as the size of inventory to create ++ * @param title the title of the inventory, displayed when inventory is ++ * viewed ++ * @return a new inventory ++ * @throws IllegalArgumentException if the size is not a multiple of 9 ++ */ ++ @NotNull ++ Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException; ++ // Paper end ++ + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. +@@ -1320,18 +1394,32 @@ public interface Server extends PluginMessageRecipient { + * viewed + * @return a new inventory + * @throws IllegalArgumentException if the size is not a multiple of 9 ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + @NotNull + Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; + ++ // Paper start ++ /** ++ * Creates an empty merchant. ++ * ++ * @param title the title of the corresponding merchant inventory, displayed ++ * when the merchant inventory is viewed ++ * @return a new merchant ++ */ ++ @NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title); ++ // Paper start + /** + * Creates an empty merchant. + * + * @param title the title of the corresponding merchant inventory, displayed + * when the merchant inventory is viewed + * @return a new merchant ++ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} + */ + @NotNull ++ @Deprecated // Paper + Merchant createMerchant(@Nullable String title); + + /** +@@ -1427,19 +1515,46 @@ public interface Server extends PluginMessageRecipient { + */ + boolean isPrimaryThread(); + ++ // Paper start ++ /** ++ * Gets the message that is displayed on the server list. ++ * ++ * @return the server's MOTD ++ */ ++ net.kyori.adventure.text.@NotNull Component motd(); ++ ++ /** ++ * Set the message that is displayed on the server list. ++ * ++ * @param motd The message to be displayed ++ */ ++ void motd(final net.kyori.adventure.text.@NotNull Component motd); ++ ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ */ ++ net.kyori.adventure.text.@Nullable Component shutdownMessage(); ++ // Paper end ++ + /** + * Gets the message that is displayed on the server list. + * + * @return the servers MOTD ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + String getMotd(); + + /** + * Set the message that is displayed on the server list. + * + * @param motd The message to be displayed ++ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setMotd(@NotNull String motd); + + /** +@@ -1455,8 +1570,10 @@ public interface Server extends PluginMessageRecipient { + * Gets the default message that is displayed when the server is stopped. + * + * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} + */ + @Nullable ++ @Deprecated // Paper + String getShutdownMessage(); + + /** +@@ -1865,7 +1982,9 @@ public interface Server extends PluginMessageRecipient { + * Sends the component to the player + * + * @param component the components to send ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -1874,7 +1993,9 @@ public interface Server extends PluginMessageRecipient { + * Sends an array of components as a single message to the player + * + * @param components the components to send ++ * @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +diff --git a/src/main/java/org/bukkit/ServerLinks.java b/src/main/java/org/bukkit/ServerLinks.java +index 18a53194483410c4d5ad35f901c90d44efaeef60..aff43d77f31d81b82e5fc5fea6272dda24506562 100644 +--- a/src/main/java/org/bukkit/ServerLinks.java ++++ b/src/main/java/org/bukkit/ServerLinks.java +@@ -50,13 +50,27 @@ public interface ServerLinks { + @NotNull + ServerLink addLink(@NotNull Type type, @NotNull URI url); + ++ // Paper start - Adventure ++ /** ++ * Adds the given link to the list of links. ++ * ++ * @param displayName link name / display text Component ++ * @param url link url ++ * @return the added link ++ */ ++ @NotNull ++ ServerLink addLink(@NotNull net.kyori.adventure.text.Component displayName, @NotNull URI url); ++ // Paper end - Adventure ++ + /** + * Adds the given link to the list of links. + * + * @param displayName link name / display text + * @param url link url + * @return the added link ++ * @deprecated in favour of {@link ServerLinks#addLink(net.kyori.adventure.text.Component, URI)} + */ ++ @Deprecated // Paper - Adventure + @NotNull + ServerLink addLink(@NotNull String displayName, @NotNull URI url); + +@@ -89,11 +103,23 @@ public interface ServerLinks { + @Nullable + Type getType(); + ++ // Paper start - Adventure ++ /** ++ * Gets the display name/text Component of this link. ++ * ++ * @return display name Component ++ */ ++ @NotNull ++ net.kyori.adventure.text.Component displayName(); ++ // Paper end - Adventure ++ + /** + * Gets the display name/text of this link. + * + * @return display name ++ * @deprecated in favour of {@link ServerLink#displayName()} + */ ++ @Deprecated // Paper - Adventure + @NotNull + String getDisplayName(); + +diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java +index fab510afe4fa67d3171e23d739765095916197cb..779fd6dd572dea41e7e22464c9c6068a0fb71b9d 100644 +--- a/src/main/java/org/bukkit/Sound.java ++++ b/src/main/java/org/bukkit/Sound.java +@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; + * guarantee values will not be removed from this interface. As such, you should not + * depend on the ordinal values of this class. + */ +-public interface Sound extends OldEnum, Keyed { ++public interface Sound extends OldEnum, Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type + + Sound AMBIENT_BASALT_DELTAS_ADDITIONS = getSound("ambient.basalt_deltas.additions"); + Sound AMBIENT_BASALT_DELTAS_LOOP = getSound("ambient.basalt_deltas.loop"); +@@ -1713,4 +1713,11 @@ public interface Sound extends OldEnum, Keyed { + static Sound[] values() { + return Lists.newArrayList(Registry.SOUNDS).toArray(new Sound[0]); + } ++ ++ // Paper start ++ @Override ++ default net.kyori.adventure.key.@NotNull Key key() { ++ return this.getKey(); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/SoundCategory.java b/src/main/java/org/bukkit/SoundCategory.java +index ac5e263d737973af077e3406a84a84baca4370db..2d91924b7f5ef16a91d40cdc1bfc3d68e0fda38d 100644 +--- a/src/main/java/org/bukkit/SoundCategory.java ++++ b/src/main/java/org/bukkit/SoundCategory.java +@@ -3,7 +3,7 @@ package org.bukkit; + /** + * An Enum of categories for sounds. + */ +-public enum SoundCategory { ++public enum SoundCategory implements net.kyori.adventure.sound.Sound.Source.Provider { // Paper - implement Sound.Source.Provider + + MASTER, + MUSIC, +@@ -15,4 +15,22 @@ public enum SoundCategory { + PLAYERS, + AMBIENT, + VOICE; ++ ++ // Paper start - implement Sound.Source.Provider ++ @Override ++ public net.kyori.adventure.sound.Sound.@org.jetbrains.annotations.NotNull Source soundSource() { ++ return switch (this) { ++ case MASTER -> net.kyori.adventure.sound.Sound.Source.MASTER; ++ case MUSIC -> net.kyori.adventure.sound.Sound.Source.MUSIC; ++ case RECORDS -> net.kyori.adventure.sound.Sound.Source.RECORD; ++ case WEATHER -> net.kyori.adventure.sound.Sound.Source.WEATHER; ++ case BLOCKS -> net.kyori.adventure.sound.Sound.Source.BLOCK; ++ case HOSTILE -> net.kyori.adventure.sound.Sound.Source.HOSTILE; ++ case NEUTRAL -> net.kyori.adventure.sound.Sound.Source.NEUTRAL; ++ case PLAYERS -> net.kyori.adventure.sound.Sound.Source.PLAYER; ++ case AMBIENT -> net.kyori.adventure.sound.Sound.Source.AMBIENT; ++ case VOICE -> net.kyori.adventure.sound.Sound.Source.VOICE; ++ }; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index ea786130380315660a60830e9c4d00b1ccc8bb70..89d5def8c1dcdab0a9e2d1809badcbbd112c3d9c 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -31,6 +31,15 @@ import org.jetbrains.annotations.Nullable; + */ + @Deprecated(since = "1.7.2") + public interface UnsafeValues { ++ // Paper start ++ net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener(); ++ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); ++ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer plainTextSerializer(); ++ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer(); ++ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer(); ++ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer(); ++ net.kyori.adventure.text.Component resolveWithContext(net.kyori.adventure.text.Component component, org.bukkit.command.CommandSender context, org.bukkit.entity.Entity scoreboardSubject, boolean bypassPermissions) throws java.io.IOException; ++ // Paper end + + Material toLegacy(Material material); + +diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java +index 0208fc2bcd5c99c60b37419b92248db76681fc1e..5c1dda6888561a7eba0fbf9ba6ca7d7fe856eb53 100644 +--- a/src/main/java/org/bukkit/Warning.java ++++ b/src/main/java/org/bukkit/Warning.java +@@ -68,6 +68,7 @@ public @interface Warning { + * + */ + public boolean printFor(@Nullable Warning warning) { ++ if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper + if (this == DEFAULT) { + return warning == null || warning.value(); + } +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 55cfe19be7a6f4ffa8cc31f6fbfffb592d96a085..ed87e82eb0e30bdea6f7760bb80addcb3bbe59cc 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -47,7 +47,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a world, which may contain entities, chunks and blocks + */ +-public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed { ++public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed, net.kyori.adventure.audience.ForwardingAudience { // Paper + + /** + * Gets the {@link Block} at the given coordinates +@@ -644,6 +644,14 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @NotNull + public List getPlayers(); + ++ // Paper start ++ @NotNull ++ @Override ++ default Iterable audiences() { ++ return this.getPlayers(); ++ } ++ // Paper end ++ + /** + * Returns a list of entities within a bounding box centered around a + * Location. +diff --git a/src/main/java/org/bukkit/block/CommandBlock.java b/src/main/java/org/bukkit/block/CommandBlock.java +index 372c0bd5a4d7800a11c24c95e39fe376a96232bf..9c88be68b4f403d0500cb607394b3a1646675ef7 100644 +--- a/src/main/java/org/bukkit/block/CommandBlock.java ++++ b/src/main/java/org/bukkit/block/CommandBlock.java +@@ -33,7 +33,9 @@ public interface CommandBlock extends TileState { + * by default is "@". + * + * @return Name of this CommandBlock. ++ * @deprecated in favour of {@link #name()} + */ ++ @Deprecated // Paper + @NotNull + public String getName(); + +@@ -43,6 +45,28 @@ public interface CommandBlock extends TileState { + * same as setting it to "@". + * + * @param name New name for this CommandBlock. ++ * @deprecated in favour of {@link #name(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setName(@Nullable String name); ++ ++ // Paper start ++ /** ++ * Gets the name of this CommandBlock. The name is used with commands ++ * that this CommandBlock executes. This name will never be null, and ++ * by default is a {@link net.kyori.adventure.text.TextComponent} containing {@code @}. ++ * ++ * @return Name of this CommandBlock. ++ */ ++ public net.kyori.adventure.text.@NotNull Component name(); ++ ++ /** ++ * Sets the name of this CommandBlock. The name is used with commands ++ * that this CommandBlock executes. Setting the name to null is the ++ * same as setting it to a {@link net.kyori.adventure.text.TextComponent} containing {@code @}. ++ * ++ * @param name New name for this CommandBlock. ++ */ ++ public void name(net.kyori.adventure.text.@Nullable Component name); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java +index 5aa7148dd24009564f1e6f07007a7a921eec6a39..be36f722c7e465fae09ae7c99d92bfa032b66cc3 100644 +--- a/src/main/java/org/bukkit/block/Sign.java ++++ b/src/main/java/org/bukkit/block/Sign.java +@@ -12,12 +12,51 @@ import org.jetbrains.annotations.Nullable; + * Represents a captured state of either a SignPost or a WallSign. + */ + public interface Sign extends TileState, Colorable { ++ // Paper start ++ /** ++ * Gets all the lines of text currently on the {@link Side#FRONT} of this sign. ++ * ++ * @return List of components containing each line of text ++ * @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}. ++ */ ++ @NotNull ++ @Deprecated ++ public java.util.List lines(); ++ ++ /** ++ * Gets the line of text at the specified index on the {@link Side#FRONT}. ++ *

    ++ * For example, getLine(0) will return the first line of text. ++ * ++ * @param index Line number to get the text from, starting at 0 ++ * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @return Text on the given line ++ * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}. ++ */ ++ @NotNull ++ @Deprecated ++ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; ++ ++ /** ++ * Sets the line of text at the specified index on the {@link Side#FRONT}. ++ *

    ++ * For example, setLine(0, "Line One") will set the first line of text to ++ * "Line One". ++ * ++ * @param index Line number to set the text at, starting from 0 ++ * @param line New text to set at the specified index ++ * @throws IndexOutOfBoundsException If the index is out of the range 0..3 ++ * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}. ++ */ ++ @Deprecated ++ public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException; ++ // Paper end + + /** + * Gets all the lines of text currently on the {@link Side#FRONT} of this sign. + * + * @return Array of Strings containing each line of text +- * @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#getLines()}. ++ * @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}. + */ + @Deprecated(since = "1.20") + @NotNull +@@ -31,7 +70,7 @@ public interface Sign extends TileState, Colorable { + * @param index Line number to get the text from, starting at 0 + * @return Text on the given line + * @throws IndexOutOfBoundsException Thrown when the line does not exist +- * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#getLine(int)}. ++ * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}. + */ + @Deprecated(since = "1.20") + @NotNull +@@ -46,7 +85,7 @@ public interface Sign extends TileState, Colorable { + * @param index Line number to set the text at, starting from 0 + * @param line New text to set at the specified index + * @throws IndexOutOfBoundsException If the index is out of the range 0..3 +- * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setLine(int, String)}. ++ * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}. + */ + @Deprecated(since = "1.20") + public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; +diff --git a/src/main/java/org/bukkit/block/sign/SignSide.java b/src/main/java/org/bukkit/block/sign/SignSide.java +index 0f4ae7bd2ad379b5edb40f49f93de9e18c38f415..575e545a69b5279b90067d7ebee08b7b59288496 100644 +--- a/src/main/java/org/bukkit/block/sign/SignSide.java ++++ b/src/main/java/org/bukkit/block/sign/SignSide.java +@@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; + * Represents a side of a sign. + */ + public interface SignSide extends Colorable { ++ // Paper start ++ /** ++ * Gets all the lines of text currently on the sign. ++ * ++ * @return List of components containing each line of text ++ */ ++ @NotNull ++ public java.util.List lines(); ++ ++ /** ++ * Gets the line of text at the specified index. ++ *

    ++ * For example, getLine(0) will return the first line of text. ++ * ++ * @param index Line number to get the text from, starting at 0 ++ * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @return Text on the given line ++ */ ++ @NotNull ++ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; ++ ++ /** ++ * Sets the line of text at the specified index. ++ *

    ++ * For example, setLine(0, "Line One") will set the first line of text to ++ * "Line One". ++ * ++ * @param index Line number to set the text at, starting from 0 ++ * @param line New text to set at the specified index ++ * @throws IndexOutOfBoundsException If the index is out of the range 0..3 ++ */ ++ public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException; ++ // Paper end + + /** + * Gets all the lines of text currently on this side of the sign. + * + * @return Array of Strings containing each line of text ++ * @deprecated in favour of {@link #lines()} + */ + @NotNull ++ @Deprecated // Paper + public String[] getLines(); + + /** +@@ -24,8 +59,10 @@ public interface SignSide extends Colorable { + * @param index Line number to get the text from, starting at 0 + * @return Text on the given line + * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @deprecated in favour of {@link #line(int)} + */ + @NotNull ++ @Deprecated // Paper + public String getLine(int index) throws IndexOutOfBoundsException; + + /** +@@ -37,7 +74,9 @@ public interface SignSide extends Colorable { + * @param index Line number to set the text at, starting from 0 + * @param line New text to set at the specified index + * @throws IndexOutOfBoundsException If the index is out of the range 0..3 ++ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; + + /** +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 9019ebeefc9492d7c982b09fc9438d58c4233df0..6686d025222dc50156347a1757c88da02f882eec 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -32,7 +32,7 @@ public abstract class Command { + protected String description; + protected String usageMessage; + private String permission; +- private String permissionMessage; ++ private net.kyori.adventure.text.Component permissionMessage; // Paper + public org.spigotmc.CustomTimingsHandler timings; // Spigot + + protected Command(@NotNull String name) { +@@ -186,10 +186,10 @@ public abstract class Command { + + if (permissionMessage == null) { + target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake."); +- } else if (permissionMessage.length() != 0) { +- for (String line : permissionMessage.replace("", permission).split("\n")) { +- target.sendMessage(line); +- } ++ // Paper start - use components for permissionMessage ++ } else if (!permissionMessage.equals(net.kyori.adventure.text.Component.empty())) { ++ target.sendMessage(permissionMessage.replaceText(net.kyori.adventure.text.TextReplacementConfig.builder().matchLiteral("").replacement(permission).build())); ++ // Paper end + } + + return false; +@@ -327,7 +327,7 @@ public abstract class Command { + @Deprecated(since = "1.20.4") + @Nullable + public String getPermissionMessage() { +- return permissionMessage; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serializeOrNull(permissionMessage); // Paper + } + + /** +@@ -398,7 +398,7 @@ public abstract class Command { + @Deprecated(since = "1.20.4") + @NotNull + public Command setPermissionMessage(@Nullable String permissionMessage) { +- this.permissionMessage = permissionMessage; ++ this.permissionMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(permissionMessage); // Paper + return this; + } + +@@ -413,13 +413,61 @@ public abstract class Command { + this.usageMessage = (usage == null) ? "" : usage; + return this; + } ++ // Paper start ++ /** ++ * Gets the permission message. ++ * ++ * @return the permission message ++ * @deprecated permission messages have not worked for player-executed ++ * commands since 1.13 as clients without permission to execute a command ++ * are unaware of its existence and therefore will not send an unknown ++ * command execution to the server. This message will only ever be shown to ++ * consoles or when this command is executed with ++ * {@link Bukkit#dispatchCommand(CommandSender, String)}. ++ */ ++ @Deprecated ++ public net.kyori.adventure.text.@Nullable Component permissionMessage() { ++ return this.permissionMessage; ++ } ++ ++ /** ++ * Sets the permission message. ++ * ++ * @param permissionMessage the permission message ++ * @deprecated permission messages have not worked for player-executed ++ * commands since 1.13 as clients without permission to execute a command ++ * are unaware of its existence and therefore will not send an unknown ++ * command execution to the server. This message will only ever be shown to ++ * consoles or when this command is executed with ++ * {@link Bukkit#dispatchCommand(CommandSender, String)}. ++ */ ++ @Deprecated ++ public void permissionMessage(net.kyori.adventure.text.@Nullable Component permissionMessage) { ++ this.permissionMessage = permissionMessage; ++ } ++ // Paper end + + public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull String message) { + broadcastCommandMessage(source, message, true); + } + + public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull String message, boolean sendToSource) { +- String result = source.getName() + ": " + message; ++ // Paper start ++ broadcastCommandMessage(source, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message), sendToSource); ++ } ++ ++ public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message) { ++ broadcastCommandMessage(source, message, true); ++ } ++ ++ public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message, boolean sendToSource) { ++ net.kyori.adventure.text.TextComponent.Builder result = net.kyori.adventure.text.Component.text() ++ .color(net.kyori.adventure.text.format.NamedTextColor.WHITE) ++ .decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false) ++ .append(source.name()) ++ .append(net.kyori.adventure.text.Component.text(": ")) ++ .append(message); ++ // Paper end + + if (source instanceof BlockCommandSender) { + BlockCommandSender blockCommandSender = (BlockCommandSender) source; +@@ -438,7 +486,12 @@ public abstract class Command { + } + + Set users = Bukkit.getPluginManager().getPermissionSubscriptions(Server.BROADCAST_CHANNEL_ADMINISTRATIVE); +- String colored = ChatColor.GRAY + "" + ChatColor.ITALIC + "[" + result + ChatColor.GRAY + ChatColor.ITALIC + "]"; ++ // Paper start ++ net.kyori.adventure.text.TextComponent.Builder colored = net.kyori.adventure.text.Component.text() ++ .color(net.kyori.adventure.text.format.NamedTextColor.GRAY) ++ .decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC) ++ .append(net.kyori.adventure.text.Component.text("["), result, net.kyori.adventure.text.Component.text("]")); ++ // Paper end + + if (sendToSource && !(source instanceof ConsoleCommandSender)) { + source.sendMessage(message); +diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java +index 284be63a125624a8ae43d2c164aede810ce6bfe5..70fec73328227725f519af845ecbdce8be2fa4e2 100644 +--- a/src/main/java/org/bukkit/command/CommandSender.java ++++ b/src/main/java/org/bukkit/command/CommandSender.java +@@ -6,20 +6,28 @@ import org.bukkit.permissions.Permissible; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-public interface CommandSender extends Permissible { ++public interface CommandSender extends net.kyori.adventure.audience.Audience, Permissible { // Paper + + /** + * Sends this sender a message + * + * @param message Message to be displayed ++ * @see #sendMessage(net.kyori.adventure.text.Component) ++ * @see #sendPlainMessage(String) ++ * @see #sendRichMessage(String) + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete // Paper + public void sendMessage(@NotNull String message); + + /** + * Sends this sender multiple messages + * + * @param messages An array of messages to be displayed ++ * @see #sendMessage(net.kyori.adventure.text.Component) ++ * @see #sendPlainMessage(String) ++ * @see #sendRichMessage(String) + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete // Paper + public void sendMessage(@NotNull String... messages); + + /** +@@ -27,7 +35,10 @@ public interface CommandSender extends Permissible { + * + * @param message Message to be displayed + * @param sender The sender of this message ++ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) ++ * @deprecated sender UUID is ignored + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull String message); + + /** +@@ -35,7 +46,10 @@ public interface CommandSender extends Permissible { + * + * @param messages An array of messages to be displayed + * @param sender The sender of this message ++ * @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component) ++ * @deprecated sender UUID is ignored + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull String... messages); + + /** +@@ -61,7 +75,9 @@ public interface CommandSender extends Permissible { + * Sends this sender a chat component. + * + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -70,7 +86,9 @@ public interface CommandSender extends Permissible { + * Sends an array of components as a single message to the sender. + * + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -80,7 +98,9 @@ public interface CommandSender extends Permissible { + * + * @param component the components to send + * @param sender the sender of the message ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -90,7 +110,9 @@ public interface CommandSender extends Permissible { + * + * @param components the components to send + * @param sender the sender of the message ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -99,4 +121,52 @@ public interface CommandSender extends Permissible { + @NotNull + Spigot spigot(); + // Spigot end ++ ++ // Paper start ++ /** ++ * Gets the name of this command sender ++ * ++ * @return Name of the sender ++ */ ++ public net.kyori.adventure.text.@NotNull Component name(); ++ ++ @Override ++ default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity identity, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) { ++ this.sendMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(message)); ++ } ++ ++ /** ++ * Sends a message with the MiniMessage format to the command sender. ++ *

    ++ * See MiniMessage docs ++ * for more information on the format. ++ * ++ * @param message MiniMessage content ++ */ ++ default void sendRichMessage(final @NotNull String message) { ++ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message)); ++ } ++ ++ /** ++ * Sends a message with the MiniMessage format to the command sender. ++ *

    ++ * See MiniMessage docs and MiniMessage Placeholders docs ++ * for more information on the format. ++ * ++ * @param message MiniMessage content ++ * @param resolvers resolvers to use ++ */ ++ default void sendRichMessage(final @NotNull String message, final net.kyori.adventure.text.minimessage.tag.resolver.@NotNull TagResolver... resolvers) { ++ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message, resolvers)); ++ } ++ ++ /** ++ * Sends a plain message to the command sender. ++ * ++ * @param message plain message ++ */ ++ default void sendPlainMessage(final @NotNull String message) { ++ this.sendMessage(net.kyori.adventure.text.Component.text(message)); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/PluginCommandYamlParser.java b/src/main/java/org/bukkit/command/PluginCommandYamlParser.java +index a542c4bb3c973bbe4b976642feccde6a4d90cb7b..ef870b864c1e36032b54b31f3f85707edc06d764 100644 +--- a/src/main/java/org/bukkit/command/PluginCommandYamlParser.java ++++ b/src/main/java/org/bukkit/command/PluginCommandYamlParser.java +@@ -67,7 +67,7 @@ public class PluginCommandYamlParser { + } + + if (permissionMessage != null) { +- newCmd.setPermissionMessage(permissionMessage.toString()); ++ newCmd.permissionMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(permissionMessage.toString())); // Paper + } + + pluginCmds.add(newCmd); +diff --git a/src/main/java/org/bukkit/command/ProxiedCommandSender.java b/src/main/java/org/bukkit/command/ProxiedCommandSender.java +index fcc34b640265f4dccb46b9f09466ab8e1d96043e..5c813ac024f675951159a59d88d8baa0d49840e9 100644 +--- a/src/main/java/org/bukkit/command/ProxiedCommandSender.java ++++ b/src/main/java/org/bukkit/command/ProxiedCommandSender.java +@@ -3,7 +3,7 @@ package org.bukkit.command; + + import org.jetbrains.annotations.NotNull; + +-public interface ProxiedCommandSender extends CommandSender { ++public interface ProxiedCommandSender extends CommandSender, net.kyori.adventure.audience.ForwardingAudience.Single { // Paper + + /** + * Returns the CommandSender which triggered this proxied command +@@ -21,4 +21,16 @@ public interface ProxiedCommandSender extends CommandSender { + @NotNull + CommandSender getCallee(); + ++ // Paper start ++ @Override ++ default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity source, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) { ++ net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type); ++ } ++ ++ @NotNull ++ @Override ++ default net.kyori.adventure.audience.Audience audience() { ++ return this.getCaller(); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/configuration/ConfigurationSection.java b/src/main/java/org/bukkit/configuration/ConfigurationSection.java +index b6b00af08f12f838411845e4f4e29e62826dfc7f..d168b1e58b4b4ad00466fab60232d516551668e0 100644 +--- a/src/main/java/org/bukkit/configuration/ConfigurationSection.java ++++ b/src/main/java/org/bukkit/configuration/ConfigurationSection.java +@@ -1058,4 +1058,98 @@ public interface ConfigurationSection { + * one line. + */ + public void setInlineComments(@NotNull String path, @Nullable List comments); ++ ++ // Paper start - add rich message component support to configuration ++ /** ++ * Gets the requested MiniMessage formatted String as Component by path. ++ *

    ++ * If the Component does not exist but a default value has been specified, ++ * this will return the default value. If the Component does not exist and no ++ * default value was specified, this will return null. ++ * ++ * @param path Path of the Component to get. ++ * @return Requested Component. ++ */ ++ default net.kyori.adventure.text.@Nullable Component getRichMessage(final @NotNull String path) { ++ return this.getRichMessage(path, null); ++ } ++ ++ /** ++ * Gets the requested MiniMessage formatted String as Component by path. ++ *

    ++ * If the Component does not exist but a default value has been specified, ++ * this will return the default value. If the Component does not exist and no ++ * default value was specified, this will return null. ++ * ++ * @param path Path of the Component to get. ++ * @param fallback component that will be used as fallback ++ * @return Requested Component. ++ */ ++ @Contract("_, !null -> !null") ++ default net.kyori.adventure.text.@Nullable Component getRichMessage(final @NotNull String path, final net.kyori.adventure.text.@Nullable Component fallback) { ++ return this.getComponent(path, net.kyori.adventure.text.minimessage.MiniMessage.miniMessage(), fallback); ++ } ++ ++ /** ++ * Sets the specified path to the given value. ++ *

    ++ * If value is null, the entry will be removed. Any existing entry will be ++ * replaced, regardless of what the new value is. ++ * ++ * @param path Path of the object to set. ++ * @param value New value to set the path to. ++ */ ++ default void setRichMessage(final @NotNull String path, final net.kyori.adventure.text.@Nullable Component value) { ++ this.setComponent(path, net.kyori.adventure.text.minimessage.MiniMessage.miniMessage(), value); ++ } ++ ++ /** ++ * Gets the requested formatted String as Component by path deserialized by the ComponentDecoder. ++ *

    ++ * If the Component does not exist but a default value has been specified, ++ * this will return the default value. If the Component does not exist and no ++ * default value was specified, this will return null. ++ * ++ * @param path Path of the Component to get. ++ * @param decoder ComponentDecoder instance used for deserialization ++ * @return Requested Component. ++ */ ++ default @Nullable C getComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentDecoder decoder) { ++ return this.getComponent(path, decoder, null); ++ } ++ ++ /** ++ * Gets the requested formatted String as Component by path deserialized by the ComponentDecoder. ++ *

    ++ * If the Component does not exist but a default value has been specified, ++ * this will return the default value. If the Component does not exist and no ++ * default value was specified, this will return null. ++ * ++ * @param path Path of the Component to get. ++ * @param decoder ComponentDecoder instance used for deserialization ++ * @param fallback component that will be used as fallback ++ * @return Requested Component. ++ */ ++ @Contract("_, _, !null -> !null") ++ default @Nullable C getComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentDecoder decoder, final @Nullable C fallback) { ++ java.util.Objects.requireNonNull(decoder, "decoder"); ++ final String value = this.getString(path); ++ return decoder.deserializeOr(value, fallback); ++ } ++ ++ /** ++ * Sets the specified path to the given value. ++ *

    ++ * If value is null, the entry will be removed. Any existing entry will be ++ * replaced, regardless of what the new value is. ++ * ++ * @param path Path of the object to set. ++ * @param encoder the encoder used to transform the value ++ * @param value New value to set the path to. ++ */ ++ default void setComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentEncoder encoder, final @Nullable C value) { ++ java.util.Objects.requireNonNull(encoder, "encoder"); ++ this.set(path, encoder.serializeOrNull(value)); ++ } ++ // Paper end - add rich message component support to configuration + } +diff --git a/src/main/java/org/bukkit/conversations/Conversable.java b/src/main/java/org/bukkit/conversations/Conversable.java +index b7d8dd30360a38dbdc7bbce40c8e6ced7261f833..0817f2395c2b18828565435568ce651f5ba99a99 100644 +--- a/src/main/java/org/bukkit/conversations/Conversable.java ++++ b/src/main/java/org/bukkit/conversations/Conversable.java +@@ -55,6 +55,7 @@ public interface Conversable { + * + * @param message Message to be displayed + */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete // Paper + public void sendRawMessage(@NotNull String message); + + /** +@@ -62,6 +63,8 @@ public interface Conversable { + * + * @param message Message to be displayed + * @param sender The sender of this message ++ * @deprecated sender UUID is ignored + */ ++ @Deprecated // Paper + public void sendRawMessage(@Nullable UUID sender, @NotNull String message); + } +diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java +index e560a13a1b2f51da041aa58082800d47cf6eddae..4d8defb32544c4cb972d257f58e4eabbc14a2176 100644 +--- a/src/main/java/org/bukkit/enchantments/Enchantment.java ++++ b/src/main/java/org/bukkit/enchantments/Enchantment.java +@@ -310,6 +310,19 @@ public abstract class Enchantment implements Keyed, Translatable { + * @return True if the enchantment may be applied, otherwise False + */ + public abstract boolean canEnchantItem(@NotNull ItemStack item); ++ // Paper start ++ /** ++ * Get the name of the enchantment with its applied level. ++ *

    ++ * If the given {@code level} is either less than the {@link #getStartLevel()} or greater than the {@link #getMaxLevel()}, ++ * the level may not be shown in the numeral format one may otherwise expect. ++ *

    ++ * ++ * @param level the level of the enchantment to show ++ * @return the name of the enchantment with {@code level} applied ++ */ ++ public abstract net.kyori.adventure.text.@NotNull Component displayName(int level); ++ // Paper end + + /** + * Gets the Enchantment at the specified key +diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +index ac3a61fb5d81c73326d3c313dc4b8b02ea322d42..865ab3d2015e114d3cac72e0e26e4086a3913b38 100644 +--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java ++++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +@@ -20,4 +20,11 @@ public abstract class EnchantmentWrapper extends Enchantment { + public Enchantment getEnchantment() { + return this; + } ++ // Paper start ++ @NotNull ++ @Override ++ public net.kyori.adventure.text.Component displayName(int level) { ++ return getEnchantment().displayName(level); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index a4cf548b5f1e182282483a89a447a6616faf1f25..d7f95863922bf332c674d538eb187015fadae9d8 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable; + * Not all methods are guaranteed to work/may have side effects when + * {@link #isInWorld()} is false. + */ +-public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder { ++public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource, net.kyori.adventure.sound.Sound.Emitter { // Paper + + /** + * Gets the entity's current position +@@ -776,4 +776,20 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + @Override + Spigot spigot(); + // Spigot end ++ ++ // Paper start ++ /** ++ * Gets the entity's display name formatted with their team prefix/suffix and ++ * the entity's default hover/click events. ++ * ++ * @return the team display name ++ */ ++ net.kyori.adventure.text.@NotNull Component teamDisplayName(); ++ ++ @NotNull ++ @Override ++ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 299c3d4c91341b91da8675d741ba2254db337640..64d32c377d0303ed28011a5f002274de3c16b383 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -58,7 +58,41 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a player, connected or not + */ +-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient { ++public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer { // Paper ++ ++ // Paper start ++ @Override ++ default net.kyori.adventure.identity.@NotNull Identity identity() { ++ return net.kyori.adventure.identity.Identity.identity(this.getUniqueId()); ++ } ++ ++ /** ++ * Gets an unmodifiable view of all known currently active bossbars. ++ *

    ++ * This currently only returns bossbars shown to the player via ++ * {@link #showBossBar(net.kyori.adventure.bossbar.BossBar)} and does not contain bukkit ++ * {@link org.bukkit.boss.BossBar} instances shown to the player. ++ * ++ * @return an unmodifiable view of all known currently active bossbars ++ * @since 4.14.0 ++ */ ++ @Override ++ @org.jetbrains.annotations.UnmodifiableView @NotNull Iterable activeBossBars(); ++ ++ /** ++ * Gets the "friendly" name to display of this player. ++ * ++ * @return the display name ++ */ ++ net.kyori.adventure.text.@NotNull Component displayName(); ++ ++ /** ++ * Sets the "friendly" name to display of this player. ++ * ++ * @param displayName the display name to set ++ */ ++ void displayName(final net.kyori.adventure.text.@Nullable Component displayName); ++ // Paper end + + /** + * {@inheritDoc} +@@ -75,7 +109,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * places defined by plugins. + * + * @return the friendly name ++ * @deprecated in favour of {@link #displayName()} + */ ++ @Deprecated // Paper + @NotNull + public String getDisplayName(); + +@@ -87,15 +123,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * places defined by plugins. + * + * @param name The new display name. ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setDisplayName(@Nullable String name); + ++ // Paper start ++ /** ++ * Sets the name that is shown on the in-game player list. ++ *

    ++ * If the value is null, the name will be identical to {@link #getName()}. ++ * ++ * @param name new player list name ++ */ ++ void playerListName(net.kyori.adventure.text.@Nullable Component name); ++ ++ /** ++ * Gets the name that is shown on the in-game player list. ++ * ++ * @return the player list name ++ */ ++ net.kyori.adventure.text.@NotNull Component playerListName(); ++ ++ /** ++ * Gets the currently displayed player list header for this player. ++ * ++ * @return player list header or null ++ */ ++ net.kyori.adventure.text.@Nullable Component playerListHeader(); ++ ++ /** ++ * Gets the currently displayed player list footer for this player. ++ * ++ * @return player list footer or null ++ */ ++ net.kyori.adventure.text.@Nullable Component playerListFooter(); ++ // Paper end + /** + * Gets the name that is shown on the player list. + * + * @return the player list name ++ * @deprecated in favour of {@link #playerListName()} + */ + @NotNull ++ @Deprecated // Paper + public String getPlayerListName(); + + /** +@@ -104,7 +175,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * If the value is null, the name will be identical to {@link #getName()}. + * + * @param name new player list name ++ * @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListName(@Nullable String name); + + /** +@@ -126,7 +199,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Gets the currently displayed player list header for this player. + * + * @return player list header or null ++ * @deprecated in favour of {@link #playerListHeader()} + */ ++ @Deprecated // Paper + @Nullable + public String getPlayerListHeader(); + +@@ -134,7 +209,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Gets the currently displayed player list footer for this player. + * + * @return player list header or null ++ * @deprecated in favour of {@link #playerListFooter()} + */ ++ @Deprecated // Paper + @Nullable + public String getPlayerListFooter(); + +@@ -142,14 +219,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Sets the currently displayed player list header for this player. + * + * @param header player list header, null for empty ++ * @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListHeader(@Nullable String header); + + /** + * Sets the currently displayed player list footer for this player. + * + * @param footer player list footer, null for empty ++ * @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListFooter(@Nullable String footer); + + /** +@@ -158,7 +239,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param header player list header, null for empty + * @param footer player list footer, null for empty ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer); + + /** +@@ -235,9 +318,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * Kicks player with custom kick message. + * + * @param message kick message ++ * @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void kickPlayer(@Nullable String message); + ++ // Paper start ++ /** ++ * Kicks the player with the default kick message. ++ * @see #kick(net.kyori.adventure.text.Component) ++ */ ++ void kick(); ++ /** ++ * Kicks player with custom kick message. ++ * ++ * @param message kick message ++ */ ++ void kick(final net.kyori.adventure.text.@Nullable Component message); ++ // Paper end ++ + /** + * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will + * update the entry. +@@ -924,6 +1023,106 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendEquipmentChange(@NotNull LivingEntity entity, @NotNull Map items); + ++ // Paper start ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) ++ */ ++ @Deprecated ++ default void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines) throws IllegalArgumentException { ++ this.sendSignChange(loc, lines, DyeColor.BLACK); ++ } ++ ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @param dyeColor the color of the sign ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if dyeColor is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) ++ */ ++ @Deprecated ++ default void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException { ++ this.sendSignChange(loc, lines, dyeColor, false); ++ } ++ ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @param hasGlowingText whether the text of the sign should glow as if dyed with a glowing ink sac ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if dyeColor is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) ++ */ ++ @Deprecated ++ default void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, boolean hasGlowingText) throws IllegalArgumentException { ++ this.sendSignChange(loc, lines, DyeColor.BLACK, hasGlowingText); ++ } ++ ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

    ++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @param dyeColor the color of the sign ++ * @param hasGlowingText whether the text of the sign should glow as if dyed with a glowing ink sac ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if dyeColor is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) ++ */ ++ @Deprecated ++ void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor, boolean hasGlowingText) ++ throws IllegalArgumentException; ++ // Paper end ++ + /** + * Send a sign change. This fakes a sign change packet for a user at + * a certain location. This will not actually change the world in any way. +@@ -941,7 +1140,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param lines the new text on the sign or null to clear it + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) + */ ++ @Deprecated // Paper + public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; + + /** +@@ -963,7 +1166,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if dyeColor is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) + */ ++ @Deprecated // Paper + public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; + + /** +@@ -986,7 +1193,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if dyeColor is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ * @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual ++ * {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()} ++ * (constructed e.g. via {@link Material#createBlockData()}) + */ ++ @Deprecated // Paper + public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException; + + /** +@@ -1461,7 +1672,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException Thrown if the URL is null. + * @throws IllegalArgumentException Thrown if the URL is too long. + * @deprecated Minecraft no longer uses textures packs. Instead you +- * should use {@link #setResourcePack(String)}. ++ * should use {@link #setResourcePack(UUID, String, byte[], net.kyori.adventure.text.Component, boolean)}. + */ + @Deprecated(since = "1.7.2") + public void setTexturePack(@NotNull String url); +@@ -1497,7 +1708,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException Thrown if the URL is null. + * @throws IllegalArgumentException Thrown if the URL is too long. The + * length restriction is an implementation specific arbitrary value. ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + */ ++ @Deprecated // Paper - adventure + public void setResourcePack(@NotNull String url); + + /** +@@ -1529,6 +1742,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * pack correctly. + * + * ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + * @param url The URL from which the client will download the resource + * pack. The string must contain only US-ASCII characters and should + * be encoded as per RFC 1738. +@@ -1541,6 +1755,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException Thrown if the hash is not 20 bytes + * long. + */ ++ @Deprecated // Paper - adventure + public void setResourcePack(@NotNull String url, @Nullable byte[] hash); + + /** +@@ -1565,12 +1780,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! + *

  • To remove a resource pack you can use +- * {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. + *
  • The request is sent with empty string as the hash when the hash is + * not provided. This might result in newer versions not loading the + * pack correctly. + * + * ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + * @param url The URL from which the client will download the resource + * pack. The string must contain only US-ASCII characters and should + * be encoded as per RFC 1738. +@@ -1584,8 +1800,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException Thrown if the hash is not 20 bytes + * long. + */ ++ @Deprecated // Paper - adventure + public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt); + ++ // Paper start + /** + * Request that the player's client download and switch resource packs. + *

    +@@ -1608,7 +1826,54 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! + *

  • To remove a resource pack you can use +- * {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
  • The request is sent with empty string as the hash when the hash is ++ * not provided. This might result in newer versions not loading the ++ * pack correctly. ++ * ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash The sha1 hash sum of the resource pack file which is used ++ * to apply a cached version of the pack directly without downloading ++ * if it is available. Hast to be 20 bytes long! ++ * @param prompt The optional custom prompt message to be shown to client. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ * @throws IllegalArgumentException Thrown if the hash is not 20 bytes ++ * long. ++ * @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest) ++ */ ++ default void setResourcePack(final @NotNull String url, final byte @Nullable [] hash, final net.kyori.adventure.text.@Nullable Component prompt) { ++ this.setResourcePack(url, hash, prompt, false); ++ } ++ // Paper end ++ ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

    ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached a ++ * resource pack with the same hash in the past it will not download but ++ * directly apply the cached pack. If the hash is null and the client has ++ * downloaded and cached the same resource pack in the past, it will ++ * perform a file size check against the response content to determine if ++ * the resource pack has changed and needs to be downloaded again. When ++ * this request is sent for the very first time from a given server, the ++ * client will first display a confirmation GUI to the player before ++ * proceeding with the download. ++ *

    ++ * Notes: ++ *

      ++ *
    • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. Use the ++ * {@link PlayerResourcePackStatusEvent} to figure out whether or not ++ * the player loaded the pack! ++ *
    • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. + *
    • The request is sent with empty string as the hash when the hash is + * not provided. This might result in newer versions not loading the + * pack correctly. +@@ -1627,7 +1892,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * length restriction is an implementation specific arbitrary value. + * @throws IllegalArgumentException Thrown if the hash is not 20 bytes + * long. ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + */ ++ @Deprecated // Paper - adventure + public void setResourcePack(@NotNull String url, @Nullable byte[] hash, boolean force); + + /** +@@ -1652,7 +1919,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! + *
    • To remove a resource pack you can use +- * {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. + *
    • The request is sent with empty string as the hash when the hash is + * not provided. This might result in newer versions not loading the + * pack correctly. +@@ -1672,9 +1939,61 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * length restriction is an implementation specific arbitrary value. + * @throws IllegalArgumentException Thrown if the hash is not 20 bytes + * long. ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + */ ++ @Deprecated // Paper + public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); + ++ // Paper start ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached a ++ * resource pack with the same hash in the past it will not download but ++ * directly apply the cached pack. If the hash is null and the client has ++ * downloaded and cached the same resource pack in the past, it will ++ * perform a file size check against the response content to determine if ++ * the resource pack has changed and needs to be downloaded again. When ++ * this request is sent for the very first time from a given server, the ++ * client will first display a confirmation GUI with a custom prompt ++ * to the player before proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. Use the ++ * {@link PlayerResourcePackStatusEvent} to figure out whether or not ++ * the player loaded the pack! ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      • The request is sent with empty string as the hash when the hash is ++ * not provided. This might result in newer versions not loading the ++ * pack correctly. ++ *
      ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash The sha1 hash sum of the resource pack file which is used ++ * to apply a cached version of the pack directly without downloading ++ * if it is available. Hast to be 20 bytes long! ++ * @param prompt The optional custom prompt message to be shown to client. ++ * @param force If true, the client will be disconnected from the server ++ * when it declines to use the resource pack. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ * @throws IllegalArgumentException Thrown if the hash is not 20 bytes ++ * long. ++ * @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest) ++ */ ++ default void setResourcePack(final @NotNull String url, final byte @Nullable [] hash, final net.kyori.adventure.text.@Nullable Component prompt, final boolean force) { ++ this.setResourcePack(UUID.nameUUIDFromBytes(url.getBytes(java.nio.charset.StandardCharsets.UTF_8)), url, hash, prompt, force); ++ } ++ // Paper end ++ + /** + * Request that the player's client download and switch resource packs. + *

      +@@ -1697,7 +2016,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! + *

    • To remove a resource pack you can use +- * {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. + *
    • The request is sent with empty string as the hash when the hash is + * not provided. This might result in newer versions not loading the + * pack correctly. +@@ -1718,9 +2037,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * length restriction is an implementation specific arbitrary value. + * @throws IllegalArgumentException Thrown if the hash is not 20 bytes + * long. ++ * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} + */ ++ @Deprecated // Paper - adventure + public void setResourcePack(@NotNull UUID id, @NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); + ++ // Paper start ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached a ++ * resource pack with the same hash in the past it will not download but ++ * directly apply the cached pack. If the hash is null and the client has ++ * downloaded and cached the same resource pack in the past, it will ++ * perform a file size check against the response content to determine if ++ * the resource pack has changed and needs to be downloaded again. When ++ * this request is sent for the very first time from a given server, the ++ * client will first display a confirmation GUI to the player before ++ * proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. Use the ++ * {@link PlayerResourcePackStatusEvent} to figure out whether or not ++ * the player loaded the pack! ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      • The request is sent with empty string as the hash when the hash is ++ * not provided. This might result in newer versions not loading the ++ * pack correctly. ++ *
      ++ * ++ * @param uuid Unique resource pack ID. ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash The sha1 hash sum of the resource pack file which is used ++ * to apply a cached version of the pack directly without downloading ++ * if it is available. Hast to be 20 bytes long! ++ * @param prompt The optional custom prompt message to be shown to client. ++ * @param force If true, the client will be disconnected from the server ++ * when it declines to use the resource pack. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ * @throws IllegalArgumentException Thrown if the hash is not 20 bytes ++ * long. ++ * @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest) ++ */ ++ void setResourcePack(@NotNull UUID uuid, @NotNull String url, byte @Nullable [] hash, net.kyori.adventure.text.@Nullable Component prompt, boolean force); ++ // Paper end ++ + /** + * Request that the player's client download and include another resource pack. + *

      +@@ -1773,12 +2143,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param id the id of the resource pack. + * @throws IllegalArgumentException If the ID is null. ++ * @see #removeResourcePacks(UUID, UUID...) + */ + public void removeResourcePack(@NotNull UUID id); + + /** + * Request that the player's client remove all loaded resource pack sent by + * the server. ++ * @see #clearResourcePacks() + */ + public void removeResourcePacks(); + +@@ -1916,7 +2288,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param title Title text + * @param subtitle Subtitle text +- * @deprecated API behavior subject to change ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} + */ + @Deprecated(since = "1.8.7") + public void sendTitle(@Nullable String title, @Nullable String subtitle); +@@ -1935,7 +2307,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param fadeIn time in ticks for titles to fade in. Defaults to 10. + * @param stay time in ticks for titles to stay. Defaults to 70. + * @param fadeOut time in ticks for titles to fade out. Defaults to 20. ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} + */ ++ @Deprecated // Paper - Adventure + public void sendTitle(@Nullable String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut); + + /** +@@ -2210,6 +2584,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public int getClientViewDistance(); + ++ // Paper start ++ /** ++ * Gets the player's current locale. ++ * ++ * @return the player's locale ++ */ ++ @NotNull java.util.Locale locale(); ++ // Paper end + /** + * Gets the player's estimated ping in milliseconds. + * +@@ -2235,8 +2617,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * they wish. + * + * @return the player's locale ++ * @deprecated in favour of {@link #locale()} + */ + @NotNull ++ @Deprecated // Paper + public String getLocale(); + + /** +@@ -2288,6 +2672,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public boolean isAllowingServerListings(); + ++ // Paper start ++ @NotNull ++ @Override ++ default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName()))); ++ } ++ // Paper end ++ + // Spigot start + public class Spigot extends Entity.Spigot { + +@@ -2319,11 +2711,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + throw new UnsupportedOperationException("Not supported yet."); + } + ++ @Deprecated // Paper + @Override + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } + ++ @Deprecated // Paper + @Override + public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); +@@ -2334,7 +2728,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param position the screen position + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -2344,7 +2740,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param position the screen position + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -2355,7 +2753,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param position the screen position + * @param sender the sender of the message + * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -2366,7 +2766,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param position the screen position + * @param sender the sender of the message + * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} + */ ++ @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); + } +diff --git a/src/main/java/org/bukkit/entity/TextDisplay.java b/src/main/java/org/bukkit/entity/TextDisplay.java +index bbce00a6d84aaad4a0ec892ec5cb1b995a0a5a05..a8277270e81bc3d9bbc64c029fe11e3d11e1d9ac 100644 +--- a/src/main/java/org/bukkit/entity/TextDisplay.java ++++ b/src/main/java/org/bukkit/entity/TextDisplay.java +@@ -13,17 +13,37 @@ public interface TextDisplay extends Display { + * Gets the displayed text. + * + * @return the displayed text. ++ * @deprecated in favour of {@link #text()} + */ + @Nullable ++ @Deprecated // Paper + String getText(); + + /** + * Sets the displayed text. + * + * @param text the new text ++ * @deprecated in favour of {@link #text(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setText(@Nullable String text); + ++ // Paper start ++ /** ++ * Gets the displayed text. ++ * ++ * @return the displayed text ++ */ ++ net.kyori.adventure.text.@NotNull Component text(); ++ ++ /** ++ * Sets the displayed text. ++ * ++ * @param text the new text ++ */ ++ void text(net.kyori.adventure.text.@Nullable Component text); ++ // Paper end ++ + /** + * Gets the maximum line width before wrapping. + * +diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +index 63c80b4ee1f7adc8a9efc3b607993104b1991f90..91cab8b13d5bba34007f124838b32a1df58c5ac7 100644 +--- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +@@ -32,7 +32,9 @@ public interface CommandMinecart extends Minecart { + * same as setting it to "@". + * + * @param name New name for this CommandMinecart. ++ * @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setName(@Nullable String name); + + } +diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +index 5cf3a7890f0e56ded53966348752615590eb16d6..e7538a863ddb2c4283a7f1c418b2beffc8d9ae35 100644 +--- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java ++++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java +@@ -17,18 +17,38 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; + private final Player player; +- private final String[] lines; ++ private final java.util.List adventure$lines; // Paper + private final Side side; + ++ // Paper start ++ public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List adventure$lines, @NotNull Side side) { ++ super(theBlock); ++ this.player = player; ++ this.adventure$lines = adventure$lines; ++ this.side = side; ++ } ++ ++ @Deprecated ++ public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List adventure$lines) { ++ this(theBlock, player, adventure$lines, Side.FRONT); ++ } ++ // Paper end ++ + @Deprecated(since = "1.19.4") + public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) { + this(theBlock, thePlayer, theLines, Side.FRONT); + } + ++ @Deprecated // Paper + public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines, @NotNull Side side) { + super(theBlock); + this.player = thePlayer; +- this.lines = theLines; ++ // Paper start ++ this.adventure$lines = new java.util.ArrayList<>(); ++ for (String theLine : theLines) { ++ this.adventure$lines.add(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(theLine)); ++ } ++ // Paper end + this.side = side; + } + +@@ -42,14 +62,52 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + return player; + } + ++ // Paper start ++ /** ++ * Gets all of the lines of text from the sign involved in this event. ++ * ++ * @return the String array for the sign's lines new text ++ */ ++ public @NotNull java.util.List lines() { ++ return this.adventure$lines; ++ } ++ ++ /** ++ * Gets a single line of text from the sign involved in this event. ++ * ++ * @param index index of the line to get ++ * @return the String containing the line of text associated with the ++ * provided index ++ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 ++ * or < 0} ++ */ ++ public net.kyori.adventure.text.@Nullable Component line(int index) throws IndexOutOfBoundsException { ++ return this.adventure$lines.get(index); ++ } ++ ++ /** ++ * Sets a single line for the sign involved in this event ++ * ++ * @param index index of the line to set ++ * @param line text to set ++ * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 ++ * or < 0} ++ */ ++ public void line(int index, net.kyori.adventure.text.@Nullable Component line) throws IndexOutOfBoundsException { ++ this.adventure$lines.set(index, line); ++ } ++ // Paper end ++ + /** + * Gets all of the lines of text from the sign involved in this event. + * + * @return the String array for the sign's lines new text ++ * @deprecated in favour of {@link #lines()} + */ + @NotNull ++ @Deprecated // Paper + public String[] getLines() { +- return lines; ++ return adventure$lines.stream().map(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()::serialize).toArray(String[]::new); // Paper + } + + /** +@@ -60,10 +118,12 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * provided index + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} ++ * @deprecated in favour of {@link #line(int)} + */ + @Nullable ++ @Deprecated // Paper + public String getLine(int index) throws IndexOutOfBoundsException { +- return lines[index]; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.adventure$lines.get(index)); // Paper + } + + /** +@@ -73,9 +133,11 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * @param line text to set + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} ++ * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { +- lines[index] = line; ++ adventure$lines.set(index, line != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line) : null); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +index 133760be6c73436512ba684a3ac77a514b2d8765..9473303bd8ab1f6b63b6999a5f5ff3eca1cc23d6 100644 +--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +@@ -12,26 +12,49 @@ import org.jetbrains.annotations.Nullable; + */ + public class PlayerDeathEvent extends EntityDeathEvent { + private int newExp = 0; +- private String deathMessage = ""; ++ private net.kyori.adventure.text.Component deathMessage; // Paper - adventure + private int newLevel = 0; + private int newTotalExp = 0; + private boolean keepLevel = false; + private boolean keepInventory = false; ++ // Paper start - adventure ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final @Nullable net.kyori.adventure.text.Component deathMessage) { ++ this(player, damageSource, drops, droppedExp, 0, deathMessage); ++ } ++ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final @Nullable net.kyori.adventure.text.Component deathMessage) { ++ this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage); ++ } ++ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable net.kyori.adventure.text.Component deathMessage) { ++ super(player, damageSource, drops, droppedExp); ++ this.newExp = newExp; ++ this.newTotalExp = newTotalExp; ++ this.newLevel = newLevel; ++ this.deathMessage = deathMessage; ++ } ++ // Paper end - adventure + ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp, @Nullable final String deathMessage) { + this(player, damageSource, drops, droppedExp, 0, deathMessage); + } + ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) { + this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage); + } + ++ @Deprecated // Paper + public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) { + super(player, damageSource, drops, droppedExp); + this.newExp = newExp; + this.newTotalExp = newTotalExp; + this.newLevel = newLevel; +- this.deathMessage = deathMessage; ++ this.deathMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); // Paper + } + + @NotNull +@@ -40,25 +63,49 @@ public class PlayerDeathEvent extends EntityDeathEvent { + return (Player) entity; + } + ++ // Paper start - adventure ++ /** ++ * Set the death message that will appear to everyone on the server. ++ * ++ * @param deathMessage Component message to appear to other players on the server. ++ */ ++ public void deathMessage(final net.kyori.adventure.text.@Nullable Component deathMessage) { ++ this.deathMessage = deathMessage; ++ } ++ ++ /** ++ * Get the death message that will appear to everyone on the server. ++ * ++ * @return Component message to appear to other players on the server. ++ */ ++ public net.kyori.adventure.text.@Nullable Component deathMessage() { ++ return this.deathMessage; ++ } ++ // Paper end - adventure ++ + /** + * Set the death message that will appear to everyone on the server. + * + * @param deathMessage Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setDeathMessage(@Nullable String deathMessage) { +- this.deathMessage = deathMessage; ++ this.deathMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); // Paper + } + + /** + * Get the death message that will appear to everyone on the server. + * + * @return Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getDeathMessage() { +- return deathMessage; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serializeOrNull(this.deathMessage); // Paper + } +- ++ // Paper end + /** + * Gets how much EXP the Player should have at respawn. + *

      +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java +index c2af9a9832fb7c3ebb397a4c5fb8604b90216f0c..f80d5bc893efd8846365b4677ef1407158b1abc8 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java +@@ -163,7 +163,18 @@ public enum InventoryType { + private final String title; + private final MenuType menuType; + private final boolean isCreatable; ++ // Paper start ++ private final net.kyori.adventure.text.Component defaultTitleComponent; + ++ /** ++ * Gets the inventory's default title. ++ * ++ * @return the inventory's default title ++ */ ++ public net.kyori.adventure.text.@NotNull Component defaultTitle() { ++ return defaultTitleComponent; ++ } ++ // Paper end + private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, @Nullable MenuType type) { + this(defaultSize, defaultTitle, type, true); + } +@@ -173,6 +184,7 @@ public enum InventoryType { + title = defaultTitle; + this.menuType = type; + this.isCreatable = isCreatable; ++ this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure + } + + public int getDefaultSize() { +@@ -180,6 +192,7 @@ public enum InventoryType { + } + + @NotNull ++ @Deprecated // Paper + public String getDefaultTitle() { + return title; + } +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java +index 9c68c3f2d61500479f48b80264f625aaae2f3204..399afcd19fcb6acd24857ed6ab48cf0d105a01a3 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java +@@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull; + *

      + * Care should be taken to check {@link #isAsynchronous()} and treat the event + * appropriately. ++ * ++ * @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead + */ ++@Deprecated // Paper ++@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper + public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; +diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +index 23257ae3953d1aa5ba96c69485a5e3d7889ad8de..b2f32debd32f78e7df4851866a47da3ff0d1f015 100644 +--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java +@@ -10,11 +10,18 @@ import org.jetbrains.annotations.NotNull; + * Stores details for players attempting to log in. + *

      + * This event is asynchronous, and not run using main thread. ++ *

      ++ * When this event is fired, the player's locale is not ++ * available. Therefore, any translatable component will be ++ * rendered with the default locale, {@link java.util.Locale#US}. ++ *

      ++ * Consider rendering any translatable yourself with {@link net.kyori.adventure.translation.GlobalTranslator#render} ++ * if the client's language is known. + */ + public class AsyncPlayerPreLoginEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Result result; +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final String name; + private final InetAddress ipAddress; + private final UUID uniqueId; +@@ -33,7 +40,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, boolean transferred) { + super(true); + this.result = Result.ALLOWED; +- this.message = ""; ++ this.message = net.kyori.adventure.text.Component.empty(); // Paper + this.name = name; + this.ipAddress = ipAddress; + this.uniqueId = uniqueId; +@@ -86,6 +93,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + this.result = result == null ? null : Result.valueOf(result.name()); + } + ++ // Paper start + /** + * Gets the current kick message that will be used if getResult() != + * Result.ALLOWED +@@ -93,7 +101,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + * @return Current kick message + */ + @NotNull +- public String getKickMessage() { ++ public net.kyori.adventure.text.Component kickMessage() { + return message; + } + +@@ -102,16 +110,66 @@ public class AsyncPlayerPreLoginEvent extends Event { + * + * @param message New kick message + */ +- public void setKickMessage(@NotNull final String message) { ++ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { ++ this.message = message; ++ } ++ ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result; ++ this.message = message; ++ } ++ ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ * @deprecated This method uses a deprecated enum from {@link ++ * PlayerPreLoginEvent} ++ * @see #disallow(Result, String) ++ */ ++ @Deprecated ++ public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result == null ? null : Result.valueOf(result.name()); + this.message = message; + } ++ // Paper end ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} ++ */ ++ @NotNull ++ @Deprecated // Paper ++ public String getKickMessage() { ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ public void setKickMessage(@NotNull final String message) { ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper ++ } + + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -119,10 +177,12 @@ public class AsyncPlayerPreLoginEvent extends Event { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void disallow(@NotNull final Result result, @NotNull final String message) { + this.result = result; +- this.message = message; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + + /** +@@ -137,7 +197,7 @@ public class AsyncPlayerPreLoginEvent extends Event { + @Deprecated(since = "1.3.2") + public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) { + this.result = result == null ? null : Result.valueOf(result.name()); +- this.message = message; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java +index eb1018a84aac4f8265f3f848fa6f78781d85de4f..373162d96fbf65286adf35a1c32031e1ac846346 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java +@@ -12,12 +12,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Holds information for player chat and commands + * +- * @deprecated This event will fire from the main thread and allows the use of +- * all of the Bukkit API, unlike the {@link AsyncPlayerChatEvent}. +- *

      +- * Listening to this event forces chat to wait for the main thread which +- * causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged +- * alternative for thread safe implementations. ++ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link io.papermc.paper.event.player.AsyncChatEvent} instead, wherever possible. + */ + @Deprecated(since = "1.3.1") + @Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.") +diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java +index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a1290af3fd6d 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java +@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event { + player = who; + } + +- PlayerEvent(@NotNull final Player who, boolean async) { ++ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public + super(async); + player = who; + +diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java +index d06684aba7688ce06777dbd837a46856a9d7767f..3e1e7cd0415509da4dd887db59efa55011b1dab4 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java +@@ -10,30 +10,60 @@ import org.jetbrains.annotations.Nullable; + */ + public class PlayerJoinEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); +- private String joinMessage; ++ // Paper start ++ private net.kyori.adventure.text.Component joinMessage; ++ public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) { ++ super(playerJoined); ++ this.joinMessage = joinMessage; ++ } + ++ @Deprecated // Paper end + public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { + super(playerJoined); ++ this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper end ++ } ++ ++ // Paper start ++ /** ++ * Gets the join message to send to all online players ++ * ++ * @return string join message. Can be null ++ */ ++ public net.kyori.adventure.text.@Nullable Component joinMessage() { ++ return this.joinMessage; ++ } ++ ++ /** ++ * Sets the join message to send to all online players ++ * ++ * @param joinMessage join message. If null, no message will be sent ++ */ ++ public void joinMessage(net.kyori.adventure.text.@Nullable Component joinMessage) { + this.joinMessage = joinMessage; + } ++ // Paper end + + /** + * Gets the join message to send to all online players + * + * @return string join message. Can be null ++ * @deprecated in favour of {@link #joinMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getJoinMessage() { +- return joinMessage; ++ return this.joinMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.joinMessage); // Paper + } + + /** + * Sets the join message to send to all online players + * + * @param joinMessage join message. If null, no message will be sent ++ * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setJoinMessage(@Nullable String joinMessage) { +- this.joinMessage = joinMessage; ++ this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +index 2f6ca42330675733b2b4132cbb66e433788d05d5..997b06c19a5277656521e0e298f2958c209f1da1 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +@@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull; + */ + public class PlayerKickEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +- private String leaveMessage; +- private String kickReason; ++ private net.kyori.adventure.text.Component leaveMessage; // Paper ++ private net.kyori.adventure.text.Component kickReason; // Paper + private boolean cancel; + ++ @Deprecated // Paper + public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) { ++ super(playerKicked); ++ this.kickReason = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(kickReason); // Paper ++ this.leaveMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(leaveMessage); // Paper ++ this.cancel = false; ++ } ++ // Paper start ++ public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) { + super(playerKicked); + this.kickReason = kickReason; + this.leaveMessage = leaveMessage; + this.cancel = false; + } + ++ /** ++ * Gets the leave message send to all online players ++ * ++ * @return string kick reason ++ */ ++ public net.kyori.adventure.text.@NotNull Component leaveMessage() { ++ return this.leaveMessage; ++ } ++ ++ /** ++ * Sets the leave message send to all online players ++ * ++ * @param leaveMessage leave message ++ */ ++ public void leaveMessage(net.kyori.adventure.text.@NotNull Component leaveMessage) { ++ this.leaveMessage = leaveMessage; ++ } ++ + /** + * Gets the reason why the player is getting kicked + * + * @return string kick reason + */ ++ public net.kyori.adventure.text.@NotNull Component reason() { ++ return this.kickReason; ++ } ++ ++ /** ++ * Sets the reason why the player is getting kicked ++ * ++ * @param kickReason kick reason ++ */ ++ public void reason(net.kyori.adventure.text.@NotNull Component kickReason) { ++ this.kickReason = kickReason; ++ } ++ // Paper end ++ ++ /** ++ * Gets the reason why the player is getting kicked ++ * ++ * @return string kick reason ++ * @deprecated in favour of {@link #reason()} ++ */ + @NotNull ++ @Deprecated // Paper + public String getReason() { +- return kickReason; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.kickReason); // Paper + } + + /** + * Gets the leave message send to all online players + * + * @return string kick reason ++ * @deprecated in favour of {@link #leaveMessage()} + */ + @NotNull ++ @Deprecated // Paper + public String getLeaveMessage() { +- return leaveMessage; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.leaveMessage); // Paper + } + + @Override +@@ -55,18 +104,22 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { + * Sets the reason why the player is getting kicked + * + * @param kickReason kick reason ++ * @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setReason(@NotNull String kickReason) { +- this.kickReason = kickReason; ++ this.kickReason = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(kickReason); // Paper + } + + /** + * Sets the leave message send to all online players + * + * @param leaveMessage leave message ++ * @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setLeaveMessage(@NotNull String leaveMessage) { +- this.leaveMessage = leaveMessage; ++ this.leaveMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(leaveMessage); // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java +index 36b436e145a7215682b692a87ab894df25752c1d..dc6b41950570c3a8b02415dd9017b2336e6e7f0c 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerLocaleChangeEvent.java +@@ -12,17 +12,31 @@ public class PlayerLocaleChangeEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); + // + private final String locale; ++ // Paper start ++ private final java.util.Locale adventure$locale; ++ /** ++ * @see Player#locale() ++ * ++ * @return the player's new locale ++ */ ++ public @NotNull java.util.Locale locale() { ++ return this.adventure$locale; ++ } ++ // Paper end + + public PlayerLocaleChangeEvent(@NotNull Player who, @NotNull String locale) { + super(who); + this.locale = locale; ++ this.adventure$locale = java.util.Objects.requireNonNullElse(net.kyori.adventure.translation.Translator.parseLocale(locale), java.util.Locale.US); // Paper start + } + + /** + * @return the player's new locale + * @see Player#getLocale() ++ * @deprecated in favour of {@link #locale()} + */ + @NotNull ++ @Deprecated // Paper + public String getLocale() { + return locale; + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +index 2bc81b0aa73f7f5b0352121f6bf18fa63acf7a83..eaa0548cf430bf5b58ff84e0a4403c451699db28 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +@@ -18,7 +18,7 @@ public class PlayerLoginEvent extends PlayerEvent { + private final InetAddress realAddress; + private final String hostname; + private Result result = Result.ALLOWED; +- private String message = ""; ++ private net.kyori.adventure.text.Component message = net.kyori.adventure.text.Component.empty(); + + /** + * This constructor defaults message to an empty string, and result to +@@ -60,13 +60,53 @@ public class PlayerLoginEvent extends PlayerEvent { + * @param result The result status for this event + * @param message The message to be displayed if result denies login + * @param realAddress the actual, unspoofed connecting address ++ * @deprecated in favour of {@link #PlayerLoginEvent(Player, String, InetAddress, Result, net.kyori.adventure.text.Component, InetAddress)} + */ ++ @Deprecated // Paper + public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) { + this(player, hostname, address, realAddress); + this.result = result; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper ++ } ++ ++ // Paper start ++ /** ++ * This constructor pre-configures the event with a result and message ++ * ++ * @param player The {@link Player} for this event ++ * @param hostname The hostname that was used to connect to the server ++ * @param address The address the player used to connect, provided for ++ * timing issues ++ * @param result The result status for this event ++ * @param message The message to be displayed if result denies login ++ * @param realAddress the actual, unspoofed connecting address ++ */ ++ public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) { ++ this(player, hostname, address, realAddress); // Spigot ++ this.result = result; + this.message = message; + } + ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ */ ++ public net.kyori.adventure.text.@NotNull Component kickMessage() { ++ return this.message; ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ */ ++ public void kickMessage(net.kyori.adventure.text.@NotNull Component message) { ++ this.message = message; ++ } ++ // Paper end ++ + /** + * Gets the current result of the login, as an enum + * +@@ -91,19 +131,23 @@ public class PlayerLoginEvent extends PlayerEvent { + * Result.ALLOWED + * + * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} + */ + @NotNull ++ @Deprecated // Paper + public String getKickMessage() { +- return message; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper + } + + /** + * Sets the kick message to display if getResult() != Result.ALLOWED + * + * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setKickMessage(@NotNull final String message) { +- this.message = message; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + + /** +@@ -122,7 +166,7 @@ public class PlayerLoginEvent extends PlayerEvent { + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -130,8 +174,21 @@ public class PlayerLoginEvent extends PlayerEvent { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper start + public void disallow(@NotNull final Result result, @NotNull final String message) { ++ this.result = result; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); ++ } ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ // Paper end + this.result = result; + this.message = message; + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +index 203d030dbb2312a06bfb526351c1af92ddbc351a..b323212f11f831a96d87f6c9d746a90d119a3efd 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java +@@ -9,6 +9,13 @@ import org.jetbrains.annotations.NotNull; + + /** + * Stores details for players attempting to log in ++ *

      ++ * When this event is fired, the player's locale is not ++ * available. Therefore, any translatable component will be ++ * rendered with the default locale, {@link java.util.Locale#US}. ++ *

      ++ * Consider rendering any translatable yourself with {@link net.kyori.adventure.translation.GlobalTranslator#render} ++ * if the client's language is known. + * + * @deprecated This event causes synchronization from the login thread; {@link + * AsyncPlayerPreLoginEvent} is preferred to keep the secondary threads +@@ -19,7 +26,7 @@ import org.jetbrains.annotations.NotNull; + public class PlayerPreLoginEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Result result; +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final String name; + private final InetAddress ipAddress; + private final UUID uniqueId; +@@ -31,7 +38,7 @@ public class PlayerPreLoginEvent extends Event { + + public PlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) { + this.result = Result.ALLOWED; +- this.message = ""; ++ this.message = net.kyori.adventure.text.Component.empty(); // Paper + this.name = name; + this.ipAddress = ipAddress; + this.uniqueId = uniqueId; +@@ -56,6 +63,7 @@ public class PlayerPreLoginEvent extends Event { + this.result = result; + } + ++ // Paper start + /** + * Gets the current kick message that will be used if getResult() != + * Result.ALLOWED +@@ -63,7 +71,7 @@ public class PlayerPreLoginEvent extends Event { + * @return Current kick message + */ + @NotNull +- public String getKickMessage() { ++ public net.kyori.adventure.text.Component kickMessage() { + return message; + } + +@@ -72,16 +80,51 @@ public class PlayerPreLoginEvent extends Event { + * + * @param message New kick message + */ +- public void setKickMessage(@NotNull final String message) { ++ public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { + this.message = message; + } + ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user ++ */ ++ public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { ++ this.result = result; ++ this.message = message; ++ } ++ // Paper end ++ /** ++ * Gets the current kick message that will be used if getResult() != ++ * Result.ALLOWED ++ * ++ * @return Current kick message ++ * @deprecated in favour of {@link #kickMessage()} ++ */ ++ @Deprecated // Paper ++ @NotNull ++ public String getKickMessage() { ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper ++ } ++ ++ /** ++ * Sets the kick message to display if getResult() != Result.ALLOWED ++ * ++ * @param message New kick message ++ * @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ public void setKickMessage(@NotNull final String message) { ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper ++ } ++ + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; +- message = ""; ++ message = net.kyori.adventure.text.Component.empty(); // Paper + } + + /** +@@ -89,10 +132,12 @@ public class PlayerPreLoginEvent extends Event { + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user ++ * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void disallow(@NotNull final Result result, @NotNull final String message) { + this.result = result; +- this.message = message; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +index d70c25f404e994766a9ebce89a917c8d0719777c..14b27eaaf744736b3e56bb1383481df98a218c43 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +@@ -10,30 +10,59 @@ import org.jetbrains.annotations.Nullable; + */ + public class PlayerQuitEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); +- private String quitMessage; ++ private net.kyori.adventure.text.Component quitMessage; // Paper + ++ @Deprecated // Paper + public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { + super(who); ++ this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper ++ } ++ // Paper start ++ public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { ++ super(who); ++ this.quitMessage = quitMessage; ++ } ++ ++ /** ++ * Gets the quit message to send to all online players ++ * ++ * @return string quit message ++ */ ++ public net.kyori.adventure.text.@Nullable Component quitMessage() { ++ return quitMessage; ++ } ++ ++ /** ++ * Sets the quit message to send to all online players ++ * ++ * @param quitMessage quit message ++ */ ++ public void quitMessage(net.kyori.adventure.text.@Nullable Component quitMessage) { + this.quitMessage = quitMessage; + } ++ // Paper end + + /** + * Gets the quit message to send to all online players + * + * @return string quit message ++ * @deprecated in favour of {@link #quitMessage()} + */ + @Nullable ++ @Deprecated // Paper + public String getQuitMessage() { +- return quitMessage; ++ return this.quitMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.quitMessage); // Paper + } + + /** + * Sets the quit message to send to all online players + * + * @param quitMessage quit message ++ * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setQuitMessage(@Nullable String quitMessage) { +- this.quitMessage = quitMessage; ++ this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java +index 24d57cf17639f51b9557aec17a3686816542cfc6..173cdb379217d38af0df7a38e009553d0b257ea6 100644 +--- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java ++++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java +@@ -9,16 +9,16 @@ import org.jetbrains.annotations.NotNull; + + /** + * Event triggered for server broadcast messages such as from +- * {@link org.bukkit.Server#broadcast(String, String)}. ++ * {@link org.bukkit.Server#broadcast(net.kyori.adventure.text.Component)} (String, String)}. + * +- * This event behaves similarly to {@link AsyncPlayerChatEvent} in that it ++ * This event behaves similarly to {@link io.papermc.paper.event.player.AsyncChatEvent} in that it + * should be async if fired from an async thread. Please see that event for + * further information. + */ + public class BroadcastMessageEvent extends ServerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); +- private String message; ++ private net.kyori.adventure.text.Component message; // Paper + private final Set recipients; + private boolean cancelled = false; + +@@ -27,29 +27,66 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable { + this(false, message, recipients); + } + ++ @Deprecated // Paper + public BroadcastMessageEvent(boolean isAsync, @NotNull String message, @NotNull Set recipients) { ++ // Paper start ++ super(isAsync); ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); ++ this.recipients = recipients; ++ } ++ ++ @Deprecated ++ public BroadcastMessageEvent(net.kyori.adventure.text.@NotNull Component message, @NotNull Set recipients) { ++ this(false, message, recipients); ++ } ++ ++ public BroadcastMessageEvent(boolean isAsync, net.kyori.adventure.text.@NotNull Component message, @NotNull Set recipients) { ++ // Paper end + super(isAsync); + this.message = message; + this.recipients = recipients; + } ++ // Paper start ++ /** ++ * Get the broadcast message. ++ * ++ * @return Message to broadcast ++ */ ++ public net.kyori.adventure.text.@NotNull Component message() { ++ return this.message; ++ } ++ ++ /** ++ * Set the broadcast message. ++ * ++ * @param message New message to broadcast ++ */ ++ public void message(net.kyori.adventure.text.@NotNull Component message) { ++ this.message = message; ++ } ++ // Paper end + + /** + * Get the message to broadcast. + * + * @return Message to broadcast ++ * @deprecated in favour of {@link #message()} + */ + @NotNull ++ @Deprecated // Paper + public String getMessage() { +- return message; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper + } + + /** + * Set the message to broadcast. + * + * @param message New message to broadcast ++ * @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setMessage(@NotNull String message) { +- this.message = message; ++ this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java +index 689e533a61be76b96312daf52db00d9885f1fb5a..1cc5a0abce39c939398ce945dd916dc086888b13 100644 +--- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java ++++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java +@@ -22,7 +22,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + private static final HandlerList handlers = new HandlerList(); + private final String hostname; + private final InetAddress address; +- private String motd; ++ private net.kyori.adventure.text.Component motd; // Paper + private final int numPlayers; + private int maxPlayers; + +@@ -31,7 +31,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + Preconditions.checkArgument(numPlayers >= 0, "Cannot have negative number of players online", numPlayers); + this.hostname = hostname; + this.address = address; +- this.motd = motd; ++ this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper + this.numPlayers = numPlayers; + this.maxPlayers = maxPlayers; + } +@@ -45,15 +45,80 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + * @param address the address of the pinger + * @param motd the message of the day + * @param maxPlayers the max number of players ++ * @deprecated in favour of {@link #ServerListPingEvent(String, java.net.InetAddress, net.kyori.adventure.text.Component, int)} + */ ++ @Deprecated // Paper + protected ServerListPingEvent(@NotNull final String hostname, @NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) { + super(true); + this.numPlayers = MAGIC_PLAYER_COUNT; + this.hostname = hostname; + this.address = address; ++ this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper ++ this.maxPlayers = maxPlayers; ++ } ++ // Paper start ++ @Deprecated ++ public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) { ++ this("", address, motd, numPlayers, maxPlayers); ++ } ++ public ServerListPingEvent(@NotNull final String hostname, @NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) { ++ super(true); ++ Preconditions.checkArgument(numPlayers >= 0, "Cannot have negative number of players online (%s)", numPlayers); ++ this.hostname = hostname; ++ this.address = address; + this.motd = motd; ++ this.numPlayers = numPlayers; + this.maxPlayers = maxPlayers; + } ++ /** ++ * This constructor is intended for implementations that provide the ++ * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} ++ * count. ++ * ++ * @param address the address of the pinger ++ * @param motd the message of the day ++ * @param maxPlayers the max number of players ++ * @deprecated in favour of {@link #ServerListPingEvent(String, java.net.InetAddress, net.kyori.adventure.text.Component, int)} ++ */ ++ @Deprecated ++ protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int maxPlayers) { ++ this("", address, motd, maxPlayers); ++ } ++ ++ /** ++ * This constructor is intended for implementations that provide the ++ * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} ++ * count. ++ * ++ * @param hostname The hostname that was used to connect to the server ++ * @param address the address of the pinger ++ * @param motd the message of the day ++ * @param maxPlayers the max number of players ++ */ ++ protected ServerListPingEvent(final @NotNull String hostname, final @NotNull InetAddress address, final net.kyori.adventure.text.@NotNull Component motd, final int maxPlayers) { ++ this.numPlayers = MAGIC_PLAYER_COUNT; ++ this.hostname = hostname; ++ this.address = address; ++ this.motd = motd; ++ this.maxPlayers = maxPlayers; ++ } ++ /** ++ * Get the message of the day message. ++ * ++ * @return the message of the day ++ */ ++ public net.kyori.adventure.text.@NotNull Component motd() { ++ return motd; ++ } ++ /** ++ * Change the message of the day message. ++ * ++ * @param motd the message of the day ++ */ ++ public void motd(net.kyori.adventure.text.@NotNull Component motd) { ++ this.motd = motd; ++ } ++ // Paper end + + /** + * Gets the hostname that the player used to connect to the server, or +@@ -80,19 +145,23 @@ public class ServerListPingEvent extends ServerEvent implements Iterable + * Get the message of the day message. + * + * @return the message of the day ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + public String getMotd() { +- return motd; ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.motd); // Paper + } + + /** + * Change the message of the day message. + * + * @param motd the message of the day ++ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setMotd(@NotNull String motd) { +- this.motd = motd; ++ this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java +index 021d9491d0b7337e036bc95aad076b923f7451dd..0b5e2f4760a43a7a8d3de7bca557027822145a18 100644 +--- a/src/main/java/org/bukkit/inventory/InventoryView.java ++++ b/src/main/java/org/bukkit/inventory/InventoryView.java +@@ -269,12 +269,26 @@ public interface InventoryView { + */ + public boolean setProperty(@NotNull Property prop, int value); + ++ // Paper start + /** + * Get the title of this inventory window. + * + * @return The title. + */ + @NotNull ++ default net.kyori.adventure.text.Component title() { ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getTitle()); ++ } ++ // Paper end ++ ++ /** ++ * Get the title of this inventory window. ++ * ++ * @return The title. ++ * @deprecated in favour of {@link #title()} ++ */ ++ @Deprecated // Paper ++ @NotNull + public String getTitle(); + + /** +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index aa7fcae0de70aa5c10a331dfb076efd2f2c64065..d5342258086066d3b9ef404916bad8440f0cf0cd 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -200,4 +200,24 @@ public interface ItemFactory { + */ + @NotNull + ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures); ++ ++ // Paper start - Adventure ++ /** ++ * Creates a hover event for the given item. ++ * ++ * @param item The item ++ * @return A hover event ++ */ ++ @NotNull ++ net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator op); ++ ++ /** ++ * Get the formatted display name of the {@link ItemStack}. ++ * ++ * @param itemStack the {@link ItemStack} ++ * @return display name of the {@link ItemStack} ++ */ ++ @NotNull ++ net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); ++ // Paper end - Adventure + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 8d9c309067235b24893de6a86ae8efe1f30015bd..a71a37e3833b6a339c4df8939768c2bd46a816a5 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; + * use this class to encapsulate Materials for which {@link Material#isItem()} + * returns false. + */ +-public class ItemStack implements Cloneable, ConfigurationSerializable, Translatable { ++public class ItemStack implements Cloneable, ConfigurationSerializable, Translatable, net.kyori.adventure.text.event.HoverEventSource { // Paper + private Material type = Material.AIR; + private int amount = 0; + private MaterialData data = null; +@@ -626,4 +626,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + public String getTranslationKey() { + return Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ // Paper start ++ @NotNull ++ @Override ++ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { ++ return org.bukkit.Bukkit.getServer().getItemFactory().asHoverEvent(this, op); ++ } ++ ++ /** ++ * Get the formatted display name of the {@link ItemStack}. ++ * ++ * @return display name of the {@link ItemStack} ++ */ ++ public net.kyori.adventure.text.@NotNull Component displayName() { ++ return Bukkit.getServer().getItemFactory().displayName(this); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/MenuType.java b/src/main/java/org/bukkit/inventory/MenuType.java +index 45d3889206fb3b7a7303490b8d4e67ede2aae7a4..34d45a105da72481a7c4f2e3831f5d2a676c91c6 100644 +--- a/src/main/java/org/bukkit/inventory/MenuType.java ++++ b/src/main/java/org/bukkit/inventory/MenuType.java +@@ -145,11 +145,45 @@ public interface MenuType extends Keyed { + * @param player the player the view belongs to + * @param title the title of the view + * @return the created {@link InventoryView} ++ * @deprecated Use {@link #create(HumanEntity, net.kyori.adventure.text.Component)} instead. + */ + @NotNull ++ @Deprecated(since = "1.21") // Paper - adventure + V create(@NotNull HumanEntity player, @NotNull String title); ++ ++ // Paper start - adventure ++ /** ++ * Creates a view of the specified menu type. ++ *

      ++ * The player provided to create this view must be the player the view ++ * is opened for. See {@link HumanEntity#openInventory(InventoryView)} ++ * for more information. ++ * ++ * @param player the player the view belongs to ++ * @param title the title of the view ++ * @return the created {@link InventoryView} ++ */ ++ @NotNull ++ V create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title); ++ // Paper end - adventure + } + ++ // Paper start - adventure ++ /** ++ * Creates a view of the specified menu type. ++ *

      ++ * The player provided to create this view must be the player the view ++ * is opened for. See {@link HumanEntity#openInventory(InventoryView)} ++ * for more information. ++ * ++ * @param player the player the view belongs to ++ * @param title the title of the view ++ * @return the created {@link InventoryView} ++ */ ++ @NotNull ++ InventoryView create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title); ++ // Paper end - adventure ++ + /** + * Yields this MenuType as a typed version of itself with a plain + * {@link InventoryView} representing it. +diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java +index 9bab73c3c2ca759b8e1c7d07d98cc593c961666a..f0c6943da3f783101ca647b75b3230fae3a310da 100644 +--- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java +@@ -7,10 +7,15 @@ import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + /** +- * Represents a {@link Material#WRITTEN_BOOK}) that can have a title, an author, ++ * Represents a {@link Material#WRITTEN_BOOK} that can have a title, an author, + * and pages. ++ *

      ++ * Before using this type, make sure to check the itemstack's material with ++ * {@link org.bukkit.inventory.ItemStack#getType()}. {@code instanceof} on ++ * the meta instance is not sufficient due to unusual inheritance ++ * with relation to {@link WritableBookMeta}. + */ +-public interface BookMeta extends WritableBookMeta { ++public interface BookMeta extends WritableBookMeta, net.kyori.adventure.inventory.Book { // Paper - adventure + + /** + * Represents the generation (or level of copying) of a written book +@@ -116,6 +121,153 @@ public interface BookMeta extends WritableBookMeta { + @NotNull + BookMeta clone(); + ++ // Paper start - adventure ++ // ++ /** ++ * @deprecated use {@link #page(int)} ++ */ ++ @Deprecated ++ @Override ++ @NotNull String getPage(int page); ++ ++ /** ++ * @deprecated use {@link #page(int, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ @Override ++ void setPage(int page, @NotNull String data); ++ ++ /** ++ * @deprecated use {@link #pages()} ++ */ ++ @Deprecated ++ @Override ++ @NotNull List getPages(); ++ ++ /** ++ * @deprecated use {@link #pages(List)} ++ */ ++ @Deprecated ++ @Override ++ void setPages(@NotNull List pages); ++ ++ /** ++ * @deprecated use {@link #pages(net.kyori.adventure.text.Component...)} ++ */ ++ @Deprecated ++ @Override ++ void setPages(@NotNull String... pages); ++ ++ /** ++ * @deprecated use {@link #addPages(net.kyori.adventure.text.Component...)} ++ */ ++ @Deprecated ++ @Override ++ void addPage(@NotNull String... pages); ++ // ++ ++ /** ++ * Gets the title of the book. ++ *

      ++ * Plugins should check that hasTitle() returns true before calling this ++ * method. ++ * ++ * @return the title of the book ++ */ ++ @Override ++ net.kyori.adventure.text.@Nullable Component title(); ++ ++ /** ++ * Sets the title of the book. ++ *

      ++ * Limited to 32 characters. Removes title when given null. ++ * ++ * @param title the title to set ++ * @return the same {@link BookMeta} instance ++ */ ++ @org.jetbrains.annotations.Contract(value = "_ -> this", pure = false) ++ @Override ++ @NotNull BookMeta title(net.kyori.adventure.text.@Nullable Component title); ++ ++ /** ++ * Gets the author of the book. ++ *

      ++ * Plugins should check that hasAuthor() returns true before calling this ++ * method. ++ * ++ * @return the author of the book ++ */ ++ @Override ++ net.kyori.adventure.text.@Nullable Component author(); ++ ++ /** ++ * Sets the author of the book. Removes author when given null. ++ * ++ * @param author the author to set ++ * @return the same {@link BookMeta} instance ++ */ ++ @org.jetbrains.annotations.Contract(value = "_ -> this", pure = false) ++ @Override ++ @NotNull BookMeta author(net.kyori.adventure.text.@Nullable Component author); ++ ++ ++ /** ++ * Gets the specified page in the book. The page must exist. ++ *

      ++ * Pages are 1-indexed. ++ * ++ * @param page the page number to get, in range [1, getPageCount()] ++ * @return the page from the book ++ */ ++ net.kyori.adventure.text.@NotNull Component page(int page); ++ ++ /** ++ * Sets the specified page in the book. Pages of the book must be ++ * contiguous. ++ *

      ++ * The data can be up to 1024 characters in length, additional characters ++ * are truncated. ++ *

      ++ * Pages are 1-indexed. ++ * ++ * @param page the page number to set, in range [1, getPageCount()] ++ * @param data the data to set for that page ++ */ ++ void page(int page, net.kyori.adventure.text.@NotNull Component data); ++ ++ /** ++ * Adds new pages to the end of the book. Up to a maximum of 100 pages with ++ * 1024 characters per page. ++ * ++ * @param pages A list of strings, each being a page ++ */ ++ void addPages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages); ++ ++ interface BookMetaBuilder extends net.kyori.adventure.inventory.Book.Builder { ++ ++ @Override ++ @NotNull BookMetaBuilder title(net.kyori.adventure.text.@Nullable Component title); ++ ++ @Override ++ @NotNull BookMetaBuilder author(net.kyori.adventure.text.@Nullable Component author); ++ ++ @Override ++ @NotNull BookMetaBuilder addPage(net.kyori.adventure.text.@NotNull Component page); ++ ++ @Override ++ @NotNull BookMetaBuilder pages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages); ++ ++ @Override ++ @NotNull BookMetaBuilder pages(java.util.@NotNull Collection pages); ++ ++ @Override ++ @NotNull BookMeta build(); ++ } ++ ++ @Override ++ @NotNull BookMetaBuilder toBuilder(); ++ // Paper end ++ + // Spigot start + public class Spigot { + +@@ -124,8 +276,10 @@ public interface BookMeta extends WritableBookMeta { + * + * @param page the page number to get + * @return the page from the book ++ * @deprecated in favour of {@link #page(int)} + */ + @NotNull ++ @Deprecated // Paper + public BaseComponent[] getPage(int page) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -139,7 +293,9 @@ public interface BookMeta extends WritableBookMeta { + * + * @param page the page number to set + * @param data the data to set for that page ++ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setPage(int page, @Nullable BaseComponent... data) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -148,8 +304,10 @@ public interface BookMeta extends WritableBookMeta { + * Gets all the pages in the book. + * + * @return list of all the pages in the book ++ * @deprecated in favour of {@link #pages()} + */ + @NotNull ++ @Deprecated // Paper + public List getPages() { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -159,7 +317,9 @@ public interface BookMeta extends WritableBookMeta { + * pages. Maximum 50 pages with 256 characters per page. + * + * @param pages A list of pages to set the book to use ++ * @deprecated in favour of {@link #pages(java.util.List)} + */ ++ @Deprecated // Paper + public void setPages(@NotNull List pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -169,7 +329,9 @@ public interface BookMeta extends WritableBookMeta { + * pages. Maximum 50 pages with 256 characters per page. + * + * @param pages A list of component arrays, each being a page ++ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + public void setPages(@NotNull BaseComponent[]... pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +@@ -179,7 +341,9 @@ public interface BookMeta extends WritableBookMeta { + * with 256 characters per page. + * + * @param pages A list of component arrays, each being a page ++ * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} + */ ++ @Deprecated // Paper + public void addPage(@NotNull BaseComponent[]... pages) { + throw new UnsupportedOperationException("Not supported yet."); + } +diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +index 69d6de6e9618dd27f5ba73b931f8455912caf060..753a756525f6afea981dd0c2984e7a747d4d148b 100644 +--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +@@ -38,12 +38,65 @@ import org.jetbrains.annotations.Nullable; + */ + public interface ItemMeta extends Cloneable, ConfigurationSerializable, PersistentDataHolder { + ++ // Paper start ++ /** ++ * Checks for existence of a custom name. ++ * ++ * @return true if this has a custom name ++ */ ++ boolean hasCustomName(); ++ ++ /** ++ * Gets the custom name. ++ * ++ *

      Plugins should check that {@link #hasCustomName()} returns {@code true} before calling this method.

      ++ * ++ * @return the custom name ++ */ ++ net.kyori.adventure.text.@Nullable Component customName(); ++ ++ /** ++ * Sets the custom name. ++ * ++ * @param customName the custom name to set ++ */ ++ void customName(final net.kyori.adventure.text.@Nullable Component customName); ++ + /** + * Checks for existence of a display name. + * ++ * @apiNote This method is obsolete, use {@link #hasCustomName()} instead. + * @return true if this has a display name + */ +- boolean hasDisplayName(); ++ @ApiStatus.Obsolete(since = "1.21.4") ++ default boolean hasDisplayName() { ++ return this.hasCustomName(); ++ } ++ ++ /** ++ * Gets the display name. ++ * ++ *

      Plugins should check that {@link #hasDisplayName()} returns true before calling this method.

      ++ * ++ * @apiNote This method is obsolete, use {@link #customName()} instead. ++ * @return the display name ++ */ ++ @ApiStatus.Obsolete(since = "1.21.4") ++ default net.kyori.adventure.text.@Nullable Component displayName() { ++ return this.customName(); ++ } ++ ++ /** ++ * Sets the display name. ++ * ++ * @param displayName the display name to set ++ * @apiNote This method is obsolete, use {@link #customName(Component)} instead. ++ */ ++ @ApiStatus.Obsolete(since = "1.21.4") ++ default void displayName(final net.kyori.adventure.text.@Nullable Component displayName) { ++ this.customName(displayName); ++ } ++ // Paper end + + /** + * Gets the display name that is set. +@@ -52,7 +105,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * before calling this method. + * + * @return the display name that is set ++ * @deprecated in favour of {@link #displayName()} + */ ++ @Deprecated // Paper + @NotNull + String getDisplayName(); + +@@ -60,7 +115,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * Sets the display name. + * + * @param name the name to set ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@Nullable String name); + + /** +@@ -73,6 +130,32 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + */ + boolean hasItemName(); + ++ // Paper start ++ /** ++ * Gets the item name component that is set. ++ *
      ++ * Item name differs from display name in that it is cannot be edited by an ++ * anvil, is not styled with italics, and does not show labels. ++ *

      ++ * Plugins should check that {@link #hasItemName()} returns true before ++ * calling this method. ++ * ++ * @return the item name that is set ++ * @see #hasItemName() ++ */ ++ @org.jetbrains.annotations.NotNull ++ Component itemName(); ++ ++ /** ++ * Sets the item name. ++ *
      ++ * Item name differs from display name in that it is cannot be edited by an ++ * anvil, is not styled with italics, and does not show labels. ++ * ++ * @param name the name to set, null to remove it ++ */ ++ void itemName(@Nullable final Component name); ++ // Paper end + /** + * Gets the item name that is set. + *
      +@@ -83,7 +166,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * calling this method. + * + * @return the item name that is set ++ * @deprecated in favour of {@link #itemName()} + */ ++ @Deprecated // Paper + @NotNull + String getItemName(); + +@@ -94,7 +179,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * anvil, is not styled with italics, and does not show labels. + * + * @param name the name to set ++ * @deprecated in favour of {@link #itemName(Component)} + */ ++ @Deprecated // Paper + void setItemName(@Nullable String name); + + /** +@@ -135,6 +222,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + */ + boolean hasLore(); + ++ // Paper start ++ /** ++ * Gets the lore. ++ * ++ *

      Plugins should check that {@link #hasLore()} returns true before calling this method.

      ++ * ++ * @return the lore ++ */ ++ @Nullable List lore(); ++ ++ /** ++ * Sets the lore. ++ * ++ * @param lore the lore to set ++ */ ++ void lore(final @Nullable List lore); ++ // Paper end ++ + /** + * Gets the lore that is set. + *

      +@@ -142,7 +247,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * calling this method. + * + * @return a list of lore that is set ++ * @deprecated in favour of {@link #lore()} + */ ++ @Deprecated // Paper + @Nullable + List getLore(); + +@@ -151,7 +258,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste + * Removes lore when given null. + * + * @param lore the lore that will be set ++ * @deprecated in favour of {@link #lore(List)} + */ ++ @Deprecated // Paper + void setLore(@Nullable List lore); + + /** +diff --git a/src/main/java/org/bukkit/inventory/meta/PotionMeta.java b/src/main/java/org/bukkit/inventory/meta/PotionMeta.java +index b61d2e322f80fcabae5e286cba8df9701ebcf5ea..ada7b3d8f5743fa4dd7809060f1c5a5608b7aec3 100644 +--- a/src/main/java/org/bukkit/inventory/meta/PotionMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/PotionMeta.java +@@ -149,27 +149,64 @@ public interface PotionMeta extends ItemMeta { + /** + * Checks for existence of a custom potion name translation suffix. + * ++ * @deprecated conflicting name, use {@link #hasCustomPotionName()} + * @return true if this has a custom potion name + */ +- boolean hasCustomName(); ++ @Deprecated(forRemoval = true, since = "1.21.4") ++ default boolean hasCustomName() { ++ return this.hasCustomPotionName(); ++ } + + /** + * Gets the potion name translation suffix that is set. + *

      +- * Plugins should check that hasCustomName() returns true ++ * Plugins should check that {@link #hasCustomPotionName()} returns {@code true} + * before calling this method. + * ++ * @deprecated conflicting name, use {@link #getCustomPotionName()} + * @return the potion name that is set + */ ++ @Deprecated(forRemoval = true, since = "1.21.4") + @Nullable +- String getCustomName(); ++ default String getCustomName() { ++ return this.getCustomPotionName(); ++ } + + /** + * Sets the potion name translation suffix. + * ++ * @deprecated conflicting name, use {@link #setCustomPotionName(String)} + * @param name the name to set + */ +- void setCustomName(@Nullable String name); ++ @Deprecated(forRemoval = true, since = "1.21.4") ++ default void setCustomName(@Nullable String name) { ++ this.setCustomPotionName(name); ++ } ++ ++ /** ++ * Checks for existence of a custom potion name translation suffix. ++ * ++ * @return true if this has a custom potion name ++ */ ++ boolean hasCustomPotionName(); ++ ++ /** ++ * Gets the potion name translation suffix that is set. ++ *

      ++ * Plugins should check that {@link #hasCustomPotionName()} returns {@code true} ++ * before calling this method. ++ * ++ * @return the potion name that is set ++ */ ++ @Nullable ++ String getCustomPotionName(); ++ ++ /** ++ * Sets the potion name translation suffix. ++ * ++ * @param name the name to set ++ */ ++ void setCustomPotionName(@Nullable String name); + + @Override + PotionMeta clone(); +diff --git a/src/main/java/org/bukkit/inventory/meta/WritableBookMeta.java b/src/main/java/org/bukkit/inventory/meta/WritableBookMeta.java +index 12595536080ffe09df2b6ecdb83d846f50100d38..9fc47c879ee6b8edf2503f20e4736c2997d2de2e 100644 +--- a/src/main/java/org/bukkit/inventory/meta/WritableBookMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/WritableBookMeta.java +@@ -5,8 +5,14 @@ import org.bukkit.Material; + import org.jetbrains.annotations.NotNull; + + /** +- * Represents a book ({@link Material#WRITABLE_BOOK} or {@link +- * Material#WRITTEN_BOOK}) that can have pages. ++ * Represents a book ({@link Material#WRITABLE_BOOK}) that can have pages. ++ *

      ++ * For {@link Material#WRITTEN_BOOK}, use {@link BookMeta}. ++ *

      ++ * Before using this type, make sure to check the itemstack's material with ++ * {@link org.bukkit.inventory.ItemStack#getType()}. {@code instanceof} on ++ * the meta instance is not sufficient due to unusual inheritance ++ * with relation to {@link BookMeta}. + */ + public interface WritableBookMeta extends ItemMeta { + +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +index ebfd6f5523205cfc932e3d6b351ff26da855fb15..cc38bee3c412bef4767f08407c0f5559a113fce5 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +@@ -61,4 +61,21 @@ public interface TrimMaterial extends Keyed, Translatable { + private static TrimMaterial getTrimMaterial(@NotNull String key) { + return Registry.TRIM_MATERIAL.getOrThrow(NamespacedKey.minecraft(key)); + } ++ ++ // Paper start - adventure ++ /** ++ * Get the description of this {@link TrimMaterial}. ++ * ++ * @return the description ++ */ ++ net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component description(); ++ ++ /** ++ * @deprecated this method assumes that {@link #description()} will ++ * always be a translatable component which is not guaranteed. ++ */ ++ @Override ++ @Deprecated(forRemoval = true) ++ @org.jetbrains.annotations.NotNull String getTranslationKey(); ++ // Paper end - adventure + } +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +index e8e0786467bfcea14d30b352489b7bfb1a06addc..56cfe665daba1754e41f633d7c18172bebf87028 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +@@ -89,4 +89,21 @@ public interface TrimPattern extends Keyed, Translatable { + private static TrimPattern getTrimPattern(@NotNull String key) { + return Registry.TRIM_PATTERN.getOrThrow(NamespacedKey.minecraft(key)); + } ++ ++ // Paper start - adventure ++ /** ++ * Get the description of this {@link TrimPattern}. ++ * ++ * @return the description ++ */ ++ net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component description(); ++ ++ /** ++ * @deprecated this method assumes that {@link #description()} will ++ * always be a translatable component which is not guaranteed. ++ */ ++ @Override ++ @Deprecated(forRemoval = true) ++ @org.jetbrains.annotations.NotNull String getTranslationKey(); ++ // Paper end - adventure + } +diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java +index 3ca6d94e9930c93013ee654d5bc5a5d6656c6c0e..8de6d0c53bce0279a82b84b408e83d2128077400 100644 +--- a/src/main/java/org/bukkit/map/MapCursor.java ++++ b/src/main/java/org/bukkit/map/MapCursor.java +@@ -17,7 +17,7 @@ public final class MapCursor { + private byte x, y; + private byte direction; + private boolean visible; +- private String caption; ++ private net.kyori.adventure.text.Component caption; // Paper + private Type type; + + /** +@@ -32,7 +32,7 @@ public final class MapCursor { + */ + @Deprecated(since = "1.6.2") + public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) { +- this(x, y, direction, type, visible, null); ++ this(x, y, direction, type, visible, (String) null); // Paper + } + + /** +@@ -45,7 +45,7 @@ public final class MapCursor { + * @param visible Whether the cursor is visible by default. + */ + public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) { +- this(x, y, direction, type, visible, null); ++ this(x, y, direction, type, visible, (String) null); // Paper + } + + /** +@@ -57,7 +57,7 @@ public final class MapCursor { + * @param type The type (color/style) of the map cursor. + * @param visible Whether the cursor is visible by default. + * @param caption cursor caption +- * @deprecated Magic value, use {@link #MapCursor(byte, byte, byte, Type, boolean, String)} ++ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, Type, boolean, net.kyori.adventure.text.Component)} + */ + @Deprecated(since = "1.13") + public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { +@@ -66,8 +66,42 @@ public final class MapCursor { + setDirection(direction); + setRawType(type); + this.visible = visible; +- this.caption = caption; ++ this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper ++ } ++ // Paper start ++ /** ++ * Initialize the map cursor. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible by default. ++ * @param caption cursor caption ++ * @deprecated Magic value ++ */ ++ @Deprecated ++ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { ++ this.x = x; this.y = y; this.visible = visible; this.caption = caption; ++ setDirection(direction); ++ setRawType(type); ++ } ++ /** ++ * Initialize the map cursor. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible by default. ++ * @param caption cursor caption ++ */ ++ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { ++ this.x = x; this.y = y; this.visible = visible; this.caption = caption; ++ setDirection(direction); ++ setType(type); + } ++ // Paper end + + /** + * Initialize the map cursor. +@@ -85,7 +119,7 @@ public final class MapCursor { + setDirection(direction); + this.type = type; + this.visible = visible; +- this.caption = caption; ++ this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper + } + + /** +@@ -204,23 +238,45 @@ public final class MapCursor { + this.visible = visible; + } + ++ // Paper start + /** + * Gets the caption on this cursor. + * + * @return caption + */ ++ public net.kyori.adventure.text.@Nullable Component caption() { ++ return this.caption; ++ } ++ /** ++ * Sets the caption on this cursor. ++ * ++ * @param caption new caption ++ */ ++ public void caption(net.kyori.adventure.text.@Nullable Component caption) { ++ this.caption = caption; ++ } ++ // Paper end ++ /** ++ * Gets the caption on this cursor. ++ * ++ * @return caption ++ * @deprecated in favour of {@link #caption()} ++ */ + @Nullable ++ @Deprecated // Paper + public String getCaption() { +- return caption; ++ return this.caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.caption); // Paper + } + + /** + * Sets the caption on this cursor. + * + * @param caption new caption ++ * @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public void setCaption(@Nullable String caption) { +- this.caption = caption; ++ this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java +index 986f9c8a659ed5cdda9fc4528bff23bf0e9f801e..f95a9aaa0cb020ea71d4c8a8e71bceb7147cbe4d 100644 +--- a/src/main/java/org/bukkit/map/MapCursorCollection.java ++++ b/src/main/java/org/bukkit/map/MapCursorCollection.java +@@ -117,4 +117,22 @@ public final class MapCursorCollection { + public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable String caption) { + return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); + } ++ // Paper start ++ /** ++ * Add a cursor to the collection. ++ * ++ * @param x The x coordinate, from -128 to 127. ++ * @param y The y coordinate, from -128 to 127. ++ * @param direction The facing of the cursor, from 0 to 15. ++ * @param type The type (color/style) of the map cursor. ++ * @param visible Whether the cursor is visible. ++ * @param caption banner caption ++ * @return The newly added MapCursor. ++ * @deprecated Magic value ++ */ ++ @Deprecated ++ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { ++ return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/permissions/Permissible.java b/src/main/java/org/bukkit/permissions/Permissible.java +index 228421154913116069c20323afb519bdde2134df..26791db3c267670d5782f1d2b67ff7d5b55b9dac 100644 +--- a/src/main/java/org/bukkit/permissions/Permissible.java ++++ b/src/main/java/org/bukkit/permissions/Permissible.java +@@ -126,4 +126,34 @@ public interface Permissible extends ServerOperator { + */ + @NotNull + public Set getEffectivePermissions(); ++ ++ // Paper start - add TriState permission checks ++ /** ++ * Checks if this object has a permission set and, if it is set, the value of the permission. ++ * ++ * @param permission the permission to check ++ * @return a tri-state of if the permission is set and, if it is set, it's value ++ */ ++ default net.kyori.adventure.util.@NotNull TriState permissionValue(final @NotNull Permission permission) { ++ if (this.isPermissionSet(permission)) { ++ return net.kyori.adventure.util.TriState.byBoolean(this.hasPermission(permission)); ++ } else { ++ return net.kyori.adventure.util.TriState.NOT_SET; ++ } ++ } ++ ++ /** ++ * Checks if this object has a permission set and, if it is set, the value of the permission. ++ * ++ * @param permission the permission to check ++ * @return a tri-state of if the permission is set and, if it is set, it's value ++ */ ++ default net.kyori.adventure.util.@NotNull TriState permissionValue(final @NotNull String permission) { ++ if (this.isPermissionSet(permission)) { ++ return net.kyori.adventure.util.TriState.byBoolean(this.hasPermission(permission)); ++ } else { ++ return net.kyori.adventure.util.TriState.NOT_SET; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java +index 03ca87a1cbace2459174bb7bb8847bda766e80c5..b37938745f916b5f0111b07b1a1c97527f026e9d 100644 +--- a/src/main/java/org/bukkit/plugin/Plugin.java ++++ b/src/main/java/org/bukkit/plugin/Plugin.java +@@ -179,6 +179,13 @@ public interface Plugin extends TabExecutor { + @NotNull + public Logger getLogger(); + ++ // Paper start - Adventure component logger ++ @NotNull ++ default net.kyori.adventure.text.logger.slf4j.ComponentLogger getComponentLogger() { ++ return net.kyori.adventure.text.logger.slf4j.ComponentLogger.logger(getLogger().getName()); ++ } ++ // Paper end ++ + /** + * Returns the name of the plugin. + *

      +diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java +index c15e056e7697aac9079d3506911d82cb71aa9d23..d57634dd3796a695aba7623d2b04e35d630887b3 100644 +--- a/src/main/java/org/bukkit/scoreboard/Objective.java ++++ b/src/main/java/org/bukkit/scoreboard/Objective.java +@@ -20,13 +20,35 @@ public interface Objective { + @NotNull + String getName(); + ++ // Paper start - Adventure ++ /** ++ * Gets the display name for this objective ++ * ++ * @return this objective's display name ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ net.kyori.adventure.text.@NotNull Component displayName(); ++ /** ++ * Sets the name displayed to players for this objective. ++ * ++ * @param displayName Display name to set ++ * @throws IllegalStateException if this objective has been unregistered ++ * @throws IllegalArgumentException if displayName is null ++ * @throws IllegalArgumentException if displayName is longer than 128 ++ * characters. ++ */ ++ void displayName(net.kyori.adventure.text.@Nullable Component displayName); ++ // Paper end - Adventure ++ + /** + * Gets the name displayed to players for this objective + * + * @return this objective's display name + * @throws IllegalStateException if this objective has been unregistered ++ * @deprecated in favour of {@link #displayName()} + */ + @NotNull ++ @Deprecated // Paper + String getDisplayName(); + + /** +@@ -34,7 +56,9 @@ public interface Objective { + * + * @param displayName Display name to set + * @throws IllegalStateException if this objective has been unregistered ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@NotNull String displayName); + + /** +diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +index a55188ec3ec1c038fdd96da62f534cb71686da97..1cba9a96cc7efce2a4394add33e4c0369f94be31 100644 +--- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java ++++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +@@ -26,6 +26,71 @@ public interface Scoreboard { + @NotNull + Objective registerNewObjective(@NotNull String name, @NotNull String criteria); + ++ // Paper start - Adventure ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName display name for the Objective. ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is longer than 32767 ++ * characters. ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)} ++ */ ++ @NotNull ++ @Deprecated ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName); ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName Name displayed to players for the Objective. ++ * @param renderType Manner of rendering the Objective ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is longer than 32767 ++ * characters. ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)} ++ */ ++ @NotNull ++ @Deprecated ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName Name displayed to players for the Objective. ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is longer than 32767 ++ * characters. ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ */ ++ @NotNull ++ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName) throws IllegalArgumentException; ++ /** ++ * Registers an Objective on this Scoreboard ++ * ++ * @param name Name of the Objective ++ * @param criteria Criteria for the Objective ++ * @param displayName Name displayed to players for the Objective. ++ * @param renderType Manner of rendering the Objective ++ * @return The registered Objective ++ * @throws IllegalArgumentException if name is longer than 32767 ++ * characters. ++ * @throws IllegalArgumentException if an objective by that name already ++ * exists ++ */ ++ @NotNull ++ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; ++ // Paper end - Adventure ++ + /** + * Registers an Objective on this Scoreboard + * +@@ -37,7 +102,7 @@ public interface Scoreboard { + * characters. + * @throws IllegalArgumentException if an objective by that name already + * exists +- * @deprecated use {@link #registerNewObjective(String, Criteria, String)} ++ * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)} + */ + @Deprecated(since = "1.20.5") + @NotNull +@@ -55,7 +120,7 @@ public interface Scoreboard { + * characters. + * @throws IllegalArgumentException if an objective by that name already + * exists +- * @deprecated use {@link #registerNewObjective(String, Criteria, String, RenderType)} ++ * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)} + */ + @Deprecated(since = "1.20.5") + @NotNull +@@ -72,8 +137,10 @@ public interface Scoreboard { + * characters. + * @throws IllegalArgumentException if an objective by that name already + * exists ++ * @deprecated in favour of {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)} + */ + @NotNull ++ @Deprecated // Paper + Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName); + + /** +@@ -88,8 +155,10 @@ public interface Scoreboard { + * characters. + * @throws IllegalArgumentException if an objective by that name already + * exists ++ * @deprecated in favour of {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)} + */ + @NotNull ++ @Deprecated // Paper + Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName, @NotNull RenderType renderType); + + /** +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index f6e684853fbca3f015f4948db5603eb155ea1f2f..284468fd3d310a7acdffa31f0f6593f5a98419ba 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; + * properties. This team is only relevant to the display of the associated + * {@link #getScoreboard() scoreboard}. + */ +-public interface Team { ++public interface Team extends net.kyori.adventure.audience.ForwardingAudience { // Paper - Make Team extend ForwardingAudience + + /** + * Gets the name of this Team +@@ -23,13 +23,96 @@ public interface Team { + @NotNull + String getName(); + ++ // Paper start - Adventure ++ /** ++ * Gets the display name for this team ++ * ++ * @return Team display name ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ net.kyori.adventure.text.@NotNull Component displayName(); ++ ++ /** ++ * Sets the name displayed to entries for this team ++ * ++ * @param displayName New display name ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void displayName(net.kyori.adventure.text.@Nullable Component displayName); ++ ++ /** ++ * Gets the prefix prepended to the display of entries on this team. ++ * ++ * @return Team prefix ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ net.kyori.adventure.text.@NotNull Component prefix(); ++ ++ /** ++ * Sets the prefix prepended to the display of entries on this team. ++ * ++ * @param prefix New prefix ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void prefix(net.kyori.adventure.text.@Nullable Component prefix); ++ ++ /** ++ * Gets the suffix appended to the display of entries on this team. ++ * ++ * @return the team's current suffix ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ net.kyori.adventure.text.@NotNull Component suffix(); ++ ++ /** ++ * Sets the suffix appended to the display of entries on this team. ++ * ++ * @param suffix the new suffix for this team. ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void suffix(net.kyori.adventure.text.@Nullable Component suffix); ++ ++ /** ++ * Checks if the team has a color specified ++ * ++ * @return true if it has a color ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ boolean hasColor(); ++ ++ /** ++ * Gets the color of the team. ++ *
      ++ * This only sets the team outline, other occurrences of colors such as in ++ * names are handled by prefixes / suffixes. ++ * ++ * @return team color ++ * @throws IllegalStateException if this team has been unregistered ++ * @throws IllegalStateException if the team doesn't have a color ++ * @see #hasColor() ++ */ ++ net.kyori.adventure.text.format.@NotNull TextColor color(); ++ ++ /** ++ * Sets the color of the team. ++ *
      ++ * This only sets the team outline, other occurrences of colors such as in ++ * names are handled by prefixes / suffixes. ++ * ++ * @param color new color, null for no color ++ */ ++ void color(net.kyori.adventure.text.format.@Nullable NamedTextColor color); ++ // Paper end - Adventure ++ + /** + * Gets the name displayed to entries for this team + * + * @return Team display name + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #displayName()} + */ + @NotNull ++ @Deprecated // Paper + String getDisplayName(); + + /** +@@ -37,7 +120,9 @@ public interface Team { + * + * @param displayName New display name + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setDisplayName(@NotNull String displayName); + + /** +@@ -45,8 +130,10 @@ public interface Team { + * + * @return Team prefix + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #prefix()} + */ + @NotNull ++ @Deprecated // Paper + String getPrefix(); + + /** +@@ -54,7 +141,9 @@ public interface Team { + * + * @param prefix New prefix + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setPrefix(@NotNull String prefix); + + /** +@@ -62,8 +151,10 @@ public interface Team { + * + * @return the team's current suffix + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #suffix()} + */ + @NotNull ++ @Deprecated // Paper + String getSuffix(); + + /** +@@ -71,7 +162,9 @@ public interface Team { + * + * @param suffix the new suffix for this team. + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + void setSuffix(@NotNull String suffix); + + /** +@@ -82,8 +175,10 @@ public interface Team { + * + * @return team color, defaults to {@link ChatColor#RESET} + * @throws IllegalStateException if this team has been unregistered ++ * @deprecated in favour of {@link #color()} + */ + @NotNull ++ @Deprecated // Paper + ChatColor getColor(); + + /** +@@ -94,7 +189,9 @@ public interface Team { + * + * @param color new color, must be non-null. Use {@link ChatColor#RESET} for + * no color ++ * @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)} + */ ++ @Deprecated // Paper + void setColor(@NotNull ChatColor color); + + /** +diff --git a/src/test/java/io/papermc/paper/adventure/KeyTest.java b/src/test/java/io/papermc/paper/adventure/KeyTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7ede17d60358e0e3a04f3166ea9657e5239e0d8f +--- /dev/null ++++ b/src/test/java/io/papermc/paper/adventure/KeyTest.java +@@ -0,0 +1,31 @@ ++package io.papermc.paper.adventure; ++ ++import java.util.HashSet; ++import java.util.Set; ++import net.kyori.adventure.key.Key; ++import org.bukkit.NamespacedKey; ++import org.junit.jupiter.api.Test; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; ++import static org.junit.jupiter.api.Assertions.assertTrue; ++ ++public class KeyTest { ++ ++ @Test ++ public void equalsTest() { ++ Key key = new NamespacedKey("test", "key"); ++ Key key1 = Key.key("test", "key"); ++ assertEquals(key, key1); ++ assertEquals(key1, key); ++ } ++ ++ @Test ++ public void setTest() { ++ Key key = new NamespacedKey("test", "key"); ++ Key key1 = Key.key("test", "key"); ++ Set set = new HashSet<>(Set.of(key)); ++ Set set1 = new HashSet<>(Set.of(key1)); ++ assertTrue(set.contains(key1)); ++ assertTrue(set1.contains(key)); ++ } ++} diff --git a/patches/api/0007-Paper-Utils.patch b/patches/api/0007-Paper-Utils.patch new file mode 100644 index 000000000000..38f5ac80adaf --- /dev/null +++ b/patches/api/0007-Paper-Utils.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 Feb 2019 11:26:21 -0500 +Subject: [PATCH] Paper Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fbcd82b513b4cb9839f9d2b38d9c6c73148e30a6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/SneakyThrow.java +@@ -0,0 +1,19 @@ ++package com.destroystokyo.paper.util; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++public final class SneakyThrow { ++ ++ public static void sneaky(final Throwable exception) { ++ SneakyThrow.throwSneaky(exception); ++ } ++ ++ @SuppressWarnings("unchecked") ++ private static void throwSneaky(final Throwable exception) throws T { ++ throw (T) exception; ++ } ++ ++} diff --git a/patches/api/0008-Use-ASM-for-event-executors.patch b/patches/api/0008-Use-ASM-for-event-executors.patch new file mode 100644 index 000000000000..31a3b5a44b05 --- /dev/null +++ b/patches/api/0008-Use-ASM-for-event-executors.patch @@ -0,0 +1,381 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Thu, 3 Mar 2016 13:20:33 -0700 +Subject: [PATCH] Use ASM for event executors. + +Uses method handles for private or static methods. + +diff --git a/build.gradle.kts b/build.gradle.kts +index ed5d58d7569300c917dd52b11953a63fae6878d4..43086f7d201c0988086ef06cfe5a0f866d130961 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -61,6 +61,9 @@ dependencies { + apiAndDocs("net.kyori:adventure-text-serializer-legacy") + apiAndDocs("net.kyori:adventure-text-serializer-plain") + apiAndDocs("net.kyori:adventure-text-logger-slf4j") ++ ++ implementation("org.ow2.asm:asm:9.7.1") ++ implementation("org.ow2.asm:asm-commons:9.7.1") + // Paper end + + compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5a702481d28d90cb503faad0d9b9c3231bbff940 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.event.executor; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.reflect.Method; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@ApiStatus.Internal ++@NullMarked ++public class MethodHandleEventExecutor implements EventExecutor { ++ ++ private final Class eventClass; ++ private final MethodHandle handle; ++ ++ public MethodHandleEventExecutor(final Class eventClass, final MethodHandle handle) { ++ this.eventClass = eventClass; ++ this.handle = handle; ++ } ++ ++ public MethodHandleEventExecutor(final Class eventClass, final Method m) { ++ this.eventClass = eventClass; ++ try { ++ m.setAccessible(true); ++ this.handle = MethodHandles.lookup().unreflect(m); ++ } catch (final IllegalAccessException e) { ++ throw new AssertionError("Unable to set accessible", e); ++ } ++ } ++ ++ @Override ++ public void execute(final Listener listener, final Event event) throws EventException { ++ if (!this.eventClass.isInstance(event)) return; ++ try { ++ this.handle.invoke(listener, event); ++ } catch (final Throwable t) { ++ SneakyThrow.sneaky(t); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bbdb5b472df116b71c459bdc6cc4b74267ea0f5e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +@@ -0,0 +1,44 @@ ++package com.destroystokyo.paper.event.executor; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import com.google.common.base.Preconditions; ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++public class StaticMethodHandleEventExecutor implements EventExecutor { ++ ++ private final Class eventClass; ++ private final MethodHandle handle; ++ ++ public StaticMethodHandleEventExecutor(final Class eventClass, final Method m) { ++ Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); ++ Preconditions.checkArgument(eventClass != null, "eventClass is null"); ++ this.eventClass = eventClass; ++ try { ++ m.setAccessible(true); ++ this.handle = MethodHandles.lookup().unreflect(m); ++ } catch (final IllegalAccessException e) { ++ throw new AssertionError("Unable to set accessible", e); ++ } ++ } ++ ++ @Override ++ public void execute(final Listener listener, final Event event) throws EventException { ++ if (!this.eventClass.isInstance(event)) return; ++ try { ++ this.handle.invoke(event); ++ } catch (final Throwable throwable) { ++ SneakyThrow.sneaky(throwable); ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java +new file mode 100644 +index 0000000000000000000000000000000000000000..abfcb6e8383ff311940d82afe4ff990649a082dc +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ASMEventExecutorGenerator.java +@@ -0,0 +1,59 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import java.lang.reflect.Method; ++import java.util.concurrent.atomic.AtomicInteger; ++import org.bukkit.plugin.EventExecutor; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.objectweb.asm.ClassWriter; ++import org.objectweb.asm.Type; ++import org.objectweb.asm.commons.GeneratorAdapter; ++ ++import static org.objectweb.asm.Opcodes.ACC_PUBLIC; ++import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; ++import static org.objectweb.asm.Opcodes.INVOKESPECIAL; ++import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; ++import static org.objectweb.asm.Opcodes.V1_8; ++ ++@ApiStatus.Internal ++@NullMarked ++public final class ASMEventExecutorGenerator { ++ ++ private static final String EXECUTE_DESCRIPTOR = "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V"; ++ ++ public static byte[] generateEventExecutor(final Method m, final String name) { ++ final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ++ writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[]{Type.getInternalName(EventExecutor.class)}); ++ // Generate constructor ++ GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "", "()V", null, null), ACC_PUBLIC, "", "()V"); ++ methodGenerator.loadThis(); ++ methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); // Invoke the super class (Object) constructor ++ methodGenerator.returnValue(); ++ methodGenerator.endMethod(); ++ // Generate the execute method ++ methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR, null, null), ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR); ++ methodGenerator.loadArg(0); ++ methodGenerator.checkCast(Type.getType(m.getDeclaringClass())); ++ methodGenerator.loadArg(1); ++ methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0])); ++ methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface()); ++ // The only purpose of this switch statement is to generate the correct pop instruction, should the event handler method return something other than void. ++ // Non-void event handlers will be unsupported in a future release. ++ switch (Type.getType(m.getReturnType()).getSize()) { ++ // case 0 is omitted because the only type that has size 0 is void - no pop instruction needed. ++ case 1 -> methodGenerator.pop(); // handles reference types and most primitives ++ case 2 -> methodGenerator.pop2(); // handles long and double ++ } ++ methodGenerator.returnValue(); ++ methodGenerator.endMethod(); ++ writer.visitEnd(); ++ return writer.toByteArray(); ++ } ++ ++ public static AtomicInteger NEXT_ID = new AtomicInteger(1); ++ ++ public static String generateName() { ++ final int id = NEXT_ID.getAndIncrement(); ++ return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..581561fbd32c81ab1774ba8f0b7f3cec9392d99a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/ClassDefiner.java +@@ -0,0 +1,35 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++public interface ClassDefiner { ++ ++ /** ++ * Returns if the defined classes can bypass access checks ++ * ++ * @return if classes bypass access checks ++ */ ++ default boolean isBypassAccessChecks() { ++ return false; ++ } ++ ++ /** ++ * Define a class ++ * ++ * @param parentLoader the parent classloader ++ * @param name the name of the class ++ * @param data the class data to load ++ * @return the defined class ++ * @throws ClassFormatError if the class data is invalid ++ * @throws NullPointerException if any of the arguments are null ++ */ ++ Class defineClass(ClassLoader parentLoader, String name, byte[] data); ++ ++ static ClassDefiner getInstance() { ++ return SafeClassDefiner.INSTANCE; ++ } ++ ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..48bcc72293c2a31b6e2dd2dcd6a79d618c72a137 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/executor/asm/SafeClassDefiner.java +@@ -0,0 +1,66 @@ ++package com.destroystokyo.paper.event.executor.asm; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.MapMaker; ++import java.util.concurrent.ConcurrentMap; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++public class SafeClassDefiner implements ClassDefiner { ++ ++ /* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner(); ++ ++ private SafeClassDefiner() { ++ } ++ ++ private final ConcurrentMap loaders = new MapMaker().weakKeys().makeMap(); ++ ++ @Override ++ public Class defineClass(final ClassLoader parentLoader, final String name, final byte[] data) { ++ final GeneratedClassLoader loader = this.loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new); ++ synchronized (loader.getClassLoadingLock(name)) { ++ Preconditions.checkState(!loader.hasClass(name), "%s already defined", name); ++ final Class c = loader.define(name, data); ++ assert c.getName().equals(name); ++ return c; ++ } ++ } ++ ++ private static class GeneratedClassLoader extends ClassLoader { ++ ++ static { ++ ClassLoader.registerAsParallelCapable(); ++ } ++ ++ protected GeneratedClassLoader(final ClassLoader parent) { ++ super(parent); ++ } ++ ++ private Class define(final String name, final byte[] data) { ++ synchronized (this.getClassLoadingLock(name)) { ++ assert !this.hasClass(name); ++ final Class c = this.defineClass(name, data, 0, data.length); ++ this.resolveClass(c); ++ return c; ++ } ++ } ++ ++ @Override ++ public Object getClassLoadingLock(final String name) { ++ return super.getClassLoadingLock(name); ++ } ++ ++ public boolean hasClass(final String name) { ++ synchronized (this.getClassLoadingLock(name)) { ++ try { ++ Class.forName(name); ++ return true; ++ } catch (final ClassNotFoundException e) { ++ return false; ++ } ++ } ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java +index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137befa646455 100644 +--- a/src/main/java/org/bukkit/plugin/EventExecutor.java ++++ b/src/main/java/org/bukkit/plugin/EventExecutor.java +@@ -5,9 +5,75 @@ import org.bukkit.event.EventException; + import org.bukkit.event.Listener; + import org.jetbrains.annotations.NotNull; + ++// Paper start ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentMap; ++import java.util.function.Function; ++ ++import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; ++import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor; ++import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; ++import com.destroystokyo.paper.event.executor.asm.ClassDefiner; ++import com.google.common.base.Preconditions; ++// Paper end ++ + /** + * Interface which defines the class for event call backs to plugins + */ + public interface EventExecutor { + public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException; ++ ++ // Paper start ++ ConcurrentMap> eventExecutorMap = new ConcurrentHashMap>() { ++ @NotNull ++ @Override ++ public Class computeIfAbsent(@NotNull Method key, @NotNull Function> mappingFunction) { ++ Class executorClass = get(key); ++ if (executorClass != null) ++ return executorClass; ++ ++ //noinspection SynchronizationOnLocalVariableOrMethodParameter ++ synchronized (key) { ++ executorClass = get(key); ++ if (executorClass != null) ++ return executorClass; ++ ++ return super.computeIfAbsent(key, mappingFunction); ++ } ++ } ++ }; ++ ++ @NotNull ++ public static EventExecutor create(@NotNull Method m, @NotNull Class eventClass) { ++ Preconditions.checkNotNull(m, "Null method"); ++ Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); ++ Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); ++ ClassDefiner definer = ClassDefiner.getInstance(); ++ if (Modifier.isStatic(m.getModifiers())) { ++ return new StaticMethodHandleEventExecutor(eventClass, m); ++ } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { ++ // get the existing generated EventExecutor class for the Method or generate one ++ Class executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { ++ String name = ASMEventExecutorGenerator.generateName(); ++ byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); ++ return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); ++ }); ++ ++ try { ++ EventExecutor asmExecutor = executorClass.newInstance(); ++ // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) ++ return (listener, event) -> { ++ if (!eventClass.isInstance(event)) return; ++ asmExecutor.execute(listener, event); ++ }; ++ } catch (InstantiationException | IllegalAccessException e) { ++ throw new AssertionError("Unable to initialize generated event executor", e); ++ } ++ } else { ++ return new MethodHandleEventExecutor(eventClass, m); ++ } ++ } ++ // Paper end + } diff --git a/patches/api/0009-Paper-Plugins.patch b/patches/api/0009-Paper-Plugins.patch new file mode 100644 index 000000000000..afecfce3b304 --- /dev/null +++ b/patches/api/0009-Paper-Plugins.patch @@ -0,0 +1,2550 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 6 Jul 2022 23:00:36 -0400 +Subject: [PATCH] Paper Plugins + + +diff --git a/build.gradle.kts b/build.gradle.kts +index 43086f7d201c0988086ef06cfe5a0f866d130961..305c2f3226f59e36ab1059b52e111178790aa6e8 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -66,7 +66,7 @@ dependencies { + implementation("org.ow2.asm:asm-commons:9.7.1") + // Paper end + +- compileOnly("org.apache.maven:maven-resolver-provider:3.9.6") ++ api("org.apache.maven:maven-resolver-provider:3.9.6") // Paper - make API dependency for Paper Plugins + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") + compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") + +@@ -156,6 +156,7 @@ tasks.withType { + "https://jd.advntr.dev/text-serializer-plain/$adventureVersion/", + "https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/", + // Paper end ++ "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper + ) + options.tags("apiNote:a:API Note:") + +diff --git a/src/main/java/io/papermc/paper/plugin/PermissionManager.java b/src/main/java/io/papermc/paper/plugin/PermissionManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c78ada48e27c5552529fe8d5bc23db1dac94e481 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/PermissionManager.java +@@ -0,0 +1,166 @@ ++package io.papermc.paper.plugin; ++ ++import java.util.List; ++import java.util.Set; ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * A permission manager implementation to keep backwards compatibility partially alive with existing plugins that used ++ * the bukkit one before. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public interface PermissionManager { ++ ++ /** ++ * Gets a {@link Permission} from its fully qualified name ++ * ++ * @param name Name of the permission ++ * @return Permission, or null if none ++ */ ++ @Nullable Permission getPermission(String name); ++ ++ /** ++ * Adds a {@link Permission} to this plugin manager. ++ *

      ++ * If a permission is already defined with the given name of the new ++ * permission, an exception will be thrown. ++ * ++ * @param perm Permission to add ++ * @throws IllegalArgumentException Thrown when a permission with the same ++ * name already exists ++ */ ++ void addPermission(Permission perm); ++ ++ /** ++ * Removes a {@link Permission} registration from this plugin manager. ++ *

      ++ * If the specified permission does not exist in this plugin manager, ++ * nothing will happen. ++ *

      ++ * Removing a permission registration will not remove the ++ * permission from any {@link Permissible}s that have it. ++ * ++ * @param perm Permission to remove ++ */ ++ void removePermission(Permission perm); ++ ++ /** ++ * Removes a {@link Permission} registration from this plugin manager. ++ *

      ++ * If the specified permission does not exist in this plugin manager, ++ * nothing will happen. ++ *

      ++ * Removing a permission registration will not remove the ++ * permission from any {@link Permissible}s that have it. ++ * ++ * @param name Permission to remove ++ */ ++ void removePermission(String name); ++ ++ /** ++ * Gets the default permissions for the given op status ++ * ++ * @param op Which set of default permissions to get ++ * @return The default permissions ++ */ ++ Set getDefaultPermissions(boolean op); ++ ++ /** ++ * Recalculates the defaults for the given {@link Permission}. ++ *

      ++ * This will have no effect if the specified permission is not registered ++ * here. ++ * ++ * @param perm Permission to recalculate ++ */ ++ void recalculatePermissionDefaults(Permission perm); ++ ++ /** ++ * Subscribes the given Permissible for information about the requested ++ * Permission, by name. ++ *

      ++ * If the specified Permission changes in any form, the Permissible will ++ * be asked to recalculate. ++ * ++ * @param permission Permission to subscribe to ++ * @param permissible Permissible subscribing ++ */ ++ void subscribeToPermission(String permission, Permissible permissible); ++ ++ /** ++ * Unsubscribes the given Permissible for information about the requested ++ * Permission, by name. ++ * ++ * @param permission Permission to unsubscribe from ++ * @param permissible Permissible subscribing ++ */ ++ void unsubscribeFromPermission(String permission, Permissible permissible); ++ ++ /** ++ * Gets a set containing all subscribed {@link Permissible}s to the given ++ * permission, by name ++ * ++ * @param permission Permission to query for ++ * @return Set containing all subscribed permissions ++ */ ++ Set getPermissionSubscriptions(String permission); ++ ++ /** ++ * Subscribes to the given Default permissions by operator status ++ *

      ++ * If the specified defaults change in any form, the Permissible will be ++ * asked to recalculate. ++ * ++ * @param op Default list to subscribe to ++ * @param permissible Permissible subscribing ++ */ ++ void subscribeToDefaultPerms(boolean op, Permissible permissible); ++ ++ /** ++ * Unsubscribes from the given Default permissions by operator status ++ * ++ * @param op Default list to unsubscribe from ++ * @param permissible Permissible subscribing ++ */ ++ void unsubscribeFromDefaultPerms(boolean op, Permissible permissible); ++ ++ /** ++ * Gets a set containing all subscribed {@link Permissible}s to the given ++ * default list, by op status ++ * ++ * @param op Default list to query for ++ * @return Set containing all subscribed permissions ++ */ ++ Set getDefaultPermSubscriptions(boolean op); ++ ++ /** ++ * Gets a set of all registered permissions. ++ *

      ++ * This set is a copy and will not be modified live. ++ * ++ * @return Set containing all current registered permissions ++ */ ++ Set getPermissions(); ++ ++ /** ++ * Adds a list of permissions. ++ *

      ++ * This is meant as an optimization for adding multiple permissions without recalculating each permission. ++ * ++ * @param perm permission ++ */ ++ void addPermissions(List perm); ++ ++ /** ++ * Clears the current registered permissinos. ++ *

      ++ * This is used for reloading. ++ */ ++ void clearPermissions(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4c47414fc08e1183b1e59369bacc4d7f7042f262 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java +@@ -0,0 +1,16 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin ++ * instantiation logic. ++ * A bootstrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances ++ * like the plugin's configuration or logger during the plugins bootstrap. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface BootstrapContext extends PluginProviderContext { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6696dcd8049e869bd1733f7c67ff802c54d7c37 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import io.papermc.paper.plugin.provider.util.ProviderUtil; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A plugin bootstrap is meant for loading certain parts of the plugin before the server is loaded. ++ *

      ++ * Plugin bootstrapping allows values to be initialized in certain parts of the server that might not be allowed ++ * when the server is running. ++ *

      ++ * Your bootstrap class will be on the same classloader as your JavaPlugin. ++ *

      ++ * All calls to Bukkit may throw a NullPointerExceptions or return null unexpectedly. You should only call api methods that are explicitly documented to work in the bootstrapper ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.OverrideOnly ++public interface PluginBootstrap { ++ ++ /** ++ * Called by the server, allowing you to bootstrap the plugin with a context that provides things like a logger and your shared plugin configuration file. ++ * ++ * @param context the server provided context ++ */ ++ void bootstrap(BootstrapContext context); ++ ++ /** ++ * Called by the server to instantiate your main class. ++ * Plugins may override this logic to define custom creation logic for said instance, like passing addition ++ * constructor arguments. ++ * ++ * @param context the server created bootstrap object ++ * @return the server requested instance of the plugins main class. ++ */ ++ default JavaPlugin createPlugin(final PluginProviderContext context) { ++ return ProviderUtil.loadClass(context.getConfiguration().getMainClass(), JavaPlugin.class, this.getClass().getClassLoader()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..19bb302ab264b72306d9bd15e9c40ade6dde7ee7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import java.nio.file.Path; ++import net.kyori.adventure.text.logger.slf4j.ComponentLogger; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin ++ * instantiation logic. ++ * A bootstrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances ++ * like the plugin's configuration or logger during the plugins bootstrap. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface PluginProviderContext { ++ ++ /** ++ * Provides the plugin's configuration. ++ * ++ * @return the plugin's configuration ++ */ ++ PluginMeta getConfiguration(); ++ ++ /** ++ * Provides the path to the data directory of the plugin. ++ * ++ * @return the previously described path ++ */ ++ Path getDataDirectory(); ++ ++ /** ++ * Provides the logger used for this plugin. ++ * ++ * @return the logger instance ++ */ ++ ComponentLogger getLogger(); ++ ++ /** ++ * Provides the path to the originating source of the plugin, such as the plugin's JAR file. ++ * ++ * @return the previously described path ++ */ ++ Path getPluginSource(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3c768d5ccf490e962d9638e92d4ea7c85670bad8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java +@@ -0,0 +1,186 @@ ++package io.papermc.paper.plugin.configuration; ++ ++import java.util.List; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.bukkit.plugin.PluginLoadOrder; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * This class acts as an abstraction for a plugin configuration. ++ */ ++@ApiStatus.Experimental // Subject to change! ++@NullMarked ++@ApiStatus.NonExtendable ++public interface PluginMeta { ++ ++ /** ++ * Provides the name of the plugin. This name uniquely identifies the plugin amongst all loaded plugins on the ++ * server. ++ *

        ++ *
      • Will only contain alphanumeric characters, underscores, hyphens, ++ * and periods: [a-zA-Z0-9_\-\.]. ++ *
      • Typically used for identifying the plugin data folder. ++ *
      • The name also acts as the token referenced in {@link #getPluginDependencies()}, ++ * {@link #getPluginSoftDependencies()}, and {@link #getLoadBeforePlugins()}. ++ *
      ++ *

      ++ * In the plugin.yml, this entry is named name. ++ *

      ++ * Example:

      name: MyPlugin
      ++ * ++ * @return the name of the plugin ++ */ ++ String getName(); ++ ++ /** ++ * Returns the display name of the plugin, including the version. ++ * ++ * @return a descriptive name of the plugin and respective version ++ */ ++ default String getDisplayName() { ++ return this.getName() + " v" + this.getVersion(); ++ } ++ ++ /** ++ * Provides the fully qualified class name of the main class for the plugin. ++ * A subtype of {@link JavaPlugin} is expected at this location. ++ * ++ * @return the fully qualified class name of the plugin's main class. ++ */ ++ String getMainClass(); ++ ++ /** ++ * Returns the phase of the server startup logic that the plugin should be loaded. ++ * ++ * @return the plugin load order ++ * @see PluginLoadOrder for further details regards the available load orders. ++ */ ++ PluginLoadOrder getLoadOrder(); ++ ++ /** ++ * Provides the version of this plugin as defined by the plugin. ++ * There is no inherit format defined/enforced for the version of a plugin, however a common approach ++ * might be semantic versioning. ++ * ++ * @return the string representation of the plugin's version ++ */ ++ String getVersion(); ++ ++ /** ++ * Provides the prefix that should be used for the plugin logger. ++ * The logger prefix allows plugins to overwrite the usual default of the logger prefix, which is the name of the ++ * plugin. ++ * ++ * @return the specific overwrite of the logger prefix as defined by the plugin. If the plugin did not define a ++ * custom logger prefix, this method will return null ++ */ ++ @Nullable String getLoggerPrefix(); ++ ++ /** ++ * Provides a list of dependencies that are required for this plugin to load. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the ++ * dependencies. ++ *

      ++ * If any of the dependencies defined by this list are not installed on the server, this plugin will fail to load. ++ * ++ * @return an immutable list of required dependency names ++ */ ++ List getPluginDependencies(); ++ ++ /** ++ * Provides a list of dependencies that are used but not required by this plugin. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the soft ++ * dependencies. ++ *

      ++ * If these dependencies are installed on the server, they will be loaded first and supplied as dependencies to this ++ * plugin, however the plugin will load even if these dependencies are not installed. ++ * ++ * @return immutable list of soft dependencies ++ */ ++ List getPluginSoftDependencies(); ++ ++ /** ++ * Provides a list of plugins that should be loaded before this plugin is loaded. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the ++ * plugins that should be loaded before the plugin described by this plugin meta. ++ *

      ++ * The plugins referenced in the list provided by this method are not considered dependencies of this plugin and ++ * are hence not available to the plugin at runtime. They merely load before this plugin. ++ * ++ * @return immutable list of plugins to load before this plugin ++ */ ++ List getLoadBeforePlugins(); ++ ++ /** ++ * Returns the list of plugins/dependencies that this plugin provides. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, for each plugin ++ * it provides the expected classes for. ++ * ++ * @return immutable list of provided plugins/dependencies ++ */ ++ List getProvidedPlugins(); ++ ++ /** ++ * Provides the list of authors that are credited with creating this plugin. ++ * The author names are in no particular format. ++ * ++ * @return an immutable list of the plugin's authors ++ */ ++ List getAuthors(); ++ ++ /** ++ * Provides a list of contributors that contributed to the plugin but are not considered authors. ++ * The names of the contributors are in no particular format. ++ * ++ * @return an immutable list of the plugin's contributors ++ */ ++ List getContributors(); ++ ++ /** ++ * Gives a human-friendly description of the functionality the plugin ++ * provides. ++ * ++ * @return description or null if the plugin did not define a human readable description. ++ */ ++ @Nullable String getDescription(); ++ ++ /** ++ * Provides the website for the plugin or the plugin's author. ++ * The defined string value is not guaranteed to be in the form of a url. ++ * ++ * @return a string representation of the website that serves as the main hub for this plugin/its author. ++ */ ++ @Nullable String getWebsite(); ++ ++ /** ++ * Provides the list of permissions that are defined via the plugin meta instance. ++ * ++ * @return an immutable list of permissions ++ */ ++ // TODO: Do we even want this? Why not just use the bootstrapper ++ List getPermissions(); ++ ++ /** ++ * Provides the default values that apply to the permissions defined in this plugin meta. ++ * ++ * @return the bukkit permission default container. ++ * @see #getPermissions() ++ */ ++ // TODO: Do we even want this? Why not just use the bootstrapper ++ PermissionDefault getPermissionDefault(); ++ ++ /** ++ * Gets the api version that this plugin supports. ++ * Nullable if this version is not specified, and should be ++ * considered legacy (spigot plugins only) ++ * ++ * @return the version string made up of the major and minor version (e.g. 1.18 or 1.19). Minor versions like 1.18.2 ++ * are unified to their major release version (in this example 1.18) ++ */ ++ @Nullable String getAPIVersion(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/configuration/package-info.java b/src/main/java/io/papermc/paper/plugin/configuration/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ddb3076124365d0d1a5caa32d4dcb1f4314dd7ae +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/configuration/package-info.java +@@ -0,0 +1,8 @@ ++/** ++ * The paper configuration package contains the new java representation of a plugins configuration file. ++ * While most values are described in detail on {@link io.papermc.paper.plugin.configuration.PluginMeta}, a full ++ * entry on the paper contains a full and extensive example of possible configurations of the paper-plugin.yml. ++ * @see Extensive documentation and examples of the paper-plugin.yml ++ * ++ */ ++package io.papermc.paper.plugin.configuration; +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ddb768057cdfd9202e4386494fd5f643692c73a1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java +@@ -0,0 +1,37 @@ ++package io.papermc.paper.plugin.loader; ++ ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A mutable builder that may be used to collect and register all {@link ClassPathLibrary} instances a ++ * {@link PluginLoader} aims to provide to its plugin at runtime. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface PluginClasspathBuilder { ++ ++ /** ++ * Adds a new classpath library to this classpath builder. ++ *

      ++ * As a builder, this method does not invoke {@link ClassPathLibrary#register(LibraryStore)} and ++ * may hence be run without invoking potential IO performed by a {@link ClassPathLibrary} during resolution. ++ *

      ++ * The paper api provides pre implemented {@link ClassPathLibrary} types that allow easy inclusion of existing ++ * libraries on disk or on remote maven repositories. ++ * ++ * @param classPathLibrary the library instance to add to this builder ++ * @return self ++ * @see io.papermc.paper.plugin.loader.library.impl.JarLibrary ++ * @see io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver ++ */ ++ @Contract("_ -> this") ++ PluginClasspathBuilder addLibrary(ClassPathLibrary classPathLibrary); ++ ++ PluginProviderContext getContext(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c2d029e4474cc00c84e5b3f7fceec4c3f30b486b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java +@@ -0,0 +1,31 @@ ++package io.papermc.paper.plugin.loader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A plugin loader is responsible for creating certain aspects of a plugin before it is created. ++ *

      ++ * The goal of the plugin loader is the creation of an expected/dynamic environment for the plugin to load into. ++ * This, as of right now, only applies to creating the expected classpath for the plugin, e.g. supplying external ++ * libraries to the plugin. ++ *

      ++ * It should be noted that this class will be called from a different classloader, this will cause any static values ++ * set in this class/any other classes loaded not to persist when the plugin loads. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.OverrideOnly ++public interface PluginLoader { ++ ++ /** ++ * Called by the server to allows plugins to configure the runtime classpath that the plugin is run on. ++ * This allows plugin loaders to configure dependencies for the plugin where jars can be downloaded or ++ * provided during runtime. ++ * ++ * @param classpathBuilder a mutable classpath builder that may be used to register custom runtime dependencies ++ * for the plugin the loader was registered for. ++ */ ++ void classloader(PluginClasspathBuilder classpathBuilder); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8a07333a592056bab1d26d811316bb5ea5f30e18 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * The classpath library interface represents libraries that are capable of registering themselves via ++ * {@link #register(LibraryStore)} on any given {@link LibraryStore}. ++ */ ++@NullMarked ++public interface ClassPathLibrary { ++ ++ /** ++ * Called to register the library this class path library represents into the passed library store. ++ * This method may either be implemented by the plugins themselves if they need complex logic, or existing ++ * API exposed implementations of this interface may be used. ++ * ++ * @param store the library store instance to register this library into ++ * @throws LibraryLoadingException if library loading failed for this classpath library ++ */ ++ void register(LibraryStore store) throws LibraryLoadingException; ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..79ba423a364b50588f3ee87fdc69155cb8e64ad0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java +@@ -0,0 +1,15 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++/** ++ * Indicates that an exception has occured while loading a library. ++ */ ++public class LibraryLoadingException extends RuntimeException { ++ ++ public LibraryLoadingException(String s) { ++ super(s); ++ } ++ ++ public LibraryLoadingException(String s, Exception e) { ++ super(s, e); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93ef8e369a158c25bc4fdd553faf13c1826ad872 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++import java.nio.file.Path; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents a storage that stores library jars. ++ *

      ++ * The library store api allows plugins to register specific dependencies into their runtime classloader when their ++ * {@link io.papermc.paper.plugin.loader.PluginLoader} is processed. ++ * ++ * @see io.papermc.paper.plugin.loader.PluginLoader ++ */ ++@ApiStatus.Internal ++@NullMarked ++public interface LibraryStore { ++ ++ /** ++ * Adds the provided library path to this library store. ++ * ++ * @param library path to the libraries jar file on the disk ++ */ ++ void addLibrary(Path library); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9efcd9a62d6439eb27fc4e08498b4b7fbbdecb3c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.plugin.loader.library.impl; ++ ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryLoadingException; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A simple jar library implementation of the {@link ClassPathLibrary} that allows {@link io.papermc.paper.plugin.loader.PluginLoader}s to ++ * append a jar stored on the local file system into their runtime classloader. ++ *

      ++ * An example creation of the jar library type may look like this: ++ *

      {@code
      ++ *   final JarLibrary customLibrary = new JarLibrary(Path.of("libs/custom-library-1.24.jar"));
      ++ * }
      ++ * resulting in a jar library that provides the jar at {@code libs/custom-library-1.24.jar} to the plugins classloader ++ * at runtime. ++ *

      ++ * The jar library implementation will error if the file does not exist at the specified path. ++ */ ++@NullMarked ++public class JarLibrary implements ClassPathLibrary { ++ ++ private final Path path; ++ ++ /** ++ * Creates a new jar library that references the jar file found at the provided path. ++ * ++ * @param path the path, relative to the JVMs start directory. ++ */ ++ public JarLibrary(final Path path) { ++ this.path = path; ++ } ++ ++ @Override ++ public void register(final LibraryStore store) throws LibraryLoadingException { ++ if (Files.notExists(this.path)) { ++ throw new LibraryLoadingException("Could not find library at " + this.path); ++ } ++ ++ store.addLibrary(this.path); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java +new file mode 100644 +index 0000000000000000000000000000000000000000..107705db2d82b7c191e5e625ec888e0bc3b03831 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java +@@ -0,0 +1,133 @@ ++package io.papermc.paper.plugin.loader.library.impl; ++ ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryLoadingException; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import java.io.File; ++import java.util.ArrayList; ++import java.util.List; ++import org.apache.maven.repository.internal.MavenRepositorySystemUtils; ++import org.eclipse.aether.DefaultRepositorySystemSession; ++import org.eclipse.aether.RepositorySystem; ++import org.eclipse.aether.collection.CollectRequest; ++import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; ++import org.eclipse.aether.graph.Dependency; ++import org.eclipse.aether.impl.DefaultServiceLocator; ++import org.eclipse.aether.repository.LocalRepository; ++import org.eclipse.aether.repository.RemoteRepository; ++import org.eclipse.aether.repository.RepositoryPolicy; ++import org.eclipse.aether.resolution.ArtifactResult; ++import org.eclipse.aether.resolution.DependencyRequest; ++import org.eclipse.aether.resolution.DependencyResolutionException; ++import org.eclipse.aether.resolution.DependencyResult; ++import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; ++import org.eclipse.aether.spi.connector.transport.TransporterFactory; ++import org.eclipse.aether.transfer.AbstractTransferListener; ++import org.eclipse.aether.transfer.TransferCancelledException; ++import org.eclipse.aether.transfer.TransferEvent; ++import org.eclipse.aether.transport.http.HttpTransporterFactory; ++import org.jspecify.annotations.NullMarked; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++/** ++ * The maven library resolver acts as a resolver for yet to be resolved jar libraries that may be pulled from a ++ * remote maven repository. ++ *

      ++ * Plugins may create and configure a {@link MavenLibraryResolver} by creating a new one and registering both ++ * a dependency artifact that should be resolved to a library at runtime and the repository it is found in. ++ * An example of this would be the inclusion of the jooq library for typesafe SQL queries: ++ *

      {@code
      ++ * MavenLibraryResolver resolver = new MavenLibraryResolver();
      ++ * resolver.addDependency(new Dependency(new DefaultArtifact("org.jooq:jooq:3.17.7"), null));
      ++ * resolver.addRepository(new RemoteRepository.Builder(
      ++ *     "central", "default", "https://repo1.maven.org/maven2/"
      ++ * ).build());
      ++ * }
      ++ *

      ++ * Plugins may create and register a {@link MavenLibraryResolver} after configuring it. ++ */ ++@NullMarked ++public class MavenLibraryResolver implements ClassPathLibrary { ++ ++ private static final Logger LOGGER = LoggerFactory.getLogger("MavenLibraryResolver"); ++ ++ private final RepositorySystem repository; ++ private final DefaultRepositorySystemSession session; ++ private final List repositories = new ArrayList<>(); ++ private final List dependencies = new ArrayList<>(); ++ ++ /** ++ * Creates a new maven library resolver instance. ++ *

      ++ * The created instance will use the servers {@code libraries} folder to cache fetched libraries in. ++ * Notably, the resolver is created without any repository, not even maven central. ++ * It is hence crucial that plugins which aim to use this api register all required repositories before ++ * submitting the {@link MavenLibraryResolver} to the {@link io.papermc.paper.plugin.loader.PluginClasspathBuilder}. ++ */ ++ public MavenLibraryResolver() { ++ final DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); ++ locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); ++ locator.addService(TransporterFactory.class, HttpTransporterFactory.class); ++ ++ this.repository = locator.getService(RepositorySystem.class); ++ this.session = MavenRepositorySystemUtils.newSession(); ++ ++ this.session.setSystemProperties(System.getProperties()); ++ this.session.setChecksumPolicy(RepositoryPolicy.CHECKSUM_POLICY_FAIL); ++ this.session.setLocalRepositoryManager(this.repository.newLocalRepositoryManager(this.session, new LocalRepository("libraries"))); ++ this.session.setTransferListener(new AbstractTransferListener() { ++ @Override ++ public void transferInitiated(final TransferEvent event) throws TransferCancelledException { ++ LOGGER.info("Downloading {}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName()); ++ } ++ }); ++ this.session.setReadOnly(); ++ } ++ ++ /** ++ * Adds the provided dependency to the library resolver. ++ * The artifact from the first valid repository matching the passed dependency will be chosen. ++ * ++ * @param dependency the definition of the dependency the maven library resolver should resolve when running ++ * @see MavenLibraryResolver#addRepository(RemoteRepository) ++ */ ++ public void addDependency(final Dependency dependency) { ++ this.dependencies.add(dependency); ++ } ++ ++ /** ++ * Adds the provided repository to the library resolver. ++ * The order in which these are added does matter, as dependency resolving will start at the first added ++ * repository. ++ * ++ * @param remoteRepository the configuration that defines the maven repository this library resolver should fetch ++ * dependencies from ++ */ ++ public void addRepository(final RemoteRepository remoteRepository) { ++ this.repositories.add(remoteRepository); ++ } ++ ++ /** ++ * Resolves the provided dependencies and adds them to the library store. ++ * ++ * @param store the library store the then resolved and downloaded dependencies are registered into ++ * @throws LibraryLoadingException if resolving a dependency failed ++ */ ++ @Override ++ public void register(final LibraryStore store) throws LibraryLoadingException { ++ final List repos = this.repository.newResolutionRepositories(this.session, this.repositories); ++ ++ final DependencyResult result; ++ try { ++ result = this.repository.resolveDependencies(this.session, new DependencyRequest(new CollectRequest((Dependency) null, this.dependencies, repos), null)); ++ } catch (final DependencyResolutionException ex) { ++ throw new LibraryLoadingException("Error resolving libraries", ex); ++ } ++ ++ for (final ArtifactResult artifact : result.getArtifactResults()) { ++ final File file = artifact.getArtifact().getFile(); ++ store.addLibrary(file.toPath()); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..75fe408ec742319c3cba2461b33b2a6e8b22d231 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java +@@ -0,0 +1,35 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * The class loader access interface is an internal representation of a class accesses' ability to see types ++ * from other {@link ConfiguredPluginClassLoader}. ++ *

      ++ * An example of this would be a class loader access representing a plugin. The class loader access in that case would ++ * only return {@code true} on calls for {@link #canAccess(ConfiguredPluginClassLoader)} if the passed class loader ++ * is owned by a direct or transitive dependency of the plugin, preventing the plugin for accidentally discovering and ++ * using class types that are supplied by plugins/libraries the plugin did not actively define as a dependency. ++ */ ++@NullMarked ++@ApiStatus.Internal ++public interface ClassLoaderAccess { ++ ++ /** ++ * Evaluates if this class loader access is allowed to access types provided by the passed {@link ++ * ConfiguredPluginClassLoader}. ++ *

      ++ * This interface method does not offer any further contracts on the interface level, as the logic to determine ++ * what class loaders this class loader access is allowed to retrieve types from depends heavily on the type of ++ * access. ++ * Legacy spigot types for example may access any class loader available on the server, while modern paper plugins ++ * are properly limited to their dependency tree. ++ * ++ * @param classLoader the class loader for which access should be evaluated ++ * @return a plain boolean flag, {@code true} indicating that this class loader access is allowed to access types ++ * from the passed configured plugin class loader, {@code false} indicating otherwise. ++ */ ++ boolean canAccess(ConfiguredPluginClassLoader classLoader); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7c23e0a1a38f8b89484aee160647f751088903cd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java +@@ -0,0 +1,70 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import java.io.Closeable; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * The configured plugin class loader represents an internal abstraction over the classloaders used by the server ++ * to load and access a plugins classes during runtime. ++ *

      ++ * It implements {@link Closeable} to define the ability to shutdown and close the classloader that implements this ++ * interface. ++ */ ++@NullMarked ++@ApiStatus.Internal ++public interface ConfiguredPluginClassLoader extends Closeable { ++ ++ /** ++ * Provides the configuration of the plugin that this plugin classloader provides type access to. ++ * ++ * @return the plugin meta instance, holding all meta information about the plugin instance. ++ */ ++ PluginMeta getConfiguration(); ++ ++ /** ++ * Attempts to load a class from this plugin class loader using the passed fully qualified name. ++ * This lookup logic can be configured through the following parameters to define how wide or how narrow the ++ * class lookup should be. ++ * ++ * @param name the fully qualified name of the class to load ++ * @param resolve whether the class should be resolved if needed or not ++ * @param checkGlobal whether this lookup should check transitive dependencies, including either the legacy spigot ++ * global class loader or the paper {@link PluginClassLoaderGroup} ++ * @param checkLibraries whether the defined libraries should be checked for the class or not ++ * @return the class found at the fully qualified class name passed under the passed restrictions ++ * @throws ClassNotFoundException if the class could not be found considering the passed restrictions ++ * @see ClassLoader#loadClass(String) ++ * @see Class#forName(String, boolean, ClassLoader) ++ */ ++ Class loadClass(String name, ++ boolean resolve, ++ boolean checkGlobal, ++ boolean checkLibraries) throws ClassNotFoundException; ++ ++ /** ++ * Initializes both this configured plugin class loader and the java plugin passed to link to each other. ++ * This logic is to be called exactly once when the initial setup between the class loader and the instantiated ++ * {@link JavaPlugin} is loaded. ++ * ++ * @param plugin the {@link JavaPlugin} that should be interlinked with this class loader. ++ */ ++ void init(JavaPlugin plugin); ++ ++ /** ++ * Gets the plugin held by this class loader. ++ * ++ * @return the plugin or null if it doesn't exist yet ++ */ ++ @Nullable JavaPlugin getPlugin(); ++ ++ /** ++ * Get the plugin classloader group ++ * that is used by the underlying classloader ++ * @return classloader ++ */ ++ @Nullable PluginClassLoaderGroup getGroup(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fefc87d5ffd36b848a7adb326a3a741e9edb28df +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java +@@ -0,0 +1,92 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.bukkit.plugin.java.PluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * The plugin classloader storage is an internal type that is used to manage existing classloaders on the server. ++ *

      ++ * The paper classloader storage is also responsible for storing added {@link ConfiguredPluginClassLoader}s into ++ * {@link PluginClassLoaderGroup}s, via {@link #registerOpenGroup(ConfiguredPluginClassLoader)}, ++ * {@link #registerSpigotGroup(PluginClassLoader)} and {@link ++ * #registerAccessBackedGroup(ConfiguredPluginClassLoader, ClassLoaderAccess)}. ++ *

      ++ * Groups are differentiated into the global group or plugin owned groups. ++ *

        ++ *
      • The global group holds all registered class loaders and merely exists to maintain backwards compatibility with ++ * spigots legacy classloader handling.
      • ++ *
      • The plugin groups only contains the classloaders that each plugin has access to and hence serves to properly ++ * separates unrelated classloaders.
      • ++ *
      ++ */ ++@ApiStatus.Internal ++public interface PaperClassLoaderStorage { ++ ++ /** ++ * Access to the shared instance of the {@link PaperClassLoaderStorageAccess}. ++ * ++ * @return the singleton instance of the {@link PaperClassLoaderStorage} used throughout the server ++ */ ++ static PaperClassLoaderStorage instance() { ++ return PaperClassLoaderStorageAccess.INSTANCE; ++ } ++ ++ /** ++ * Registers a legacy spigot {@link PluginClassLoader} into the loader storage, creating a group wrapping ++ * the single plugin class loader with transitive access to the global group. ++ * ++ * @param pluginClassLoader the legacy spigot plugin class loader to register ++ * @return the group the plugin class loader was placed into ++ */ ++ PluginClassLoaderGroup registerSpigotGroup(PluginClassLoader pluginClassLoader); ++ ++ /** ++ * Registers a paper configured plugin classloader into a new open group, with full access to the global ++ * plugin class loader group. ++ *

      ++ * This method hence allows the configured plugin class loader to access all other class loaders registered in this ++ * storage. ++ * ++ * @param classLoader the configured plugin class loader to register ++ * @return the group the plugin class loader was placed into ++ */ ++ PluginClassLoaderGroup registerOpenGroup(ConfiguredPluginClassLoader classLoader); ++ ++ /** ++ * Registers a paper configured classloader into a new, access backed group. ++ * The access backed classloader group, different from an open group, only has access to the classloaders ++ * the passed {@link ClassLoaderAccess} grants access to. ++ * ++ * @param classLoader the configured plugin class loader to register ++ * @param access the class loader access that defines what other classloaders the passed plugin class loader ++ * should be granted access to. ++ * @return the group the plugin class loader was placed into. ++ */ ++ PluginClassLoaderGroup registerAccessBackedGroup(ConfiguredPluginClassLoader classLoader, ClassLoaderAccess access); ++ ++ /** ++ * Unregisters a configured class loader from this storage. ++ * This removes the passed class loaders from any group it may have been a part of, including the global group. ++ *

      ++ * Note: this method is highly discouraged from being used, as mutation of the classloaders at runtime ++ * is not encouraged ++ * ++ * @param configuredPluginClassLoader the class loader to remove from this storage. ++ */ ++ void unregisterClassloader(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Registers a configured plugin class loader directly into the global group without adding it to ++ * any existing groups. ++ *

      ++ * Note: this method unsafely injects the plugin classloader directly into the global group, which bypasses the ++ * group structure paper's plugin API introduced. This method should hence be used with caution. ++ * ++ * @param pluginLoader the configured plugin classloader instance that should be registered directly into the global ++ * group. ++ * @return a simple boolean flag, {@code true} if the classloader was registered or {@code false} if the classloader ++ * was already part of the global group. ++ */ ++ boolean registerUnsafePlugin(ConfiguredPluginClassLoader pluginLoader); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c0e5ba6f8eba7a632180491843071b8a8558e56 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java +@@ -0,0 +1,17 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import net.kyori.adventure.util.Services; ++ ++/** ++ * The paper classloader storage access acts as the holder for the server provided implementation of the ++ * {@link PaperClassLoaderStorage} interface. ++ */ ++class PaperClassLoaderStorageAccess { ++ ++ /** ++ * The shared instance of the {@link PaperClassLoaderStorage}, supplied through the {@link java.util.ServiceLoader} ++ * by the server. ++ */ ++ static final PaperClassLoaderStorage INSTANCE = Services.service(PaperClassLoaderStorage.class).orElseThrow(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dd3bfbf8a30c9ac6a82dcbdf879bbf120d920e20 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java +@@ -0,0 +1,66 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * A plugin classloader group represents a group of classloaders that a plugins classloader may access. ++ *

      ++ * An example of this would be a classloader group that holds all direct and transitive dependencies a plugin declared, ++ * allowing a plugins classloader to access classes included in these dependencies via this group. ++ */ ++@NullMarked ++@ApiStatus.Internal ++public interface PluginClassLoaderGroup { ++ ++ /** ++ * Attempts to find/load a class from this plugin class loader group using the passed fully qualified name ++ * in any of the classloaders that are part of this group. ++ *

      ++ * The lookup order across the contained loaders is not defined on the API level and depends purely on the ++ * implementation. ++ * ++ * @param name the fully qualified name of the class to load ++ * @param resolve whether the class should be resolved if needed or not ++ * @param requester plugin classloader that is requesting the class from this loader group ++ * @return the class found at the fully qualified class name passed. If the class could not be found, {@code null} ++ * will be returned. ++ * @see ConfiguredPluginClassLoader#loadClass(String, boolean, boolean, boolean) ++ */ ++ @Nullable Class getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester); ++ ++ /** ++ * Removes a configured plugin classloader from this class loader group. ++ * If the classloader is not currently in the list, this method will simply do nothing. ++ * ++ * @param configuredPluginClassLoader the plugin classloader to remove from the group ++ */ ++ @Contract(mutates = "this") ++ void remove(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Adds the passed plugin classloader to this group, allowing this group to use it during ++ * {@link #getClassByName(String, boolean, ConfiguredPluginClassLoader)} lookups. ++ *

      ++ * This method does not query the {@link ClassLoaderAccess} (exposed via {@link #getAccess()}) to ensure ++ * if this group has access to the class loader passed. ++ * ++ * @param configuredPluginClassLoader the plugin classloader to add to this group. ++ */ ++ @Contract(mutates = "this") ++ void add(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Provides the class loader access that guards and defines the content of this classloader group. ++ * While not guaranteed contractually (see {@link #add(ConfiguredPluginClassLoader)}), the access generally is ++ * responsible for defining which {@link ConfiguredPluginClassLoader}s should be part of this group and which ones ++ * should not. ++ * ++ * @return the classloader access governing which classloaders should be part of this group and which ones should ++ * not. ++ */ ++ ClassLoaderAccess getAccess(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..338dc25d5161b7378dd17b17d6f603c92eb0a894 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java +@@ -0,0 +1,49 @@ ++package io.papermc.paper.plugin.provider.entrypoint; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A dependency context is a read-only abstraction of a type/concept that can resolve dependencies between plugins. ++ *

      ++ * This may for example be the server wide plugin manager itself, capable of validating if a dependency exists between ++ * two {@link PluginMeta} instances, however the implementation is not limited to such a concrete use-case. ++ */ ++@NullMarked ++@ApiStatus.Internal ++public interface DependencyContext { ++ ++ /** ++ * Computes if the passed {@link PluginMeta} defined the passed dependency as a transitive dependency. ++ * A transitive dependency, as implied by its name, may not have been configured directly by the passed plugin ++ * but could also simply be a dependency of a dependency. ++ *

      ++ * A simple example of this method would be ++ *

      {@code
      ++     * dependencyContext.isTransitiveDependency(pluginMetaA, pluginMetaC);
      ++     * }
      ++ * which would return {@code true} if {@code pluginMetaA} directly or indirectly depends on {@code pluginMetaC}. ++ * ++ * @param plugin the plugin meta this computation should consider the requester of the dependency status for the ++ * passed potential dependency. ++ * @param depend the potential transitive dependency of the {@code plugin} parameter. ++ * @return a simple boolean flag indicating if {@code plugin} considers {@code depend} as a transitive dependency. ++ */ ++ boolean isTransitiveDependency(PluginMeta plugin, PluginMeta depend); ++ ++ /** ++ * Computes if this dependency context is aware of a dependency that provides/matches the passed identifier. ++ *

      ++ * A dependency in this methods context is any dependable artefact. It does not matter if anything actually depends ++ * on said artefact, its mere existence as a potential dependency is enough for this method to consider it a ++ * dependency. If this dependency context is hence aware of an artefact with the matching identifier, this ++ * method returns {@code true}. ++ * ++ * @param pluginIdentifier the unique identifier of the dependency with which to probe this dependency context. ++ * @return a plain boolean flag indicating if this dependency context is aware of a potential dependency with the ++ * passed identifier. ++ */ ++ boolean hasDependency(String pluginIdentifier); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..48a67c1b6070292dbf4ea3081f89b530207f9f6d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.plugin.provider.util; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * An internal utility type that holds logic for loading a provider-like type from a classloaders. ++ * Provides, at least in the context of this utility, define themselves as implementations of a specific parent ++ * interface/type, e.g. {@link org.bukkit.plugin.java.JavaPlugin} and implement a no-args constructor. ++ */ ++@NullMarked ++@ApiStatus.Internal ++public final class ProviderUtil { ++ ++ /** ++ * Loads the class found at the provided fully qualified class name from the passed classloader, creates a new ++ * instance of it using the no-args constructor, that should exist as per this method contract, and casts it to the ++ * provided parent type. ++ * ++ * @param clazz the fully qualified name of the class to load ++ * @param classType the parent type that the created object found at the {@code clazz} name should be cast to ++ * @param loader the loader from which the class should be loaded ++ * @param the generic type of the parent class the created object will be cast to ++ * @return the object instantiated from the class found at the provided FQN, cast to the parent type ++ */ ++ public static T loadClass(final String clazz, final Class classType, final ClassLoader loader) { ++ return loadClass(clazz, classType, loader, null); ++ } ++ ++ /** ++ * Loads the class found at the provided fully qualified class name from the passed classloader, creates a new ++ * instance of it using the no-args constructor, that should exist as per this method contract, and casts it to the ++ * provided parent type. ++ * ++ * @param clazz the fully qualified name of the class to load ++ * @param classType the parent type that the created object found at the {@code clazz} name should be cast to ++ * @param loader the loader from which the class should be loaded ++ * @param onError a runnable that is executed before any unknown exception is raised through a sneaky throw. ++ * @param the generic type of the parent class the created object will be cast to ++ * @return the object instantiated from the class found at the provided fully qualified class name, cast to the ++ * parent type ++ */ ++ public static T loadClass(final String clazz, final Class classType, final ClassLoader loader, final @Nullable Runnable onError) { ++ try { ++ final T clazzInstance; ++ ++ try { ++ final Class jarClass = Class.forName(clazz, true, loader); ++ ++ final Class pluginClass; ++ try { ++ pluginClass = jarClass.asSubclass(classType); ++ } catch (final ClassCastException ex) { ++ throw new ClassCastException("class '%s' does not extend '%s'".formatted(clazz, classType)); ++ } ++ ++ clazzInstance = pluginClass.getDeclaredConstructor().newInstance(); ++ } catch (final IllegalAccessException exception) { ++ throw new RuntimeException("No public constructor"); ++ } catch (final InstantiationException exception) { ++ throw new RuntimeException("Abnormal class instantiation", exception); ++ } ++ ++ return clazzInstance; ++ } catch (final Throwable e) { ++ if (onError != null) { ++ onError.run(); ++ } ++ SneakyThrow.sneaky(e); ++ } ++ ++ throw new AssertionError(); // Shouldn't happen ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 89d5def8c1dcdab0a9e2d1809badcbbd112c3d9c..aec092e019667d53faf3e7352799772804d5d260 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -146,4 +146,14 @@ public interface UnsafeValues { + + @ApiStatus.Internal + Biome getCustomBiome(); ++ ++ // Paper start ++ @Deprecated(forRemoval = true) ++ boolean isSupportedApiVersion(String apiVersion); ++ ++ @Deprecated(forRemoval = true) ++ static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { ++ return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/PluginCommand.java b/src/main/java/org/bukkit/command/PluginCommand.java +index 1dbbc244309043b18c1d71707c4fb066c0d0e02d..551c5af6a7bfa2268cbc63be8e70d129bccaa912 100644 +--- a/src/main/java/org/bukkit/command/PluginCommand.java ++++ b/src/main/java/org/bukkit/command/PluginCommand.java +@@ -14,7 +14,7 @@ public final class PluginCommand extends Command implements PluginIdentifiableCo + private CommandExecutor executor; + private TabCompleter completer; + +- protected PluginCommand(@NotNull String name, @NotNull Plugin owner) { ++ PluginCommand(@NotNull String name, @NotNull Plugin owner) { + super(name); + this.executor = owner; + this.owningPlugin = owner; +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index fd5a7a55484deb3fdcced7ebd1f4f6c14d5b4f4f..9207ae900cb4cc8ce41dd4e63d7ad8b35b0ac048 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -35,7 +35,7 @@ public class SimpleCommandMap implements CommandMap { + private void setDefaultCommands() { + register("bukkit", new VersionCommand("version")); + register("bukkit", new ReloadCommand("reload")); +- register("bukkit", new PluginsCommand("plugins")); ++ //register("bukkit", new PluginsCommand("plugins")); // Paper + register("bukkit", new TimingsCommand("timings")); + } + +diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +index bcb576a4271b1ec7b1cfe6f83cf161b7d89ed2e5..4d849e1283fdf6b0872a0f2183964cc93748c116 100644 +--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +@@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender; + import org.bukkit.plugin.Plugin; + import org.jetbrains.annotations.NotNull; + ++@Deprecated(forRemoval = true) // Paper + public class PluginsCommand extends BukkitCommand { + public PluginsCommand(@NotNull String name) { + super(name); +diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java +index b37938745f916b5f0111b07b1a1c97527f026e9d..8c76716249e44ed8bf6be94c1f5c7b6d9bb35be2 100644 +--- a/src/main/java/org/bukkit/plugin/Plugin.java ++++ b/src/main/java/org/bukkit/plugin/Plugin.java +@@ -30,10 +30,21 @@ public interface Plugin extends TabExecutor { + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file ++ * @deprecated May be inaccurate due to different plugin implementations. ++ * @see Plugin#getPluginMeta() + */ ++ @Deprecated // Paper + @NotNull + public PluginDescriptionFile getDescription(); + ++ // Paper start ++ /** ++ * Gets the plugin meta for this plugin. ++ * @return configuration ++ */ ++ @NotNull ++ io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta(); ++ // Paper end + /** + * Gets a {@link FileConfiguration} for this plugin, read through + * "config.yml" +@@ -94,6 +105,7 @@ public interface Plugin extends TabExecutor { + * + * @return PluginLoader that controls this plugin + */ ++ @Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + @NotNull + public PluginLoader getPluginLoader(); + +diff --git a/src/main/java/org/bukkit/plugin/PluginBase.java b/src/main/java/org/bukkit/plugin/PluginBase.java +index 94f8ceb965cecb5669a84a0ec61c0f706c2a2673..e773db6da357ad210eb24d4c389af2dc84ce450a 100644 +--- a/src/main/java/org/bukkit/plugin/PluginBase.java ++++ b/src/main/java/org/bukkit/plugin/PluginBase.java +@@ -31,6 +31,6 @@ public abstract class PluginBase implements Plugin { + @Override + @NotNull + public final String getName() { +- return getDescription().getName(); ++ return getPluginMeta().getName(); // Paper + } + } +diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +index 4d444ed5bcfcd5bc3fd52fd5f28b8f8e0e006d1c..d24dc9dfe169089f26d1844d73b98b3d78fa9452 100644 +--- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java ++++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +@@ -199,7 +199,7 @@ import org.yaml.snakeyaml.representer.Representer; + * inferno.burningdeaths: true + * + */ +-public final class PluginDescriptionFile { ++public final class PluginDescriptionFile implements io.papermc.paper.plugin.configuration.PluginMeta { // Paper + private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9 _.-]+$"); + private static final ThreadLocal YAML = new ThreadLocal() { + @Override +@@ -260,6 +260,70 @@ public final class PluginDescriptionFile { + private Set awareness = ImmutableSet.of(); + private String apiVersion = null; + private List libraries = ImmutableList.of(); ++ // Paper start - oh my goddddd ++ /** ++ * Don't use this. ++ */ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PluginDescriptionFile(String rawName, String name, List provides, String main, String classLoaderOf, List depend, List softDepend, List loadBefore, String version, Map> commands, String description, List authors, List contributors, String website, String prefix, PluginLoadOrder order, List permissions, PermissionDefault defaultPerm, Set awareness, String apiVersion, List libraries) { ++ this.rawName = rawName; ++ this.name = name; ++ this.provides = provides; ++ this.main = main; ++ this.classLoaderOf = classLoaderOf; ++ this.depend = depend; ++ this.softDepend = softDepend; ++ this.loadBefore = loadBefore; ++ this.version = version; ++ this.commands = commands; ++ this.description = description; ++ this.authors = authors; ++ this.contributors = contributors; ++ this.website = website; ++ this.prefix = prefix; ++ this.order = order; ++ this.permissions = permissions; ++ this.defaultPerm = defaultPerm; ++ this.awareness = awareness; ++ this.apiVersion = apiVersion; ++ this.libraries = libraries; ++ } ++ ++ @Override ++ public @NotNull String getMainClass() { ++ return this.main; ++ } ++ ++ @Override ++ public @NotNull PluginLoadOrder getLoadOrder() { ++ return this.order; ++ } ++ ++ @Override ++ public @Nullable String getLoggerPrefix() { ++ return this.prefix; ++ } ++ ++ @Override ++ public @NotNull List getPluginDependencies() { ++ return this.depend; ++ } ++ ++ @Override ++ public @NotNull List getPluginSoftDependencies() { ++ return this.softDepend; ++ } ++ ++ @Override ++ public @NotNull List getLoadBeforePlugins() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getProvidedPlugins() { ++ return this.provides; ++ } ++ // Paper end + + public PluginDescriptionFile(@NotNull final InputStream stream) throws InvalidDescriptionException { + loadMap(asMap(YAML.get().load(stream))); +diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java +index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..cb530369e667c426c842da356c31304bb5c3ecfa 100644 +--- a/src/main/java/org/bukkit/plugin/PluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/PluginLoader.java +@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; + * Represents a plugin loader, which handles direct access to specific types + * of plugins + */ ++@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + public interface PluginLoader { + + /** +diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java +index ae3e68562c29992fab627428db3ff0006d8216f9..47153dee66782a00b980ecf15e8774ab6f3d887d 100644 +--- a/src/main/java/org/bukkit/plugin/PluginManager.java ++++ b/src/main/java/org/bukkit/plugin/PluginManager.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Handles all plugin management from the Server + */ +-public interface PluginManager { ++public interface PluginManager extends io.papermc.paper.plugin.PermissionManager { // Paper + + /** + * Registers the specified plugin loader +@@ -23,6 +23,7 @@ public interface PluginManager { + * @throws IllegalArgumentException Thrown when the given Class is not a + * valid PluginLoader + */ ++ @Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + public void registerInterface(@NotNull Class loader) throws IllegalArgumentException; + + /** +@@ -312,4 +313,17 @@ public interface PluginManager { + * @return True if event timings are to be used + */ + public boolean useTimings(); ++ ++ // Paper start ++ @org.jetbrains.annotations.ApiStatus.Internal ++ boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig); ++ ++ /** ++ * Sets the permission manager to be used for this server. ++ * ++ * @param permissionManager permission manager ++ */ ++ @org.jetbrains.annotations.ApiStatus.Experimental ++ void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index ccf2aafca03c96ad8d28571eb7172989f75c29db..d6f3c8da8bae1f70e0f9bee3e688a04801a3b546 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -44,6 +44,8 @@ import org.jetbrains.annotations.Nullable; + /** + * Handles all plugin management from the Server + */ ++@Deprecated(forRemoval = true) // Paper - This implementation may be replaced in a future version of Paper. ++// Plugins may still reflect into this class to modify permission logic for the time being. + public final class SimplePluginManager implements PluginManager { + private final Server server; + private final Map fileAssociations = new HashMap(); +@@ -52,10 +54,13 @@ public final class SimplePluginManager implements PluginManager { + private MutableGraph dependencyGraph = GraphBuilder.directed().build(); + private File updateDirectory; + private final SimpleCommandMap commandMap; +- private final Map permissions = new HashMap(); +- private final Map> defaultPerms = new LinkedHashMap>(); +- private final Map> permSubs = new HashMap>(); +- private final Map> defSubs = new HashMap>(); ++ // Paper start ++ public final Map permissions = new HashMap(); ++ public final Map> defaultPerms = new LinkedHashMap>(); ++ public final Map> permSubs = new HashMap>(); ++ public final Map> defSubs = new HashMap>(); ++ public PluginManager paperPluginManager; ++ // Paper end + private boolean useTimings = false; + + public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) { +@@ -112,6 +117,11 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Plugin[] loadPlugins(@NotNull File directory) { ++ if (true) { ++ List pluginList = new ArrayList<>(); ++ java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory)); ++ return pluginList.toArray(new Plugin[0]); ++ } + Preconditions.checkArgument(directory != null, "Directory cannot be null"); + Preconditions.checkArgument(directory.isDirectory(), "Directory must be a directory"); + +@@ -130,6 +140,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @NotNull + public Plugin[] loadPlugins(@NotNull File[] files) { ++ // TODO Replace with Paper plugin loader + Preconditions.checkArgument(files != null, "File list cannot be null"); + + List result = new ArrayList(); +@@ -390,6 +401,15 @@ public final class SimplePluginManager implements PluginManager { + @Nullable + public synchronized Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, UnknownDependencyException { + Preconditions.checkArgument(file != null, "File cannot be null"); ++ // Paper start ++ if (true) { ++ try { ++ return this.paperPluginManager.loadPlugin(file); ++ } catch (org.bukkit.plugin.InvalidDescriptionException ignored) { ++ return null; ++ } ++ } ++ // Paper end + + checkUpdate(file); + +@@ -440,12 +460,14 @@ public final class SimplePluginManager implements PluginManager { + @Override + @Nullable + public synchronized Plugin getPlugin(@NotNull String name) { ++ if (true) {return this.paperPluginManager.getPlugin(name);} // Paper + return lookupNames.get(name.replace(' ', '_')); + } + + @Override + @NotNull + public synchronized Plugin[] getPlugins() { ++ if (true) {return this.paperPluginManager.getPlugins();} // Paper + return plugins.toArray(new Plugin[plugins.size()]); + } + +@@ -459,6 +481,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public boolean isPluginEnabled(@NotNull String name) { ++ if (true) {return this.paperPluginManager.isPluginEnabled(name);} // Paper + Plugin plugin = getPlugin(name); + + return isPluginEnabled(plugin); +@@ -472,6 +495,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public boolean isPluginEnabled(@Nullable Plugin plugin) { ++ if (true) {return this.paperPluginManager.isPluginEnabled(plugin);} // Paper + if ((plugin != null) && (plugins.contains(plugin))) { + return plugin.isEnabled(); + } else { +@@ -481,6 +505,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void enablePlugin(@NotNull final Plugin plugin) { ++ if (true) {this.paperPluginManager.enablePlugin(plugin); return;} // Paper + if (!plugin.isEnabled()) { + List pluginCommands = PluginCommandYamlParser.parse(plugin); + +@@ -500,6 +525,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void disablePlugins() { ++ if (true) {this.paperPluginManager.disablePlugins(); return;} // Paper + Plugin[] plugins = getPlugins(); + for (int i = plugins.length - 1; i >= 0; i--) { + disablePlugin(plugins[i]); +@@ -508,6 +534,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void disablePlugin(@NotNull final Plugin plugin) { ++ if (true) {this.paperPluginManager.disablePlugin(plugin); return;} // Paper + if (plugin.isEnabled()) { + try { + plugin.getPluginLoader().disablePlugin(plugin); +@@ -552,6 +579,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void clearPlugins() { ++ if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper + synchronized (this) { + disablePlugins(); + plugins.clear(); +@@ -572,6 +600,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public void callEvent(@NotNull Event event) { ++ if (true) {this.paperPluginManager.callEvent(event); return;} // Paper + if (event.isAsynchronous()) { + if (Thread.holdsLock(this)) { + throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); +@@ -620,6 +649,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void registerEvents(@NotNull Listener listener, @NotNull Plugin plugin) { ++ if (true) {this.paperPluginManager.registerEvents(listener, plugin); return;} // Paper + if (!plugin.isEnabled()) { + throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled"); + } +@@ -653,6 +683,7 @@ public final class SimplePluginManager implements PluginManager { + Preconditions.checkArgument(priority != null, "Priority cannot be null"); + Preconditions.checkArgument(executor != null, "Executor cannot be null"); + Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); ++ if (true) {this.paperPluginManager.registerEvent(event, listener, priority, executor, plugin, ignoreCancelled); return;} // Paper + + if (!plugin.isEnabled()) { + throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); +@@ -700,16 +731,19 @@ public final class SimplePluginManager implements PluginManager { + @Override + @Nullable + public Permission getPermission(@NotNull String name) { ++ if (true) {return this.paperPluginManager.getPermission(name);} // Paper + return permissions.get(name.toLowerCase(Locale.ROOT)); + } + + @Override + public void addPermission(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper + addPermission(perm, true); + } + + @Deprecated(since = "1.12") + public void addPermission(@NotNull Permission perm, boolean dirty) { ++ if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper - This just has a performance implication, use the better api to avoid this. + String name = perm.getName().toLowerCase(Locale.ROOT); + + if (permissions.containsKey(name)) { +@@ -723,21 +757,25 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getDefaultPermissions(boolean op) { ++ if (true) {return this.paperPluginManager.getDefaultPermissions(op);} // Paper + return ImmutableSet.copyOf(defaultPerms.get(op)); + } + + @Override + public void removePermission(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.removePermission(perm); return;} // Paper + removePermission(perm.getName()); + } + + @Override + public void removePermission(@NotNull String name) { ++ if (true) {this.paperPluginManager.removePermission(name); return;} // Paper + permissions.remove(name.toLowerCase(Locale.ROOT)); + } + + @Override + public void recalculatePermissionDefaults(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.recalculatePermissionDefaults(perm); return;} // Paper + if (perm != null && permissions.containsKey(perm.getName().toLowerCase(Locale.ROOT))) { + defaultPerms.get(true).remove(perm); + defaultPerms.get(false).remove(perm); +@@ -777,6 +815,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.subscribeToPermission(permission, permissible); return;} // Paper + String name = permission.toLowerCase(Locale.ROOT); + Map map = permSubs.get(name); + +@@ -790,6 +829,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.unsubscribeFromPermission(permission, permissible); return;} // Paper + String name = permission.toLowerCase(Locale.ROOT); + Map map = permSubs.get(name); + +@@ -805,6 +845,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getPermissionSubscriptions(@NotNull String permission) { ++ if (true) {return this.paperPluginManager.getPermissionSubscriptions(permission);} // Paper + String name = permission.toLowerCase(Locale.ROOT); + Map map = permSubs.get(name); + +@@ -817,6 +858,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.subscribeToDefaultPerms(op, permissible); return;} // Paper + Map map = defSubs.get(op); + + if (map == null) { +@@ -829,6 +871,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.unsubscribeFromDefaultPerms(op, permissible); return;} // Paper + Map map = defSubs.get(op); + + if (map != null) { +@@ -843,6 +886,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getDefaultPermSubscriptions(boolean op) { ++ if (true) {return this.paperPluginManager.getDefaultPermSubscriptions(op);} // Paper + Map map = defSubs.get(op); + + if (map == null) { +@@ -855,6 +899,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getPermissions() { ++ if (true) {return this.paperPluginManager.getPermissions();} // Paper + return new HashSet(permissions.values()); + } + +@@ -878,6 +923,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public boolean useTimings() { ++ if (true) {return this.paperPluginManager.useTimings();} // Paper + return useTimings; + } + +@@ -889,4 +935,28 @@ public final class SimplePluginManager implements PluginManager { + public void useTimings(boolean use) { + useTimings = use; + } ++ ++ // Paper start ++ public void clearPermissions() { ++ if (true) {this.paperPluginManager.clearPermissions(); return;} // Paper ++ permissions.clear(); ++ defaultPerms.get(true).clear(); ++ defaultPerms.get(false).clear(); ++ } ++ ++ @Override ++ public boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig) { ++ return this.paperPluginManager.isTransitiveDependency(pluginMeta, dependencyConfig); ++ } ++ ++ @Override ++ public void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager) { ++ this.paperPluginManager.overridePermissionManager(plugin, permissionManager); ++ } ++ ++ @Override ++ public void addPermissions(@NotNull List perm) { ++ this.paperPluginManager.addPermissions(perm); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +index a80251eff75430863b37db1c131e22593f3fcd5e..310c4041963a3f1e0a26e39a6da12a9bfdb51edc 100644 +--- a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java ++++ b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +@@ -43,4 +43,16 @@ public class UnknownDependencyException extends RuntimeException { + public UnknownDependencyException() { + + } ++ // Paper start ++ /** ++ * Create a new {@link UnknownDependencyException} with a message informing ++ * about which dependencies are missing for what plugin. ++ * ++ * @param missingDependencies missing dependencies ++ * @param pluginName plugin which is missing said dependencies ++ */ ++ public UnknownDependencyException(final @org.jetbrains.annotations.NotNull java.util.Collection missingDependencies, final @org.jetbrains.annotations.NotNull String pluginName) { ++ this("Unknown/missing dependency plugins: [" + String.join(", ", missingDependencies) + "]. Please download and install these plugins to run '" + pluginName + "'."); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index 7fca39df009308adad55a6e9dc10a4a0dead86f2..2a14522c484febcd880d00197df4359a0020dddd 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -41,6 +41,7 @@ public abstract class JavaPlugin extends PluginBase { + private Server server = null; + private File file = null; + private PluginDescriptionFile description = null; ++ private io.papermc.paper.plugin.configuration.PluginMeta pluginMeta = null; // Paper + private File dataFolder = null; + private ClassLoader classLoader = null; + private boolean naggable = true; +@@ -49,13 +50,16 @@ public abstract class JavaPlugin extends PluginBase { + private PluginLogger logger = null; + + public JavaPlugin() { +- final ClassLoader classLoader = this.getClass().getClassLoader(); +- if (!(classLoader instanceof PluginClassLoader)) { +- throw new IllegalStateException("JavaPlugin requires " + PluginClassLoader.class.getName()); ++ // Paper start ++ if (this.getClass().getClassLoader() instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ configuredPluginClassLoader.init(this); ++ } else { ++ throw new IllegalStateException("JavaPlugin requires to be created by a valid classloader."); + } +- ((PluginClassLoader) classLoader).initialize(this); ++ // Paper end + } + ++ @Deprecated(forRemoval = true) // Paper + protected JavaPlugin(@NotNull final JavaPluginLoader loader, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file) { + final ClassLoader classLoader = this.getClass().getClassLoader(); + if (classLoader instanceof PluginClassLoader) { +@@ -80,9 +84,12 @@ public abstract class JavaPlugin extends PluginBase { + * Gets the associated PluginLoader responsible for this plugin + * + * @return PluginLoader that controls this plugin ++ * @deprecated Plugin loading now occurs at a point which makes it impossible to expose this ++ * behavior. This instance will only throw unsupported operation exceptions. + */ + @NotNull + @Override ++ @Deprecated(forRemoval = true) // Paper + public final PluginLoader getPluginLoader() { + return loader; + } +@@ -123,13 +130,20 @@ public abstract class JavaPlugin extends PluginBase { + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file ++ * @deprecated No longer applicable to all types of plugins + */ + @NotNull + @Override ++ @Deprecated + public final PluginDescriptionFile getDescription() { + return description; + } + ++ @NotNull ++ public final io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() { ++ return this.pluginMeta; ++ } ++ + @NotNull + @Override + public FileConfiguration getConfig() { +@@ -259,7 +273,8 @@ public abstract class JavaPlugin extends PluginBase { + * + * @param enabled true if enabled, otherwise false + */ +- protected final void setEnabled(final boolean enabled) { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public final void setEnabled(final boolean enabled) { // Paper + if (isEnabled != enabled) { + isEnabled = enabled; + +@@ -271,9 +286,18 @@ public abstract class JavaPlugin extends PluginBase { + } + } + +- +- final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) { +- this.loader = loader; ++ // Paper start ++ private static class DummyPluginLoaderImplHolder { ++ private static final PluginLoader INSTANCE = net.kyori.adventure.util.Services.service(PluginLoader.class) ++ .orElseThrow(); ++ } ++ public final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) { ++ init(server, description, dataFolder, file, classLoader, description); ++ this.pluginMeta = description; ++ } ++ public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration) { ++ // Paper end ++ this.loader = DummyPluginLoaderImplHolder.INSTANCE; // Paper + this.server = server; + this.file = file; + this.description = description; +@@ -281,6 +305,7 @@ public abstract class JavaPlugin extends PluginBase { + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); + this.logger = new PluginLogger(this); ++ this.pluginMeta = configuration; // Paper + } + + /** +@@ -397,10 +422,10 @@ public abstract class JavaPlugin extends PluginBase { + throw new IllegalArgumentException(clazz + " does not extend " + JavaPlugin.class); + } + final ClassLoader cl = clazz.getClassLoader(); +- if (!(cl instanceof PluginClassLoader)) { +- throw new IllegalArgumentException(clazz + " is not initialized by " + PluginClassLoader.class); ++ if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper ++ throw new IllegalArgumentException(clazz + " is not initialized by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper + } +- JavaPlugin plugin = ((PluginClassLoader) cl).plugin; ++ JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper + if (plugin == null) { + throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer"); + } +@@ -423,10 +448,10 @@ public abstract class JavaPlugin extends PluginBase { + public static JavaPlugin getProvidingPlugin(@NotNull Class clazz) { + Preconditions.checkArgument(clazz != null, "Null class cannot have a plugin"); + final ClassLoader cl = clazz.getClassLoader(); +- if (!(cl instanceof PluginClassLoader)) { +- throw new IllegalArgumentException(clazz + " is not provided by " + PluginClassLoader.class); ++ if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper ++ throw new IllegalArgumentException(clazz + " is not provided by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper + } +- JavaPlugin plugin = ((PluginClassLoader) cl).plugin; ++ JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper + if (plugin == null) { + throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer"); + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 29a8efdf3a8a68903a37924bbd5a24f5213aff6e..70ac93d420d0a8528428a3d038a2ef6a86d2fddd 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -49,6 +49,7 @@ import org.yaml.snakeyaml.error.YAMLException; + /** + * Represents a Java plugin loader, allowing plugins in the form of .jar + */ ++@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future. This implementation will be moved. + public final class JavaPluginLoader implements PluginLoader { + final Server server; + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; +@@ -79,6 +80,7 @@ public final class JavaPluginLoader implements PluginLoader { + @Override + @NotNull + public Plugin loadPlugin(@NotNull final File file) throws InvalidPluginException { ++ if (true) throw new UnsupportedOperationException(); // Paper + Preconditions.checkArgument(file != null, "File cannot be null"); + + if (!file.exists()) { +@@ -142,7 +144,7 @@ public final class JavaPluginLoader implements PluginLoader { + + final PluginClassLoader loader; + try { +- loader = new PluginClassLoader(this, getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null); ++ loader = new PluginClassLoader(getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null, null, null); // Paper + } catch (InvalidPluginException ex) { + throw ex; + } catch (Throwable ex) { +diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +index 160f8c348271154c672adf936b358ffeb3b63e69..f4d655a158410039305ac68cebe0d79000f73df8 100644 +--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +@@ -36,7 +36,10 @@ import org.eclipse.aether.transport.http.HttpTransporterFactory; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-class LibraryLoader ++// Paper start ++@org.jetbrains.annotations.ApiStatus.Internal ++public class LibraryLoader ++// Paper end + { + + private final Logger logger; +@@ -55,6 +58,7 @@ class LibraryLoader + this.repository = locator.getService( RepositorySystem.class ); + this.session = MavenRepositorySystemUtils.newSession(); + ++ session.setSystemProperties(System.getProperties()); // Paper - paper plugins, backport system properties fix for transitive dependency parsing, see #10116 + session.setChecksumPolicy( RepositoryPolicy.CHECKSUM_POLICY_FAIL ); + session.setLocalRepositoryManager( repository.newLocalRepositoryManager( session, new LocalRepository( "libraries" ) ) ); + session.setTransferListener( new AbstractTransferListener() +@@ -84,7 +88,7 @@ class LibraryLoader + } + logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[] + { +- desc.getName(), desc.getLibraries().size() ++ java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), desc.getLibraries().size() // Paper - use configured log prefix + } ); + + List dependencies = new ArrayList<>(); +@@ -122,7 +126,7 @@ class LibraryLoader + jarFiles.add( url ); + logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[] + { +- desc.getName(), file ++ java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), file // Paper - use configured log prefix + } ); + } + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 64a294aeb6fb548794708b38c3707f9dd882b2ff..58d20eff7e0da2d7fcb1609d55e4284715355634 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -31,7 +31,8 @@ import org.jetbrains.annotations.Nullable; + /** + * A ClassLoader for plugins, to allow shared classes across multiple plugins + */ +-final class PluginClassLoader extends URLClassLoader { ++@org.jetbrains.annotations.ApiStatus.Internal // Paper ++public final class PluginClassLoader extends URLClassLoader implements io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader { // Paper + private final JavaPluginLoader loader; + private final Map> classes = new ConcurrentHashMap>(); + private final PluginDescriptionFile description; +@@ -45,24 +46,32 @@ final class PluginClassLoader extends URLClassLoader { + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private java.util.logging.Logger logger; // Paper - add field ++ private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper ++ public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper + + static { + ClassLoader.registerAsParallelCapable(); + } + +- PluginClassLoader(@NotNull final JavaPluginLoader loader, @Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) throws IOException, InvalidPluginException, MalformedURLException { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader, JarFile jarFile, io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext) throws IOException, InvalidPluginException, MalformedURLException { // Paper - use JarFile provided by SpigotPluginProvider + super(new URL[] {file.toURI().toURL()}, parent); +- Preconditions.checkArgument(loader != null, "Loader cannot be null"); ++ this.loader = null; // Paper - pass null into loader field + +- this.loader = loader; + this.description = description; + this.dataFolder = dataFolder; + this.file = file; +- this.jar = new JarFile(file); ++ this.jar = jarFile; // Paper - use JarFile provided by SpigotPluginProvider + this.manifest = jar.getManifest(); + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; + ++ // Paper start ++ this.dependencyContext = dependencyContext; ++ this.classLoaderGroup = io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage.instance().registerSpigotGroup(this); ++ // Paper end ++ + Class jarClass; + try { + jarClass = Class.forName(description.getMain(), true, this); +@@ -107,6 +116,27 @@ final class PluginClassLoader extends URLClassLoader { + return findResources(name); + } + ++ // Paper start ++ @Override ++ public Class loadClass(@NotNull String name, boolean resolve, boolean checkGlobal, boolean checkLibraries) throws ClassNotFoundException { ++ return this.loadClass0(name, resolve, checkGlobal, checkLibraries); ++ } ++ @Override ++ public io.papermc.paper.plugin.configuration.PluginMeta getConfiguration() { ++ return this.description; ++ } ++ ++ @Override ++ public void init(JavaPlugin plugin) { ++ this.initialize(plugin); ++ } ++ ++ @Override ++ public JavaPlugin getPlugin() { ++ return this.plugin; ++ } ++ // Paper end ++ + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + return loadClass0(name, resolve, true, true); +@@ -132,26 +162,11 @@ final class PluginClassLoader extends URLClassLoader { + + if (checkGlobal) { + // This ignores the libraries of other plugins, unless they are transitive dependencies. +- Class result = loader.getClassByName(name, resolve, description); ++ Class result = this.classLoaderGroup.getClassByName(name, resolve, this); // Paper + + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. +- if (result.getClassLoader() instanceof PluginClassLoader) { +- PluginDescriptionFile provider = ((PluginClassLoader) result.getClassLoader()).description; +- +- if (provider != description +- && !seenIllegalAccess.contains(provider.getName()) +- && !((SimplePluginManager) loader.server.getPluginManager()).isTransitiveDepend(description, provider)) { +- +- seenIllegalAccess.add(provider.getName()); +- if (plugin != null) { +- plugin.getLogger().log(Level.WARNING, "Loaded class {0} from {1} which is not a depend or softdepend of this plugin.", new Object[]{name, provider.getFullName()}); +- } else { +- // In case the bad access occurs on construction +- loader.server.getLogger().log(Level.WARNING, "[{0}] Loaded class {1} from {2} which is not a depend or softdepend of this plugin.", new Object[]{description.getName(), name, provider.getFullName()}); +- } +- } +- } ++ // Paper - Totally delete the illegal access logic, we are never going to enforce it anyways here. + + return result; + } +@@ -180,7 +195,7 @@ final class PluginClassLoader extends URLClassLoader { + throw new ClassNotFoundException(name, ex); + } + +- classBytes = loader.server.getUnsafe().processClass(description, path, classBytes); ++ classBytes = org.bukkit.Bukkit.getServer().getUnsafe().processClass(description, path, classBytes); // Paper + + int dot = name.lastIndexOf('.'); + if (dot != -1) { +@@ -210,8 +225,8 @@ final class PluginClassLoader extends URLClassLoader { + result = super.findClass(name); + } + +- loader.setClass(name, result); + classes.put(name, result); ++ this.setClass(name, result); // Paper + } + + return result; +@@ -220,6 +235,12 @@ final class PluginClassLoader extends URLClassLoader { + @Override + public void close() throws IOException { + try { ++ // Paper start ++ Collection> classes = getClasses(); ++ for (Class clazz : classes) { ++ removeClass(clazz); ++ } ++ // Paper end + super.close(); + } finally { + jar.close(); +@@ -231,7 +252,7 @@ final class PluginClassLoader extends URLClassLoader { + return classes.values(); + } + +- synchronized void initialize(@NotNull JavaPlugin javaPlugin) { ++ public synchronized void initialize(@NotNull JavaPlugin javaPlugin) { // Paper + Preconditions.checkArgument(javaPlugin != null, "Initializing plugin cannot be null"); + Preconditions.checkArgument(javaPlugin.getClass().getClassLoader() == this, "Cannot initialize plugin outside of this class loader"); + if (this.plugin != null || this.pluginInit != null) { +@@ -241,6 +262,38 @@ final class PluginClassLoader extends URLClassLoader { + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + +- javaPlugin.init(loader, loader.server, description, dataFolder, file, this); ++ javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public String toString() { ++ JavaPlugin currPlugin = plugin != null ? plugin : pluginInit; ++ return "PluginClassLoader{" + ++ "plugin=" + currPlugin + ++ ", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) + ++ ", url=" + file + ++ '}'; ++ } ++ ++ void setClass(@NotNull final String name, @NotNull final Class clazz) { ++ if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) { ++ Class serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class); ++ org.bukkit.configuration.serialization.ConfigurationSerialization.registerClass(serializable); ++ } ++ } ++ ++ private void removeClass(@NotNull Class clazz) { ++ if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) { ++ Class serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class); ++ org.bukkit.configuration.serialization.ConfigurationSerialization.unregisterClass(serializable); ++ } + } ++ ++ @Override ++ public @Nullable io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup getGroup() { ++ return this.classLoaderGroup; ++ } ++ ++ // Paper end + } +diff --git a/src/test/java/org/bukkit/event/SyntheticEventTest.java b/src/test/java/org/bukkit/event/SyntheticEventTest.java +deleted file mode 100644 +index 40a086f2883c4419d2bf0bd44285f7c55562ba3e..0000000000000000000000000000000000000000 +--- a/src/test/java/org/bukkit/event/SyntheticEventTest.java ++++ /dev/null +@@ -1,49 +0,0 @@ +-package org.bukkit.event; +- +-import static org.junit.jupiter.api.Assertions.*; +-import org.bukkit.Bukkit; +-import org.bukkit.plugin.PluginLoader; +-import org.bukkit.plugin.SimplePluginManager; +-import org.bukkit.plugin.TestPlugin; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.support.AbstractTestingBase; +-import org.junit.jupiter.api.Test; +- +-public class SyntheticEventTest extends AbstractTestingBase { +- @SuppressWarnings("deprecation") +- @Test +- public void test() { +- final JavaPluginLoader loader = new JavaPluginLoader(Bukkit.getServer()); +- TestPlugin plugin = new TestPlugin(getClass().getName()) { +- @Override +- public PluginLoader getPluginLoader() { +- return loader; +- } +- }; +- SimplePluginManager pluginManager = new SimplePluginManager(Bukkit.getServer(), null); +- +- TestEvent event = new TestEvent(false); +- Impl impl = new Impl(); +- +- pluginManager.registerEvents(impl, plugin); +- pluginManager.callEvent(event); +- +- assertEquals(1, impl.callCount); +- } +- +- public abstract static class Base implements Listener { +- int callCount = 0; +- +- public void accept(E evt) { +- callCount++; +- } +- } +- +- public static class Impl extends Base { +- @Override +- @EventHandler +- public void accept(TestEvent evt) { +- super.accept(evt); +- } +- } +-} +diff --git a/src/test/java/org/bukkit/plugin/PluginManagerTest.java b/src/test/java/org/bukkit/plugin/PluginManagerTest.java +deleted file mode 100644 +index 03b08e47e91e8b56c1992fcd749a62eb9e7d4d68..0000000000000000000000000000000000000000 +--- a/src/test/java/org/bukkit/plugin/PluginManagerTest.java ++++ /dev/null +@@ -1,185 +0,0 @@ +-package org.bukkit.plugin; +- +-import static org.bukkit.support.MatcherAssert.*; +-import static org.hamcrest.Matchers.*; +-import org.bukkit.Bukkit; +-import org.bukkit.event.Event; +-import org.bukkit.event.TestEvent; +-import org.bukkit.permissions.Permission; +-import org.bukkit.support.AbstractTestingBase; +-import org.junit.jupiter.api.AfterEach; +-import org.junit.jupiter.api.Test; +- +-public class PluginManagerTest extends AbstractTestingBase { +- private class MutableObject { +- volatile Object value = null; +- } +- +- private static final PluginManager pm = Bukkit.getServer().getPluginManager(); +- +- private final MutableObject store = new MutableObject(); +- +- @Test +- public void testAsyncSameThread() { +- final Event event = new TestEvent(true); +- try { +- pm.callEvent(event); +- } catch (IllegalStateException ex) { +- assertThat(event.getEventName() + " cannot be triggered asynchronously from primary server thread.", is(ex.getMessage())); +- return; +- } +- throw new IllegalStateException("No exception thrown"); +- } +- +- @Test +- public void testSyncSameThread() { +- final Event event = new TestEvent(false); +- pm.callEvent(event); +- } +- +- @Test +- public void testAsyncLocked() throws InterruptedException { +- final Event event = new TestEvent(true); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- synchronized (pm) { +- pm.callEvent(event); +- } +- } catch (Throwable ex) { +- store.value = ex; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- assertThat(store.value, is(instanceOf(IllegalStateException.class))); +- assertThat(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.", is(((Throwable) store.value).getMessage())); +- } +- +- @Test +- public void testAsyncUnlocked() throws InterruptedException { +- final Event event = new TestEvent(true); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- pm.callEvent(event); +- } catch (Throwable ex) { +- store.value = ex; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value != null) { +- throw new RuntimeException((Throwable) store.value); +- } +- } +- +- @Test +- public void testSyncUnlocked() throws InterruptedException { +- final Event event = new TestEvent(false); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- pm.callEvent(event); +- } catch (Throwable ex) { +- store.value = ex; +- assertThat(event.getEventName() + " cannot be triggered asynchronously from another thread.", is(ex.getMessage())); +- return; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value == null) { +- throw new IllegalStateException("No exception thrown"); +- } +- } +- +- @Test +- public void testSyncLocked() throws InterruptedException { +- final Event event = new TestEvent(false); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- synchronized (pm) { +- pm.callEvent(event); +- } +- } catch (Throwable ex) { +- store.value = ex; +- assertThat(event.getEventName() + " cannot be triggered asynchronously from another thread.", is(ex.getMessage())); +- return; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value == null) { +- throw new IllegalStateException("No exception thrown"); +- } +- } +- +- @Test +- public void testRemovePermissionByNameLower() { +- this.testRemovePermissionByName("lower"); +- } +- +- @Test +- public void testRemovePermissionByNameUpper() { +- this.testRemovePermissionByName("UPPER"); +- } +- +- @Test +- public void testRemovePermissionByNameCamel() { +- this.testRemovePermissionByName("CaMeL"); +- } +- +- public void testRemovePermissionByPermissionLower() { +- this.testRemovePermissionByPermission("lower"); +- } +- +- @Test +- public void testRemovePermissionByPermissionUpper() { +- this.testRemovePermissionByPermission("UPPER"); +- } +- +- @Test +- public void testRemovePermissionByPermissionCamel() { +- this.testRemovePermissionByPermission("CaMeL"); +- } +- +- private void testRemovePermissionByName(final String name) { +- final Permission perm = new Permission(name); +- pm.addPermission(perm); +- assertThat(pm.getPermission(name), is(perm), "Permission \"" + name + "\" was not added"); +- pm.removePermission(name); +- assertThat(pm.getPermission(name), is(nullValue()), "Permission \"" + name + "\" was not removed"); +- } +- +- private void testRemovePermissionByPermission(final String name) { +- final Permission perm = new Permission(name); +- pm.addPermission(perm); +- assertThat(pm.getPermission(name), is(perm), "Permission \"" + name + "\" was not added"); +- pm.removePermission(perm); +- assertThat(pm.getPermission(name), is(nullValue()), "Permission \"" + name + "\" was not removed"); +- } +- +- @AfterEach +- public void tearDown() { +- pm.clearPlugins(); +- assertThat(pm.getPermissions(), is(empty())); +- } +-} +diff --git a/src/test/java/org/bukkit/plugin/TestPlugin.java b/src/test/java/org/bukkit/plugin/TestPlugin.java +index a8be3e23e3e280ad301d9530de50028515612966..43b58e920e739bb949ac0673e9ef73ba7b500dc9 100644 +--- a/src/test/java/org/bukkit/plugin/TestPlugin.java ++++ b/src/test/java/org/bukkit/plugin/TestPlugin.java +@@ -32,6 +32,12 @@ public class TestPlugin extends PluginBase { + public PluginDescriptionFile getDescription() { + return new PluginDescriptionFile(pluginName, "1.0", "test.test"); + } ++ // Paper start ++ @Override ++ public io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() { ++ return getDescription(); ++ } ++ // Paper end + + @Override + public FileConfiguration getConfig() { +diff --git a/src/test/java/org/bukkit/support/TestServer.java b/src/test/java/org/bukkit/support/TestServer.java +index eb1fd4b911c4af76cdd3eac85d5365e7941a4a2e..2a3ae4afef2716a5fdcefbb6d5e0e011d1db9934 100644 +--- a/src/test/java/org/bukkit/support/TestServer.java ++++ b/src/test/java/org/bukkit/support/TestServer.java +@@ -27,8 +27,7 @@ public final class TestServer { + Thread creatingThread = Thread.currentThread(); + when(instance.isPrimaryThread()).then(mock -> Thread.currentThread().equals(creatingThread)); + +- PluginManager pluginManager = new SimplePluginManager(instance, new SimpleCommandMap(instance)); +- when(instance.getPluginManager()).thenReturn(pluginManager); ++ // Paper - remove plugin manager for Paper Plugins + + Logger logger = Logger.getLogger(TestServer.class.getCanonicalName()); + when(instance.getLogger()).thenReturn(logger); diff --git a/patches/api/0010-Add-Position.patch b/patches/api/0010-Add-Position.patch new file mode 100644 index 000000000000..23e8152911b9 --- /dev/null +++ b/patches/api/0010-Add-Position.patch @@ -0,0 +1,438 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 20 Mar 2022 10:42:28 -0700 +Subject: [PATCH] Add Position + + +diff --git a/src/main/java/io/papermc/paper/math/BlockPosition.java b/src/main/java/io/papermc/paper/math/BlockPosition.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c358bfdefc9bc7598dbd0d89a6b0b8a9408b5bb3 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/math/BlockPosition.java +@@ -0,0 +1,100 @@ ++package io.papermc.paper.math; ++ ++import org.bukkit.Axis; ++import org.bukkit.block.BlockFace; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A position represented with integers. ++ *

      ++ * May see breaking changes until Experimental annotation is removed. ++ * ++ * @see FinePosition ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public interface BlockPosition extends Position { ++ ++ @Override ++ default double x() { ++ return this.blockX(); ++ } ++ ++ @Override ++ default double y() { ++ return this.blockY(); ++ } ++ ++ @Override ++ default double z() { ++ return this.blockZ(); ++ } ++ ++ @Override ++ default boolean isBlock() { ++ return true; ++ } ++ ++ @Override ++ default boolean isFine() { ++ return false; ++ } ++ ++ @Override ++ default BlockPosition toBlock() { ++ return this; ++ } ++ ++ @Override ++ default BlockPosition offset(final int x, final int y, final int z) { ++ return x == 0 && y == 0 && z == 0 ? this : new BlockPositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z); ++ } ++ ++ @Override ++ default FinePosition offset(final double x, final double y, final double z) { ++ return new FinePositionImpl(this.blockX() + x, this.blockY() + y, this.blockZ() + z); ++ } ++ ++ /** ++ * Returns a block position offset by 1 in the direction specified. ++ * ++ * @param blockFace the block face to offset towards ++ * @return the offset block position ++ */ ++ @Contract(value = "_ -> new", pure = true) ++ default BlockPosition offset(final BlockFace blockFace) { ++ return this.offset(blockFace, 1); ++ } ++ ++ /** ++ * Returns a block position offset in the direction specified ++ * multiplied by the amount. ++ * ++ * @param blockFace the block face to offset towards ++ * @param amount the number of times to move in that direction ++ * @return the offset block position ++ */ ++ @Contract(pure = true) ++ default BlockPosition offset(final BlockFace blockFace, final int amount) { ++ return amount == 0 ? this : new BlockPositionImpl(this.blockX() + (blockFace.getModX() * amount), this.blockY() + (blockFace.getModY() * amount), this.blockZ() + (blockFace.getModZ() * amount)); ++ } ++ ++ /** ++ * Returns a block position offset by the amount along ++ * the specified axis. ++ * ++ * @param axis the axis to offset along ++ * @param amount the amount to offset along that axis ++ * @return the offset block position ++ */ ++ @Contract(pure = true) ++ default BlockPosition offset(final Axis axis, final int amount) { ++ return amount == 0 ? this : switch (axis) { ++ case X -> new BlockPositionImpl(this.blockX() + amount, this.blockY(), this.blockZ()); ++ case Y -> new BlockPositionImpl(this.blockX(), this.blockY() + amount, this.blockZ()); ++ case Z -> new BlockPositionImpl(this.blockX(), this.blockY(), this.blockZ() + amount); ++ }; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/math/BlockPositionImpl.java b/src/main/java/io/papermc/paper/math/BlockPositionImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eb5a3f26c7ba56c6715827f52c0013a860ec7d9a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/math/BlockPositionImpl.java +@@ -0,0 +1,4 @@ ++package io.papermc.paper.math; ++ ++record BlockPositionImpl(int blockX, int blockY, int blockZ) implements BlockPosition { ++} +diff --git a/src/main/java/io/papermc/paper/math/FinePosition.java b/src/main/java/io/papermc/paper/math/FinePosition.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b9c0065d8a9dedc3bd1a2d8bfbedfbc7f952ff93 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/math/FinePosition.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.math; ++ ++import org.bukkit.util.NumberConversions; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A position represented with doubles. ++ *

      ++ * May see breaking changes until Experimental annotation is removed. ++ * ++ * @see BlockPosition ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public interface FinePosition extends Position { ++ ++ @Override ++ default int blockX() { ++ return NumberConversions.floor(this.x()); ++ } ++ ++ @Override ++ default int blockY() { ++ return NumberConversions.floor(this.y()); ++ } ++ ++ @Override ++ default int blockZ() { ++ return NumberConversions.floor(this.z()); ++ } ++ ++ @Override ++ default boolean isBlock() { ++ return false; ++ } ++ ++ @Override ++ default boolean isFine() { ++ return true; ++ } ++ ++ @Override ++ default BlockPosition toBlock() { ++ return new BlockPositionImpl(this.blockX(), this.blockY(), this.blockZ()); ++ } ++ ++ @Override ++ default FinePosition offset(final int x, final int y, final int z) { ++ return this.offset((double) x, y, z); ++ } ++ ++ @Override ++ default FinePosition offset(final double x, final double y, final double z) { ++ return x == 0.0 && y == 0.0 && z == 0.0 ? this : new FinePositionImpl(this.x() + x, this.y() + y, this.z() + z); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/math/FinePositionImpl.java b/src/main/java/io/papermc/paper/math/FinePositionImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93476aaf8d21efb5a30b6d2cc2eeda8100fb72d0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/math/FinePositionImpl.java +@@ -0,0 +1,4 @@ ++package io.papermc.paper.math; ++ ++record FinePositionImpl(double x, double y, double z) implements FinePosition { ++} +diff --git a/src/main/java/io/papermc/paper/math/Position.java b/src/main/java/io/papermc/paper/math/Position.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0e6a6a6738353b118e0ed093994dda06750700c4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/math/Position.java +@@ -0,0 +1,192 @@ ++package io.papermc.paper.math; ++ ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.util.Vector; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Common interface for {@link FinePosition} and {@link BlockPosition}. ++ *

      ++ * May see breaking changes until Experimental annotation is removed. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public interface Position { ++ ++ FinePosition FINE_ZERO = new FinePositionImpl(0, 0, 0); ++ BlockPosition BLOCK_ZERO = new BlockPositionImpl(0, 0, 0); ++ ++ /** ++ * Gets the block x value for this position ++ * ++ * @return the block x value ++ */ ++ int blockX(); ++ ++ /** ++ * Gets the block x value for this position ++ * ++ * @return the block x value ++ */ ++ int blockY(); ++ ++ /** ++ * Gets the block x value for this position ++ * ++ * @return the block x value ++ */ ++ int blockZ(); ++ ++ /** ++ * Gets the x value for this position ++ * ++ * @return the x value ++ */ ++ double x(); ++ ++ /** ++ * Gets the y value for this position ++ * ++ * @return the y value ++ */ ++ double y(); ++ ++ /** ++ * Gets the z value for this position ++ * ++ * @return the z value ++ */ ++ double z(); ++ ++ /** ++ * Checks of this position represents a {@link BlockPosition} ++ * ++ * @return true if block ++ */ ++ boolean isBlock(); ++ ++ /** ++ * Checks if this position represents a {@link FinePosition} ++ * ++ * @return true if fine ++ */ ++ boolean isFine(); ++ ++ /** ++ * Checks if each component of this position is finite. ++ */ ++ default boolean isFinite() { ++ return Double.isFinite(this.x()) && Double.isFinite(this.y()) && Double.isFinite(this.z()); ++ } ++ ++ /** ++ * Returns a position offset by the specified amounts. ++ * ++ * @param x x value to offset ++ * @param y y value to offset ++ * @param z z value to offset ++ * @return the offset position ++ */ ++ Position offset(int x, int y, int z); ++ ++ /** ++ * Returns a position offset by the specified amounts. ++ * ++ * @param x x value to offset ++ * @param y y value to offset ++ * @param z z value to offset ++ * @return the offset position ++ */ ++ FinePosition offset(double x, double y, double z); ++ ++ /** ++ * Returns a new position at the center of the block position this represents ++ * ++ * @return a new center position ++ */ ++ @Contract(value = "-> new", pure = true) ++ default FinePosition toCenter() { ++ return new FinePositionImpl(this.blockX() + 0.5, this.blockY() + 0.5, this.blockZ() + 0.5); ++ } ++ ++ /** ++ * Returns the block position of this position ++ * or itself if it already is a block position ++ * ++ * @return the block position ++ */ ++ @Contract(pure = true) ++ BlockPosition toBlock(); ++ ++ /** ++ * Converts this position to a vector ++ * ++ * @return a new vector ++ */ ++ @Contract(value = "-> new", pure = true) ++ default Vector toVector() { ++ return new Vector(this.x(), this.y(), this.z()); ++ } ++ ++ /** ++ * Creates a new location object at this position with the specified world ++ * ++ * @param world the world for the location object ++ * @return a new location ++ */ ++ @Contract(value = "_ -> new", pure = true) ++ default Location toLocation(final World world) { ++ return new Location(world, this.x(), this.y(), this.z()); ++ } ++ ++ /** ++ * Creates a position at the coordinates ++ * ++ * @param x x coord ++ * @param y y coord ++ * @param z z coord ++ * @return a position with those coords ++ */ ++ @Contract(value = "_, _, _ -> new", pure = true) ++ static BlockPosition block(final int x, final int y, final int z) { ++ return new BlockPositionImpl(x, y, z); ++ } ++ ++ /** ++ * Creates a position from the location. ++ * ++ * @param location the location to copy the position of ++ * @return a new position at that location ++ */ ++ @Contract(value = "_ -> new", pure = true) ++ static BlockPosition block(final Location location) { ++ return new BlockPositionImpl(location.getBlockX(), location.getBlockY(), location.getBlockZ()); ++ } ++ ++ /** ++ * Creates a position at the coordinates ++ * ++ * @param x x coord ++ * @param y y coord ++ * @param z z coord ++ * @return a position with those coords ++ */ ++ @Contract(value = "_, _, _ -> new", pure = true) ++ static FinePosition fine(final double x, final double y, final double z) { ++ return new FinePositionImpl(x, y, z); ++ } ++ ++ /** ++ * Creates a position from the location. ++ * ++ * @param location the location to copy the position of ++ * @return a new position at that location ++ */ ++ @Contract(value = "_ -> new", pure = true) ++ static FinePosition fine(final Location location) { ++ return new FinePositionImpl(location.getX(), location.getY(), location.getZ()); ++ } ++} +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 734054f1e8dad74c13d7ae0b1c1af2d9f45b2636..bc8a64d54e001eae6ef4520a49e261b96c5ae9f3 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; + * magnitude than 360 are valid, but may be normalized to any other equivalent + * representation by the implementation. + */ +-public class Location implements Cloneable, ConfigurationSerializable { ++public class Location implements Cloneable, ConfigurationSerializable, io.papermc.paper.math.FinePosition { // Paper + private Reference world; + private double x; + private double y; +@@ -706,4 +706,31 @@ public class Location implements Cloneable, ConfigurationSerializable { + } + return pitch; + } ++ ++ // Paper - add Position ++ @Override ++ public double x() { ++ return this.getX(); ++ } ++ ++ @Override ++ public double y() { ++ return this.getY(); ++ } ++ ++ @Override ++ public double z() { ++ return this.getZ(); ++ } ++ ++ @Override ++ public boolean isFinite() { ++ return io.papermc.paper.math.FinePosition.super.isFinite() && Float.isFinite(this.getYaw()) && Float.isFinite(this.getPitch()); ++ } ++ ++ @Override ++ public @NotNull Location toLocation(@NotNull World world) { ++ return new Location(world, this.x(), this.y(), this.z(), this.getYaw(), this.getPitch()); ++ } ++ // Paper end + } diff --git a/patches/api/0011-Timings-v2.patch b/patches/api/0011-Timings-v2.patch new file mode 100644 index 000000000000..00348af95d9c --- /dev/null +++ b/patches/api/0011-Timings-v2.patch @@ -0,0 +1,3798 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 18:48:17 -0600 +Subject: [PATCH] Timings v2 + +TODO: Add #isStopping to FullServerTickHandler#stopTiming in patch 191 +expose isRunning + +diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..73b125979e2f2dfd13cbf689a90b29cc68a36e09 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java +@@ -0,0 +1,89 @@ ++package co.aikar.timings; ++ ++import static co.aikar.timings.TimingsManager.*; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public class FullServerTickHandler extends TimingHandler { ++ private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null); ++ final TimingData minuteData; ++ double avgFreeMemory = -1D; ++ double avgUsedMemory = -1D; ++ FullServerTickHandler() { ++ super(IDENTITY); ++ minuteData = new TimingData(id); ++ ++ TIMING_MAP.put(IDENTITY, this); ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ if (TimingsManager.needsFullReset) { ++ TimingsManager.resetTimings(); ++ } else if (TimingsManager.needsRecheckEnabled) { ++ TimingsManager.recheckEnabled(); ++ } ++ return super.startTiming(); ++ } ++ ++ @Override ++ public void stopTiming() { ++ super.stopTiming(); ++ if (!isEnabled()) { ++ return; ++ } ++ if (TimingHistory.timedTicks % 20 == 0) { ++ final Runtime runtime = Runtime.getRuntime(); ++ double usedMemory = runtime.totalMemory() - runtime.freeMemory(); ++ double freeMemory = runtime.maxMemory() - usedMemory; ++ if (this.avgFreeMemory == -1) { ++ this.avgFreeMemory = freeMemory; ++ } else { ++ this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D)); ++ } ++ ++ if (this.avgUsedMemory == -1) { ++ this.avgUsedMemory = usedMemory; ++ } else { ++ this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D)); ++ } ++ } ++ ++ long start = System.nanoTime(); ++ TimingsManager.tick(); ++ long diff = System.nanoTime() - start; ++ TIMINGS_TICK.addDiff(diff, null); ++ // addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick. ++ record.setCurTickCount(record.getCurTickCount()-1); ++ ++ minuteData.setCurTickTotal(record.getCurTickTotal()); ++ minuteData.setCurTickCount(1); ++ ++ boolean violated = isViolated(); ++ minuteData.processTick(violated); ++ TIMINGS_TICK.processTick(violated); ++ processTick(violated); ++ ++ ++ if (TimingHistory.timedTicks % 1200 == 0) { ++ MINUTE_REPORTS.add(new TimingHistory.MinuteReport()); ++ TimingHistory.resetTicks(false); ++ minuteData.reset(); ++ } ++ if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) { ++ TimingsManager.HISTORY.add(new TimingHistory()); ++ TimingsManager.resetTimings(); ++ } ++ //Bukkit.getUnsafe().reportTimings(); ++ } ++ ++ boolean isViolated() { ++ return record.getCurTickTotal() > 50000000; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/NullTimingHandler.java b/src/main/java/co/aikar/timings/NullTimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..42e7e712403676171d34d5f2be27e48e7a071ebd +--- /dev/null ++++ b/src/main/java/co/aikar/timings/NullTimingHandler.java +@@ -0,0 +1,72 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public final class NullTimingHandler implements Timing { ++ public static final Timing NULL = new NullTimingHandler(); ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ return this; ++ } ++ ++ @Override ++ public void stopTiming() { ++ ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTimingIfSync() { ++ return this; ++ } ++ ++ @Override ++ public void stopTimingIfSync() { ++ ++ } ++ ++ @Override ++ public void abort() { ++ ++ } ++ ++ @Nullable ++ @Override ++ public TimingHandler getTimingHandler() { ++ return null; ++ } ++ ++ @Override ++ public void close() { ++ ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a3ad690691eb5537a565d7ba684354acfec5ee2d +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java +@@ -0,0 +1,87 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventException; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.EventExecutor; ++import org.bukkit.plugin.Plugin; ++ ++import java.lang.reflect.Method; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public class TimedEventExecutor implements EventExecutor { ++ ++ private final EventExecutor executor; ++ private final Timing timings; ++ ++ /** ++ * Wraps an event executor and associates a timing handler to it. ++ * ++ * @param executor Executor to wrap ++ * @param plugin Owning plugin ++ * @param method EventHandler method ++ * @param eventClass Owning class ++ */ ++ public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class eventClass) { ++ this.executor = executor; ++ String id; ++ ++ if (method == null) { ++ if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you ++ method = executor.getClass().getEnclosingMethod(); ++ } ++ } ++ ++ if (method != null) { ++ id = method.getDeclaringClass().getName(); ++ } else { ++ id = executor.getClass().getName(); ++ } ++ ++ ++ final String eventName = eventClass.getSimpleName(); ++ boolean verbose = "BlockPhysicsEvent".equals(eventName); ++ this.timings = Timings.ofSafe(plugin, (verbose ? "## " : "") + ++ "Event: " + id + " (" + eventName + ")"); ++ } ++ ++ @Override ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) { ++ executor.execute(listener, event); ++ return; ++ } ++ try (Timing ignored = timings.startTiming()){ ++ executor.execute(listener, event); ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4195efcfe044618052bb03dea34a4fb2ca7c44f0 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/Timing.java +@@ -0,0 +1,86 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Provides an ability to time sections of code within the Minecraft Server ++ * ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public interface Timing extends AutoCloseable { ++ /** ++ * Starts timing the execution until {@link #stopTiming()} is called. ++ * ++ * @return Timing ++ */ ++ @NotNull ++ Timing startTiming(); ++ ++ /** ++ *

      Stops timing and records the data. Propagates the data up to group handlers.

      ++ * ++ * Will automatically be called when this Timing is used with try-with-resources ++ */ ++ void stopTiming(); ++ ++ /** ++ * Starts timing the execution until {@link #stopTiming()} is called. ++ * ++ * But only if we are on the primary thread. ++ * ++ * @return Timing ++ */ ++ @NotNull ++ Timing startTimingIfSync(); ++ ++ /** ++ *

      Stops timing and records the data. Propagates the data up to group handlers.

      ++ * ++ *

      Will automatically be called when this Timing is used with try-with-resources

      ++ * ++ * But only if we are on the primary thread. ++ */ ++ void stopTimingIfSync(); ++ ++ /** ++ * @deprecated Doesn't do anything - Removed ++ */ ++ @Deprecated ++ void abort(); ++ ++ /** ++ * Used internally to get the actual backing Handler in the case of delegated Handlers ++ * ++ * @return TimingHandler ++ */ ++ @Nullable ++ TimingHandler getTimingHandler(); ++ ++ @Override ++ void close(); ++} +diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a5d13a1e44edb861f45c83a9b4309fbf799d407d +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingData.java +@@ -0,0 +1,122 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++ ++import static co.aikar.util.JSONUtil.toArray; ++ ++/** ++ *

      Lightweight object for tracking timing data

      ++ * ++ * This is broken out to reduce memory usage ++ */ ++class TimingData { ++ private final int id; ++ private int count = 0; ++ private int lagCount = 0; ++ private long totalTime = 0; ++ private long lagTotalTime = 0; ++ private int curTickCount = 0; ++ private long curTickTotal = 0; ++ ++ TimingData(int id) { ++ this.id = id; ++ } ++ ++ private TimingData(TimingData data) { ++ this.id = data.id; ++ this.totalTime = data.totalTime; ++ this.lagTotalTime = data.lagTotalTime; ++ this.count = data.count; ++ this.lagCount = data.lagCount; ++ } ++ ++ void add(long diff) { ++ ++curTickCount; ++ curTickTotal += diff; ++ } ++ ++ void processTick(boolean violated) { ++ totalTime += curTickTotal; ++ count += curTickCount; ++ if (violated) { ++ lagTotalTime += curTickTotal; ++ lagCount += curTickCount; ++ } ++ curTickTotal = 0; ++ curTickCount = 0; ++ } ++ ++ void reset() { ++ count = 0; ++ lagCount = 0; ++ curTickTotal = 0; ++ curTickCount = 0; ++ totalTime = 0; ++ lagTotalTime = 0; ++ } ++ ++ protected TimingData clone() { ++ return new TimingData(this); ++ } ++ ++ @NotNull ++ List export() { ++ List list = toArray( ++ id, ++ count, ++ totalTime); ++ if (lagCount > 0) { ++ list.add(lagCount); ++ list.add(lagTotalTime); ++ } ++ return list; ++ } ++ ++ boolean hasData() { ++ return count > 0; ++ } ++ ++ long getTotalTime() { ++ return totalTime; ++ } ++ ++ int getCurTickCount() { ++ return curTickCount; ++ } ++ ++ void setCurTickCount(int curTickCount) { ++ this.curTickCount = curTickCount; ++ } ++ ++ long getCurTickTotal() { ++ return curTickTotal; ++ } ++ ++ void setCurTickTotal(long curTickTotal) { ++ this.curTickTotal = curTickTotal; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..199789d56d22fcb1b77ebd56805cc28aa5a5ab0a +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHandler.java +@@ -0,0 +1,226 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingIntMap; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++ ++import java.util.ArrayDeque; ++import java.util.Deque; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++class TimingHandler implements Timing { ++ ++ private static AtomicInteger idPool = new AtomicInteger(1); ++ private static Deque TIMING_STACK = new ArrayDeque<>(); ++ final int id = idPool.getAndIncrement(); ++ ++ final TimingIdentifier identifier; ++ private final boolean verbose; ++ ++ private final Int2ObjectOpenHashMap children = new LoadingIntMap<>(TimingData::new); ++ ++ final TimingData record; ++ private TimingHandler startParent; ++ private final TimingHandler groupHandler; ++ ++ private long start = 0; ++ private int timingDepth = 0; ++ private boolean added; ++ private boolean timed; ++ private boolean enabled; ++ ++ TimingHandler(@NotNull TimingIdentifier id) { ++ this.identifier = id; ++ this.verbose = id.name.startsWith("##"); ++ this.record = new TimingData(this.id); ++ this.groupHandler = id.groupHandler; ++ ++ TimingIdentifier.getGroup(id.group).handlers.add(this); ++ checkEnabled(); ++ } ++ ++ final void checkEnabled() { ++ enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled); ++ } ++ ++ void processTick(boolean violated) { ++ if (timingDepth != 0 || record.getCurTickCount() == 0) { ++ timingDepth = 0; ++ start = 0; ++ return; ++ } ++ ++ record.processTick(violated); ++ for (TimingData handler : children.values()) { ++ handler.processTick(violated); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTimingIfSync() { ++ startTiming(); ++ return this; ++ } ++ ++ @Override ++ public void stopTimingIfSync() { ++ stopTiming(); ++ } ++ ++ @NotNull ++ public Timing startTiming() { ++ if (!enabled || !Bukkit.isPrimaryThread()) { ++ return this; ++ } ++ if (++timingDepth == 1) { ++ startParent = TIMING_STACK.peekLast(); ++ start = System.nanoTime(); ++ } ++ TIMING_STACK.addLast(this); ++ return this; ++ } ++ ++ public void stopTiming() { ++ if (!enabled || timingDepth <= 0 || start == 0 || !Bukkit.isPrimaryThread()) { ++ return; ++ } ++ ++ popTimingStack(); ++ if (--timingDepth == 0) { ++ addDiff(System.nanoTime() - start, startParent); ++ startParent = null; ++ start = 0; ++ } ++ } ++ ++ private void popTimingStack() { ++ TimingHandler last; ++ while ((last = TIMING_STACK.removeLast()) != this) { ++ last.timingDepth = 0; ++ if ("Minecraft".equalsIgnoreCase(last.identifier.group)) { ++ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Look above this for any errors and report this to Paper unless it has a plugin in the stack trace (" + last.identifier + " did not stopTiming)"); ++ } else { ++ Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + last.identifier + " did not stopTiming)", new Throwable()); ++ } ++ ++ boolean found = TIMING_STACK.contains(this); ++ if (!found) { ++ // We aren't even in the stack... Don't pop everything ++ TIMING_STACK.addLast(last); ++ break; ++ } ++ } ++ } ++ ++ @Override ++ public final void abort() { ++ ++ } ++ ++ void addDiff(long diff, @Nullable TimingHandler parent) { ++ if (parent != null) { ++ parent.children.get(id).add(diff); ++ } ++ ++ record.add(diff); ++ if (!added) { ++ added = true; ++ timed = true; ++ TimingsManager.HANDLERS.add(this); ++ } ++ if (groupHandler != null) { ++ groupHandler.addDiff(diff, parent); ++ groupHandler.children.get(id).add(diff); ++ } ++ } ++ ++ /** ++ * Reset this timer, setting all values to zero. ++ */ ++ void reset(boolean full) { ++ record.reset(); ++ if (full) { ++ timed = false; ++ } ++ start = 0; ++ timingDepth = 0; ++ added = false; ++ children.clear(); ++ checkEnabled(); ++ } ++ ++ @NotNull ++ @Override ++ public TimingHandler getTimingHandler() { ++ return this; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ return (this == o); ++ } ++ ++ @Override ++ public int hashCode() { ++ return id; ++ } ++ ++ /** ++ * This is simply for the Closeable interface so it can be used with try-with-resources () ++ */ ++ @Override ++ public void close() { ++ stopTimingIfSync(); ++ } ++ ++ public boolean isSpecial() { ++ return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK; ++ } ++ ++ boolean isTimed() { ++ return timed; ++ } ++ ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ @NotNull ++ TimingData[] cloneChildren() { ++ final TimingData[] clonedChildren = new TimingData[children.size()]; ++ int i = 0; ++ for (TimingData child : children.values()) { ++ clonedChildren[i++] = child.clone(); ++ } ++ return clonedChildren; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3d4390f263e52aafa24b306b1fd20d088a4ffcd7 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHistory.java +@@ -0,0 +1,357 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.timings.TimingHistory.RegionData.RegionId; ++import com.google.common.base.Function; ++import com.google.common.collect.Sets; ++import org.bukkit.Bukkit; ++import org.bukkit.Chunk; ++import org.bukkit.Material; ++import org.bukkit.World; ++import org.bukkit.block.BlockState; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import co.aikar.util.LoadingMap; ++import co.aikar.util.MRUMapCache; ++ ++import java.lang.management.ManagementFactory; ++import java.util.Collection; ++import java.util.EnumMap; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK; ++import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; ++import static co.aikar.util.JSONUtil.*; ++ ++/** ++ * Internal. ++ * ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"}) ++public class TimingHistory { ++ public static long lastMinuteTime; ++ public static long timedTicks; ++ public static long playerTicks; ++ public static long entityTicks; ++ public static long tileEntityTicks; ++ public static long activatedEntityTicks; ++ private static int worldIdPool = 1; ++ static Map worldMap = LoadingMap.newHashMap(new Function() { ++ @NotNull ++ @Override ++ public Integer apply(@Nullable String input) { ++ return worldIdPool++; ++ } ++ }); ++ private final long endTime; ++ private final long startTime; ++ private final long totalTicks; ++ private final long totalTime; // Represents all time spent running the server this history ++ private final MinuteReport[] minuteReports; ++ ++ private final TimingHistoryEntry[] entries; ++ final Set tileEntityTypeSet = Sets.newHashSet(); ++ final Set entityTypeSet = Sets.newHashSet(); ++ private final Map worlds; ++ ++ TimingHistory() { ++ this.endTime = System.currentTimeMillis() / 1000; ++ this.startTime = TimingsManager.historyStart / 1000; ++ if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { ++ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); ++ this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); ++ } else { ++ this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]); ++ } ++ long ticks = 0; ++ for (MinuteReport mp : this.minuteReports) { ++ ticks += mp.ticksRecord.timed; ++ } ++ this.totalTicks = ticks; ++ this.totalTime = FULL_SERVER_TICK.record.getTotalTime(); ++ this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()]; ++ ++ int i = 0; ++ for (TimingHandler handler : TimingsManager.HANDLERS) { ++ entries[i++] = new TimingHistoryEntry(handler); ++ } ++ ++ // Information about all loaded chunks/entities ++ //noinspection unchecked ++ this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function() { ++ @NotNull ++ @Override ++ public JSONPair apply(World world) { ++ Map regions = LoadingMap.newHashMap(RegionData.LOADER); ++ ++ for (Chunk chunk : world.getLoadedChunks()) { ++ RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ())); ++ ++ for (Entity entity : chunk.getEntities()) { ++ if (entity == null) { ++ Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); ++ continue; ++ } ++ ++ data.entityCounts.get(entity.getType()).increment(); ++ } ++ ++ for (BlockState tileEntity : chunk.getTileEntities()) { ++ if (tileEntity == null) { ++ Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ()); ++ continue; ++ } ++ ++ data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); ++ } ++ } ++ return pair( ++ worldMap.get(world.getName()), ++ toArrayMapper(regions.values(),new Function() { ++ @NotNull ++ @Override ++ public Object apply(RegionData input) { ++ return toArray( ++ input.regionId.x, ++ input.regionId.z, ++ toObjectMapper(input.entityCounts.entrySet(), ++ new Function, JSONPair>() { ++ @NotNull ++ @Override ++ public JSONPair apply(Map.Entry entry) { ++ entityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().ordinal()), ++ entry.getValue().count() ++ ); ++ } ++ } ++ ), ++ toObjectMapper( ++ input.tileEntityCounts.entrySet(), ++ entry -> { ++ tileEntityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().ordinal()), ++ entry.getValue().count() ++ ); ++ } ++ ) ++ ); ++ } ++ }) ++ ); ++ } ++ }); ++ } ++ static class RegionData { ++ final RegionId regionId; ++ @SuppressWarnings("Guava") ++ static Function LOADER = new Function() { ++ @NotNull ++ @Override ++ public RegionData apply(@NotNull RegionId id) { ++ return new RegionData(id); ++ } ++ }; ++ RegionData(@NotNull RegionId id) { ++ this.regionId = id; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) { ++ return true; ++ } ++ if (o == null || getClass() != o.getClass()) { ++ return false; ++ } ++ ++ RegionData that = (RegionData) o; ++ ++ return regionId.equals(that.regionId); ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return regionId.hashCode(); ++ } ++ ++ @SuppressWarnings("unchecked") ++ final Map entityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(EntityType.class), k -> new Counter() ++ )); ++ @SuppressWarnings("unchecked") ++ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(Material.class), k -> new Counter() ++ )); ++ ++ static class RegionId { ++ final int x, z; ++ final long regionId; ++ RegionId(int x, int z) { ++ this.x = x >> 5 << 5; ++ this.z = z >> 5 << 5; ++ this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ++ RegionId regionId1 = (RegionId) o; ++ ++ return regionId == regionId1.regionId; ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return (int) (regionId ^ (regionId >>> 32)); ++ } ++ } ++ } ++ static void resetTicks(boolean fullReset) { ++ if (fullReset) { ++ // Non full is simply for 1 minute reports ++ timedTicks = 0; ++ } ++ lastMinuteTime = System.nanoTime(); ++ playerTicks = 0; ++ tileEntityTicks = 0; ++ entityTicks = 0; ++ activatedEntityTicks = 0; ++ } ++ ++ @NotNull ++ Object export() { ++ return createObject( ++ pair("s", startTime), ++ pair("e", endTime), ++ pair("tk", totalTicks), ++ pair("tm", totalTime), ++ pair("w", worlds), ++ pair("h", toArrayMapper(entries, new Function() { ++ @Nullable ++ @Override ++ public Object apply(TimingHistoryEntry entry) { ++ TimingData record = entry.data; ++ if (!record.hasData()) { ++ return null; ++ } ++ return entry.export(); ++ } ++ })), ++ pair("mp", toArrayMapper(minuteReports, new Function() { ++ @NotNull ++ @Override ++ public Object apply(MinuteReport input) { ++ return input.export(); ++ } ++ })) ++ ); ++ } ++ ++ static class MinuteReport { ++ final long time = System.currentTimeMillis() / 1000; ++ ++ final TicksRecord ticksRecord = new TicksRecord(); ++ final PingRecord pingRecord = new PingRecord(); ++ final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone(); ++ final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed; ++ final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory; ++ final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory; ++ final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); ++ ++ @NotNull ++ List export() { ++ return toArray( ++ time, ++ Math.round(tps * 100D) / 100D, ++ Math.round(pingRecord.avg * 100D) / 100D, ++ fst.export(), ++ toArray(ticksRecord.timed, ++ ticksRecord.player, ++ ticksRecord.entity, ++ ticksRecord.activatedEntity, ++ ticksRecord.tileEntity ++ ), ++ usedMemory, ++ freeMemory, ++ loadAvg ++ ); ++ } ++ } ++ ++ private static class TicksRecord { ++ final long timed; ++ final long player; ++ final long entity; ++ final long tileEntity; ++ final long activatedEntity; ++ ++ TicksRecord() { ++ timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200); ++ player = playerTicks; ++ entity = entityTicks; ++ tileEntity = tileEntityTicks; ++ activatedEntity = activatedEntityTicks; ++ } ++ ++ } ++ ++ private static class PingRecord { ++ final double avg; ++ ++ PingRecord() { ++ final Collection onlinePlayers = Bukkit.getOnlinePlayers(); ++ int totalPing = 0; ++ for (Player player : onlinePlayers) { ++ totalPing += player.spigot().getPing(); ++ } ++ avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size(); ++ } ++ } ++ ++ ++ private static class Counter { ++ private int count = 0; ++ public int increment() { ++ return ++count; ++ } ++ public int count() { ++ return count; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingHistoryEntry.java b/src/main/java/co/aikar/timings/TimingHistoryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..86d5ac6bd0d7d0003688761aceb3f3343575319f +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java +@@ -0,0 +1,58 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.base.Function; ++ ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++ ++import static co.aikar.util.JSONUtil.toArrayMapper; ++ ++class TimingHistoryEntry { ++ final TimingData data; ++ private final TimingData[] children; ++ ++ TimingHistoryEntry(@NotNull TimingHandler handler) { ++ this.data = handler.record.clone(); ++ children = handler.cloneChildren(); ++ } ++ ++ @NotNull ++ List export() { ++ List result = data.export(); ++ if (children.length > 0) { ++ result.add( ++ toArrayMapper(children, new Function() { ++ @NotNull ++ @Override ++ public Object apply(TimingData child) { ++ return child.export(); ++ } ++ }) ++ ); ++ } ++ return result; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java +new file mode 100644 +index 0000000000000000000000000000000000000000..df142a89b8c43acb81eb383eac0ef048a1f49a6e +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingIdentifier.java +@@ -0,0 +1,116 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingMap; ++ ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.List; ++import java.util.Map; ++import java.util.Objects; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.atomic.AtomicInteger; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ *

      Used as a basis for fast HashMap key comparisons for the Timing Map.

      ++ * ++ * This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings ++ */ ++final class TimingIdentifier { ++ /** ++ * Holds all groups. Autoloads on request for a group by name. ++ */ ++ static final Map GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new); ++ private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft"); ++ final String group; ++ final String name; ++ final TimingHandler groupHandler; ++ private final int hashCode; ++ ++ TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) { ++ this.group = group != null ? group: DEFAULT_GROUP.name; ++ this.name = name; ++ this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null; ++ this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode(); ++ } ++ ++ @NotNull ++ static TimingGroup getGroup(@Nullable String groupName) { ++ if (groupName == null) { ++ //noinspection ConstantConditions ++ return DEFAULT_GROUP; ++ } ++ ++ return GROUP_MAP.get(groupName); ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (o == null) { ++ return false; ++ } ++ ++ TimingIdentifier that = (TimingIdentifier) o; ++ return Objects.equals(group, that.group) && Objects.equals(name, that.name); ++ } ++ ++ @Override ++ public int hashCode() { ++ return hashCode; ++ } ++ ++ @Override ++ public String toString() { ++ return "TimingIdentifier{id=" + group + ":" + name +'}'; ++ } ++ ++ static class TimingGroup { ++ ++ private static AtomicInteger idPool = new AtomicInteger(1); ++ final int id = idPool.getAndIncrement(); ++ ++ final String name; ++ final List handlers = Collections.synchronizedList(new ArrayList<>(64)); ++ ++ private TimingGroup(String name) { ++ this.name = name; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ TimingGroup that = (TimingGroup) o; ++ return id == that.id; ++ } ++ ++ @Override ++ public int hashCode() { ++ return id; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java +new file mode 100644 +index 0000000000000000000000000000000000000000..95b7cdf0677ef71e6885fa78aa5c75bb500f5f53 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/Timings.java +@@ -0,0 +1,325 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.EvictingQueue; ++import com.google.common.collect.Lists; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.List; ++import java.util.Queue; ++import java.util.logging.Level; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"}) ++public final class Timings { ++ ++ final static List requestingReport = Lists.newArrayList(); ++ private static final int MAX_HISTORY_FRAMES = 12; ++ public static final Timing NULL_HANDLER = new NullTimingHandler(); ++ static boolean timingsEnabled = false; ++ static boolean verboseEnabled = false; ++ private static int historyInterval = -1; ++ private static int historyLength = -1; ++ private static boolean warnedAboutDeprecationOnEnable; ++ ++ private Timings() {} ++ ++ /** ++ * Returns a Timing for a plugin corresponding to a name. ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @return Handler ++ */ ++ @NotNull ++ public static Timing of(@NotNull Plugin plugin, @NotNull String name) { ++ Timing pluginHandler = null; ++ if (plugin != null) { ++ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); ++ } ++ return of(plugin, name, pluginHandler); ++ } ++ ++ /** ++ *

      Returns a handler that has a groupHandler timer handler. Parent timers should not have their ++ * start/stop methods called directly, as the children will call it for you.

      ++ * ++ * Parent Timers are used to group multiple subsections together and get a summary of them combined ++ * Parent Handler can not be changed after first call ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @param groupHandler Parent handler to mirror .start/stop calls to ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { ++ Preconditions.checkNotNull(plugin, "Plugin can not be null"); ++ Bukkit.getLogger().warning(String.format("Plugin '%s' is creating timing '%s' - this is deprecated behavior, please report it to the authors: %s", plugin.getName(), name, String.join(", ", plugin.getDescription().getAuthors()))); ++ return TimingsManager.getHandler(plugin.getName(), name, groupHandler); ++ } ++ ++ /** ++ * Returns a Timing object after starting it, useful for Java7 try-with-resources. ++ * ++ * try (Timing ignored = Timings.ofStart(plugin, someName)) { ++ * // timed section ++ * } ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) { ++ return ofStart(plugin, name, null); ++ } ++ ++ /** ++ * Returns a Timing object after starting it, useful for Java7 try-with-resources. ++ * ++ * try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) { ++ * // timed section ++ * } ++ * ++ * @param plugin Plugin to own the Timing ++ * @param name Name of Timing ++ * @param groupHandler Parent handler to mirror .start/stop calls to ++ * @return Timing Handler ++ */ ++ @NotNull ++ public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) { ++ Timing timing = of(plugin, name, groupHandler); ++ timing.startTiming(); ++ return timing; ++ } ++ ++ /** ++ * Gets whether or not the Spigot Timings system is enabled ++ * ++ * @return Enabled or not ++ */ ++ public static boolean isTimingsEnabled() { ++ return timingsEnabled; ++ } ++ ++ /** ++ *

      Sets whether or not the Spigot Timings system should be enabled

      ++ * ++ * Calling this will reset timing data. ++ * ++ * @param enabled Should timings be reported ++ */ ++ public static void setTimingsEnabled(boolean enabled) { ++ if (enabled && !warnedAboutDeprecationOnEnable) { ++ Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); ++ warnedAboutDeprecationOnEnable = true; ++ } ++ } ++ ++ public static Component deprecationMessage() { ++ return Component.text() ++ .color(TextColor.color(0xffc93a)) ++ .append(Component.text("[!] The timings profiler is in no-op mode and will be fully removed in a later update.")) ++ .append(Component.newline()) ++ .append(Component.text(" We recommend migrating to the spark profiler.")) ++ .append(Component.newline()) ++ .append( ++ Component.text(" For more information please visit: ") ++ .append( ++ Component.text() ++ .content("https://github.com/PaperMC/Paper/discussions/10565") ++ .clickEvent(ClickEvent.openUrl("https://github.com/PaperMC/Paper/discussions/10565"))) ++ ) ++ .build(); ++ } ++ ++ /** ++ *

      Sets whether or not the Timings should monitor at Verbose level.

      ++ * ++ *

      When Verbose is disabled, high-frequency timings will not be available.

      ++ * ++ * @return Enabled or not ++ */ ++ public static boolean isVerboseTimingsEnabled() { ++ return verboseEnabled; ++ } ++ ++ /** ++ *

      Sets whether or not the Timings should monitor at Verbose level.

      ++ * ++ * When Verbose is disabled, high-frequency timings will not be available. ++ * Calling this will reset timing data. ++ * ++ * @param enabled Should high-frequency timings be reported ++ */ ++ public static void setVerboseTimingsEnabled(boolean enabled) { ++ verboseEnabled = enabled; ++ TimingsManager.needsRecheckEnabled = true; ++ } ++ ++ /** ++ *

      Gets the interval between Timing History report generation.

      ++ * ++ * Defaults to 5 minutes (6000 ticks) ++ * ++ * @return Interval in ticks ++ */ ++ public static int getHistoryInterval() { ++ return historyInterval; ++ } ++ ++ /** ++ *

      Sets the interval between Timing History report generations.

      ++ * ++ *

      Defaults to 5 minutes (6000 ticks)

      ++ * ++ * This will recheck your history length, so lowering this value will lower your ++ * history length if you need more than 60 history windows. ++ * ++ * @param interval Interval in ticks ++ */ ++ public static void setHistoryInterval(int interval) { ++ historyInterval = Math.max(20*60, interval); ++ // Recheck the history length with the new Interval ++ if (historyLength != -1) { ++ setHistoryLength(historyLength); ++ } ++ } ++ ++ /** ++ * Gets how long in ticks Timings history is kept for the server. ++ * ++ * Defaults to 1 hour (72000 ticks) ++ * ++ * @return Duration in Ticks ++ */ ++ public static int getHistoryLength() { ++ return historyLength; ++ } ++ ++ /** ++ * Sets how long Timing History reports are kept for the server. ++ * ++ * Defaults to 1 hours(72000 ticks) ++ * ++ * This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12) ++ * ++ * Will not reset Timing Data but may truncate old history if the new length is less than old length. ++ * ++ * @param length Duration in ticks ++ */ ++ public static void setHistoryLength(int length) { ++ // Cap at 12 History Frames, 1 hour at 5 minute frames. ++ int maxLength = historyInterval * MAX_HISTORY_FRAMES; ++ // For special cases of servers with special permission to bypass the max. ++ // This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side. ++ // Setting this will not help you bypass the max unless Aikar has added an exception on the API side. ++ if (System.getProperty("timings.bypassMax") != null) { ++ maxLength = Integer.MAX_VALUE; ++ } ++ historyLength = Math.max(Math.min(maxLength, length), historyInterval); ++ Queue oldQueue = TimingsManager.HISTORY; ++ int frames = (getHistoryLength() / getHistoryInterval()); ++ if (length > maxLength) { ++ Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length."); ++ } ++ TimingsManager.HISTORY = EvictingQueue.create(frames); ++ TimingsManager.HISTORY.addAll(oldQueue); ++ } ++ ++ /** ++ * Resets all Timing Data ++ */ ++ public static void reset() { ++ TimingsManager.reset(); ++ } ++ ++ /** ++ * Generates a report and sends it to the specified command sender. ++ * ++ * If sender is null, ConsoleCommandSender will be used. ++ * @param sender The sender to send to, or null to use the ConsoleCommandSender ++ */ ++ public static void generateReport(@Nullable CommandSender sender) { ++ if (sender == null) { ++ sender = Bukkit.getConsoleSender(); ++ } ++ requestingReport.add(sender); ++ } ++ ++ /** ++ * Generates a report and sends it to the specified listener. ++ * Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done! ++ * @param sender The listener to send responses too. ++ */ ++ public static void generateReport(@NotNull TimingsReportListener sender) { ++ Preconditions.checkNotNull(sender); ++ requestingReport.add(sender); ++ } ++ ++ /* ++ ================= ++ Protected API: These are for internal use only in Bukkit/CraftBukkit ++ These do not have isPrimaryThread() checks in the startTiming/stopTiming ++ ================= ++ */ ++ @NotNull ++ static TimingHandler ofSafe(@NotNull String name) { ++ return ofSafe(null, name, null); ++ } ++ ++ @NotNull ++ static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) { ++ Timing pluginHandler = null; ++ if (plugin != null) { ++ pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER); ++ } ++ return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler); ++ } ++ ++ @NotNull ++ static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) { ++ return ofSafe(null, name, groupHandler); ++ } ++ ++ @NotNull ++ static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) { ++ return TimingsManager.getHandler(groupName, name, groupHandler); ++ } ++} ++ +diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b83e5ff7ada8771fdf27ba9807c77ba6a4ce12da +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsCommand.java +@@ -0,0 +1,127 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.ImmutableList; ++import net.kyori.adventure.text.format.NamedTextColor; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.defaults.BukkitCommand; ++import org.bukkit.util.StringUtil; ++ ++import java.util.ArrayList; ++import java.util.List; ++import org.jetbrains.annotations.NotNull; ++ ++import static net.kyori.adventure.text.Component.text; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public class TimingsCommand extends BukkitCommand { ++ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff"); ++ private long lastResetAttempt = 0; ++ ++ public TimingsCommand(@NotNull String name) { ++ super(name); ++ this.description = "Manages Spigot Timings data to see performance of the server."; ++ this.usageMessage = "/timings "; ++ this.setPermission("bukkit.command.timings"); ++ } ++ ++ @Override ++ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { ++ if (!testPermission(sender)) { ++ return true; ++ } ++ if (true) { ++ sender.sendMessage(Timings.deprecationMessage()); ++ return true; ++ } ++ if (args.length < 1) { ++ sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); ++ return true; ++ } ++ final String arg = args[0]; ++ if ("on".equalsIgnoreCase(arg)) { ++ Timings.setTimingsEnabled(true); ++ sender.sendMessage(text("Enabled Timings & Reset")); ++ return true; ++ } else if ("off".equalsIgnoreCase(arg)) { ++ Timings.setTimingsEnabled(false); ++ sender.sendMessage(text("Disabled Timings")); ++ return true; ++ } ++ ++ if (!Timings.isTimingsEnabled()) { ++ sender.sendMessage(text("Please enable timings by typing /timings on")); ++ return true; ++ } ++ ++ long now = System.currentTimeMillis(); ++ if ("verbon".equalsIgnoreCase(arg)) { ++ Timings.setVerboseTimingsEnabled(true); ++ sender.sendMessage(text("Enabled Verbose Timings")); ++ return true; ++ } else if ("verboff".equalsIgnoreCase(arg)) { ++ Timings.setVerboseTimingsEnabled(false); ++ sender.sendMessage(text("Disabled Verbose Timings")); ++ return true; ++ } else if ("reset".equalsIgnoreCase(arg)) { ++ if (now - lastResetAttempt < 30000) { ++ TimingsManager.reset(); ++ sender.sendMessage(text("Timings reset. Please wait 5-10 minutes before using /timings report.", NamedTextColor.RED)); ++ } else { ++ lastResetAttempt = now; ++ sender.sendMessage(text("WARNING: Timings v2 should not be reset. If you are experiencing lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds.", NamedTextColor.RED)); ++ } ++ } else if ( ++ "paste".equalsIgnoreCase(arg) || ++ "report".equalsIgnoreCase(arg) || ++ "get".equalsIgnoreCase(arg) || ++ "merged".equalsIgnoreCase(arg) || ++ "separate".equalsIgnoreCase(arg) ++ ) { ++ Timings.generateReport(sender); ++ } else { ++ sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); ++ } ++ return true; ++ } ++ ++ @NotNull ++ @Override ++ public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { ++ Preconditions.checkNotNull(sender, "Sender cannot be null"); ++ Preconditions.checkNotNull(args, "Arguments cannot be null"); ++ Preconditions.checkNotNull(alias, "Alias cannot be null"); ++ ++ if (args.length == 1) { ++ return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, ++ new ArrayList(TIMINGS_SUBCOMMANDS.size())); ++ } ++ return ImmutableList.of(); ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e72ad05abada04426e32a73d02b21cb69079d268 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsManager.java +@@ -0,0 +1,192 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import co.aikar.util.LoadingMap; ++import com.google.common.collect.EvictingQueue; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.java.PluginClassLoader; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.logging.Level; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public final class TimingsManager { ++ static final Map TIMING_MAP = LoadingMap.of( ++ new ConcurrentHashMap<>(4096, .5F), TimingHandler::new ++ ); ++ public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler(); ++ public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK); ++ public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins"); ++ public static String url = "https://timings.aikar.co/"; ++ public static List hiddenConfigs = new ArrayList(); ++ public static boolean privacy = false; ++ ++ static final List HANDLERS = new ArrayList<>(1024); ++ static final List MINUTE_REPORTS = new ArrayList<>(64); ++ ++ static EvictingQueue HISTORY = EvictingQueue.create(12); ++ static long timingStart = 0; ++ static long historyStart = 0; ++ static boolean needsFullReset = false; ++ static boolean needsRecheckEnabled = false; ++ ++ private TimingsManager() {} ++ ++ /** ++ * Resets all timing data on the next tick ++ */ ++ static void reset() { ++ needsFullReset = true; ++ } ++ ++ /** ++ * Ticked every tick by CraftBukkit to count the number of times a timer ++ * caused TPS loss. ++ */ ++ static void tick() { ++ if (Timings.timingsEnabled) { ++ boolean violated = FULL_SERVER_TICK.isViolated(); ++ ++ for (TimingHandler handler : HANDLERS) { ++ if (handler.isSpecial()) { ++ // We manually call this ++ continue; ++ } ++ handler.processTick(violated); ++ } ++ ++ TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size(); ++ TimingHistory.timedTicks++; ++ // Generate TPS/Ping/Tick reports every minute ++ } ++ } ++ static void stopServer() { ++ Timings.timingsEnabled = false; ++ recheckEnabled(); ++ } ++ static void recheckEnabled() { ++ synchronized (TIMING_MAP) { ++ for (TimingHandler timings : TIMING_MAP.values()) { ++ timings.checkEnabled(); ++ } ++ } ++ needsRecheckEnabled = false; ++ } ++ static void resetTimings() { ++ if (needsFullReset) { ++ // Full resets need to re-check every handlers enabled state ++ // Timing map can be modified from async so we must sync on it. ++ synchronized (TIMING_MAP) { ++ for (TimingHandler timings : TIMING_MAP.values()) { ++ timings.reset(true); ++ } ++ } ++ Bukkit.getLogger().log(Level.INFO, "Timings Reset"); ++ HISTORY.clear(); ++ needsFullReset = false; ++ needsRecheckEnabled = false; ++ timingStart = System.currentTimeMillis(); ++ } else { ++ // Soft resets only need to act on timings that have done something ++ // Handlers can only be modified on main thread. ++ for (TimingHandler timings : HANDLERS) { ++ timings.reset(false); ++ } ++ } ++ ++ HANDLERS.clear(); ++ MINUTE_REPORTS.clear(); ++ ++ TimingHistory.resetTicks(true); ++ historyStart = System.currentTimeMillis(); ++ } ++ ++ @NotNull ++ static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) { ++ return TIMING_MAP.get(new TimingIdentifier(group, name, parent)); ++ } ++ ++ ++ /** ++ *

      Due to access restrictions, we need a helper method to get a Command TimingHandler with String group

      ++ * ++ * Plugins should never call this ++ * ++ * @param pluginName Plugin this command is associated with ++ * @param command Command to get timings for ++ * @return TimingHandler ++ */ ++ @NotNull ++ public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) { ++ Plugin plugin = null; ++ final Server server = Bukkit.getServer(); ++ if (!( server == null || pluginName == null || ++ "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || ++ "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) ++ )) { ++ plugin = server.getPluginManager().getPlugin(pluginName); ++ } ++ if (plugin == null) { ++ // Plugin is passing custom fallback prefix, try to look up by class loader ++ plugin = getPluginByClassloader(command.getClass()); ++ } ++ if (plugin == null) { ++ return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName()); ++ } ++ ++ return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName()); ++ } ++ ++ /** ++ * Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the ++ * Plugin that created this class. ++ * ++ * @param clazz Class to check ++ * @return Plugin if created by a plugin ++ */ ++ @Nullable ++ public static Plugin getPluginByClassloader(@Nullable Class clazz) { ++ if (clazz == null) { ++ return null; ++ } ++ final ClassLoader classLoader = clazz.getClassLoader(); ++ if (classLoader instanceof PluginClassLoader) { ++ PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader; ++ return pluginClassLoader.getPlugin(); ++ } ++ return null; ++ } ++} +diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..df066d6f8d55afbc0c1897c486d638657a5f8df9 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/TimingsReportListener.java +@@ -0,0 +1,90 @@ ++package co.aikar.timings; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.Lists; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.ConsoleCommandSender; ++import org.bukkit.command.MessageCommandSender; ++import org.bukkit.command.RemoteConsoleCommandSender; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.List; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++@SuppressWarnings("WeakerAccess") ++public class TimingsReportListener implements net.kyori.adventure.audience.ForwardingAudience, MessageCommandSender { ++ private final List senders; ++ private final Runnable onDone; ++ private String timingsURL; ++ ++ public TimingsReportListener(@NotNull CommandSender senders) { ++ this(senders, null); ++ } ++ public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) { ++ this(Lists.newArrayList(sender), onDone); ++ } ++ public TimingsReportListener(@NotNull List senders) { ++ this(senders, null); ++ } ++ public TimingsReportListener(@NotNull List senders, @Nullable Runnable onDone) { ++ Preconditions.checkNotNull(senders); ++ Preconditions.checkArgument(!senders.isEmpty(), "senders is empty"); ++ ++ this.senders = Lists.newArrayList(senders); ++ this.onDone = onDone; ++ } ++ ++ @Nullable ++ public String getTimingsURL() { ++ return timingsURL; ++ } ++ ++ public void done() { ++ done(null); ++ } ++ ++ public void done(@Nullable String url) { ++ this.timingsURL = url; ++ if (onDone != null) { ++ onDone.run(); ++ } ++ for (CommandSender sender : senders) { ++ if (sender instanceof TimingsReportListener) { ++ ((TimingsReportListener) sender).done(); ++ } ++ } ++ } ++ ++ @Override ++ public void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ net.kyori.adventure.audience.ForwardingAudience.super.sendMessage(source, message, type); ++ } ++ ++ @NotNull ++ @Override ++ public Iterable audiences() { ++ return this.senders; ++ } ++ ++ @Override ++ public void sendMessage(@NotNull String message) { ++ senders.forEach((sender) -> sender.sendMessage(message)); ++ } ++ ++ public void addConsoleIfNeeded() { ++ boolean hasConsole = false; ++ for (CommandSender sender : this.senders) { ++ if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) { ++ hasConsole = true; ++ } ++ } ++ if (!hasConsole) { ++ this.senders.add(Bukkit.getConsoleSender()); ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/timings/UnsafeTimingHandler.java b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..632c4961515f5052551f841cfa840e60bba7a257 +--- /dev/null ++++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java +@@ -0,0 +1,53 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.timings; ++ ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.NotNull; ++ ++class UnsafeTimingHandler extends TimingHandler { ++ ++ UnsafeTimingHandler(@NotNull TimingIdentifier id) { ++ super(id); ++ } ++ ++ private static void checkThread() { ++ if (!Bukkit.isPrimaryThread()) { ++ throw new IllegalStateException("Calling Timings from Async Operation"); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public Timing startTiming() { ++ checkThread(); ++ return super.startTiming(); ++ } ++ ++ @Override ++ public void stopTiming() { ++ checkThread(); ++ super.stopTiming(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/Counter.java b/src/main/java/co/aikar/util/Counter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dae84243804b4b076cafb3e1b29bdcf614efc93f +--- /dev/null ++++ b/src/main/java/co/aikar/util/Counter.java +@@ -0,0 +1,39 @@ ++package co.aikar.util; ++ ++import com.google.common.collect.ForwardingMap; ++ ++import java.util.HashMap; ++import java.util.Map; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++@Deprecated(forRemoval = true) ++public class Counter extends ForwardingMap { ++ private final Map counts = new HashMap<>(); ++ ++ public long decrement(@Nullable T key) { ++ return increment(key, -1); ++ } ++ public long increment(@Nullable T key) { ++ return increment(key, 1); ++ } ++ public long decrement(@Nullable T key, long amount) { ++ return increment(key, -amount); ++ } ++ public long increment(@Nullable T key, long amount) { ++ Long count = this.getCount(key); ++ count += amount; ++ this.counts.put(key, count); ++ return count; ++ } ++ ++ public long getCount(@Nullable T key) { ++ return this.counts.getOrDefault(key, 0L); ++ } ++ ++ @NotNull ++ @Override ++ protected Map delegate() { ++ return this.counts; ++ } ++} +diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c105a1429ca58b37be265708ec345e00f0d43ed8 +--- /dev/null ++++ b/src/main/java/co/aikar/util/JSONUtil.java +@@ -0,0 +1,141 @@ ++package co.aikar.util; ++ ++import com.google.common.base.Function; ++import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.json.simple.JSONArray; ++import org.json.simple.JSONObject; ++ ++import java.util.ArrayList; ++import java.util.LinkedHashMap; ++import java.util.List; ++import java.util.Map; ++ ++/** ++ * Provides Utility methods that assist with generating JSON Objects ++ */ ++@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++@Deprecated(forRemoval = true) ++public final class JSONUtil { ++ private JSONUtil() {} ++ ++ /** ++ * Creates a key/value "JSONPair" object ++ * ++ * @param key Key to use ++ * @param obj Value to use ++ * @return JSONPair ++ */ ++ @NotNull ++ public static JSONPair pair(@NotNull String key, @Nullable Object obj) { ++ return new JSONPair(key, obj); ++ } ++ ++ @NotNull ++ public static JSONPair pair(long key, @Nullable Object obj) { ++ return new JSONPair(String.valueOf(key), obj); ++ } ++ ++ /** ++ * Creates a new JSON object from multiple JSONPair key/value pairs ++ * ++ * @param data JSONPairs ++ * @return Map ++ */ ++ @NotNull ++ public static Map createObject(@NotNull JSONPair... data) { ++ return appendObjectData(new LinkedHashMap(), data); ++ } ++ ++ /** ++ * This appends multiple key/value Obj pairs into a JSON Object ++ * ++ * @param parent Map to be appended to ++ * @param data Data to append ++ * @return Map ++ */ ++ @NotNull ++ public static Map appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) { ++ for (JSONPair JSONPair : data) { ++ parent.put(JSONPair.key, JSONPair.val); ++ } ++ return parent; ++ } ++ ++ /** ++ * This builds a JSON array from a set of data ++ * ++ * @param data Data to build JSON array from ++ * @return List ++ */ ++ @NotNull ++ public static List toArray(@NotNull Object... data) { ++ return Lists.newArrayList(data); ++ } ++ ++ /** ++ * These help build a single JSON array using a mapper function ++ * ++ * @param collection Collection to apply to ++ * @param mapper Mapper to apply ++ * @param Element Type ++ * @return List ++ */ ++ @NotNull ++ public static List toArrayMapper(@NotNull E[] collection, @NotNull Function mapper) { ++ return toArrayMapper(Lists.newArrayList(collection), mapper); ++ } ++ ++ @NotNull ++ public static List toArrayMapper(@NotNull Iterable collection, @NotNull Function mapper) { ++ List array = Lists.newArrayList(); ++ for (E e : collection) { ++ Object object = mapper.apply(e); ++ if (object != null) { ++ array.add(object); ++ } ++ } ++ return array; ++ } ++ ++ /** ++ * These help build a single JSON Object from a collection, using a mapper function ++ * ++ * @param collection Collection to apply to ++ * @param mapper Mapper to apply ++ * @param Element Type ++ * @return Map ++ */ ++ @NotNull ++ public static Map toObjectMapper(@NotNull E[] collection, @NotNull Function mapper) { ++ return toObjectMapper(Lists.newArrayList(collection), mapper); ++ } ++ ++ @NotNull ++ public static Map toObjectMapper(@NotNull Iterable collection, @NotNull Function mapper) { ++ Map object = Maps.newLinkedHashMap(); ++ for (E e : collection) { ++ JSONPair JSONPair = mapper.apply(e); ++ if (JSONPair != null) { ++ object.put(JSONPair.key, JSONPair.val); ++ } ++ } ++ return object; ++ } ++ ++ /** ++ * Simply stores a key and a value, used internally by many methods below. ++ */ ++ @SuppressWarnings("PublicInnerClass") ++ public static class JSONPair { ++ final String key; ++ final Object val; ++ ++ JSONPair(@NotNull String key, @NotNull Object val) { ++ this.key = key; ++ this.val = val; ++ } ++ } ++} +diff --git a/src/main/java/co/aikar/util/LoadingIntMap.java b/src/main/java/co/aikar/util/LoadingIntMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5753b9bce89db2ac378ec41f1b61907cc2e23335 +--- /dev/null ++++ b/src/main/java/co/aikar/util/LoadingIntMap.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2015. Starlis LLC / dba Empire Minecraft ++ * ++ * This source code is proprietary software and must not be redistributed without Starlis LLC's approval ++ * ++ */ ++package co.aikar.util; ++ ++ ++import com.google.common.base.Function; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows you to pass a Loader function that when a key is accessed that doesn't exist, ++ * automatically loads the entry into the map by calling the loader Function. ++ * ++ * .get() Will only return null if the Loader can return null. ++ * ++ * You may pass any backing Map to use. ++ * ++ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. ++ * ++ * Do not wrap the backing map with Collections.synchronizedMap. ++ * ++ * @param Value ++ */ ++@Deprecated(forRemoval = true) ++public class LoadingIntMap extends Int2ObjectOpenHashMap { ++ private final Function loader; ++ ++ public LoadingIntMap(@NotNull Function loader) { ++ super(); ++ this.loader = loader; ++ } ++ ++ public LoadingIntMap(int expectedSize, @NotNull Function loader) { ++ super(expectedSize); ++ this.loader = loader; ++ } ++ ++ public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function loader) { ++ super(expectedSize, loadFactor); ++ this.loader = loader; ++ } ++ ++ ++ @Nullable ++ @Override ++ public V get(int key) { ++ V res = super.get(key); ++ if (res == null) { ++ res = loader.apply(key); ++ if (res != null) { ++ put(key, res); ++ } ++ } ++ return res; ++ } ++ ++ /** ++ * Due to java stuff, you will need to cast it to (Function) for some cases ++ * ++ * @param Type ++ */ ++ public abstract static class Feeder implements Function { ++ @Nullable ++ @Override ++ public T apply(@Nullable Object input) { ++ return apply(); ++ } ++ ++ @Nullable ++ public abstract T apply(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1786eeb5cbeaad75602c9c5649bbcd9b2af5cf81 +--- /dev/null ++++ b/src/main/java/co/aikar/util/LoadingMap.java +@@ -0,0 +1,369 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.util; ++ ++import com.google.common.base.Preconditions; ++import java.lang.reflect.Constructor; ++import java.util.AbstractMap; ++import java.util.Collection; ++import java.util.HashMap; ++import java.util.IdentityHashMap; ++import java.util.Map; ++import java.util.Set; ++import java.util.function.Function; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Allows you to pass a Loader function that when a key is accessed that doesn't exists, ++ * automatically loads the entry into the map by calling the loader Function. ++ * ++ * .get() Will only return null if the Loader can return null. ++ * ++ * You may pass any backing Map to use. ++ * ++ * This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed. ++ * ++ * Do not wrap the backing map with Collections.synchronizedMap. ++ * ++ * @param Key ++ * @param Value ++ */ ++@Deprecated(forRemoval = true) ++public class LoadingMap extends AbstractMap { ++ private final Map backingMap; ++ private final java.util.function.Function loader; ++ ++ /** ++ * Initializes an auto loading map using specified loader and backing map ++ * @param backingMap Map to wrap ++ * @param loader Loader ++ */ ++ public LoadingMap(@NotNull Map backingMap, @NotNull java.util.function.Function loader) { ++ this.backingMap = backingMap; ++ this.loader = loader; ++ } ++ ++ /** ++ * Creates a new LoadingMap with the specified map and loader ++ * ++ * @param backingMap Actual map being used. ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map of(@NotNull Map backingMap, @NotNull Function loader) { ++ return new LoadingMap<>(backingMap, loader); ++ } ++ ++ /** ++ * Creates a LoadingMap with an auto instantiating loader. ++ * ++ * Will auto construct class of of Value when not found ++ * ++ * Since this uses Reflection, It is more effecient to define your own static loader ++ * than using this helper, but if performance is not critical, this is easier. ++ * ++ * @param backingMap Actual map being used. ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newAutoMap(@NotNull Map backingMap, @Nullable final Class keyClass, ++ @NotNull final Class valueClass) { ++ return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass)); ++ } ++ /** ++ * Creates a LoadingMap with an auto instantiating loader. ++ * ++ * Will auto construct class of of Value when not found ++ * ++ * Since this uses Reflection, It is more effecient to define your own static loader ++ * than using this helper, but if performance is not critical, this is easier. ++ * ++ * @param backingMap Actual map being used. ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newAutoMap(@NotNull Map backingMap, ++ @NotNull final Class valueClass) { ++ return newAutoMap(backingMap, null, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass) { ++ return newAutoMap(new HashMap<>(), keyClass, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param valueClass Class used for the V generic ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@NotNull final Class valueClass) { ++ return newHashAutoMap(null, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param keyClass Class used for the K generic ++ * @param valueClass Class used for the V generic ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@Nullable final Class keyClass, @NotNull final Class valueClass, int initialCapacity, float loadFactor) { ++ return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass); ++ } ++ ++ /** ++ * @see #newAutoMap ++ * ++ * new Auto initializing map using a HashMap. ++ * ++ * @param valueClass Class used for the V generic ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map that auto instantiates on .get() ++ */ ++ @NotNull ++ public static Map newHashAutoMap(@NotNull final Class valueClass, int initialCapacity, float loadFactor) { ++ return newHashAutoMap(null, valueClass, initialCapacity, loadFactor); ++ } ++ ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader) { ++ return new LoadingMap<>(new HashMap<>(), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader, int initialCapacity) { ++ return new LoadingMap<>(new HashMap<>(initialCapacity), loader); ++ } ++ /** ++ * Initializes an auto loading map using a HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param loadFactor Load factor to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newHashMap(@NotNull Function loader, int initialCapacity, float loadFactor) { ++ return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using an Identity HashMap ++ * ++ * @param loader Loader to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newIdentityHashMap(@NotNull Function loader) { ++ return new LoadingMap<>(new IdentityHashMap<>(), loader); ++ } ++ ++ /** ++ * Initializes an auto loading map using an Identity HashMap ++ * ++ * @param loader Loader to use ++ * @param initialCapacity Initial capacity to use ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map newIdentityHashMap(@NotNull Function loader, int initialCapacity) { ++ return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader); ++ } ++ ++ @Override ++ public int size() {return backingMap.size();} ++ ++ @Override ++ public boolean isEmpty() {return backingMap.isEmpty();} ++ ++ @Override ++ public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);} ++ ++ @Override ++ public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);} ++ ++ @Nullable ++ @Override ++ public V get(@Nullable Object key) { ++ V v = backingMap.get(key); ++ if (v != null) { ++ return v; ++ } ++ return backingMap.computeIfAbsent((K) key, loader); ++ } ++ ++ @Nullable ++ public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);} ++ ++ @Nullable ++ @Override ++ public V remove(@Nullable Object key) {return backingMap.remove(key);} ++ ++ public void putAll(@NotNull Map m) {backingMap.putAll(m);} ++ ++ @Override ++ public void clear() {backingMap.clear();} ++ ++ @NotNull ++ @Override ++ public Set keySet() {return backingMap.keySet();} ++ ++ @NotNull ++ @Override ++ public Collection values() {return backingMap.values();} ++ ++ @Override ++ public boolean equals(@Nullable Object o) {return backingMap.equals(o);} ++ ++ @Override ++ public int hashCode() {return backingMap.hashCode();} ++ ++ @NotNull ++ @Override ++ public Set> entrySet() { ++ return backingMap.entrySet(); ++ } ++ ++ @NotNull ++ public LoadingMap clone() { ++ return new LoadingMap<>(backingMap, loader); ++ } ++ ++ private static class AutoInstantiatingLoader implements Function { ++ final Constructor constructor; ++ private final Class valueClass; ++ ++ AutoInstantiatingLoader(@Nullable Class keyClass, @NotNull Class valueClass) { ++ try { ++ this.valueClass = valueClass; ++ if (keyClass != null) { ++ constructor = valueClass.getConstructor(keyClass); ++ } else { ++ constructor = null; ++ } ++ } catch (NoSuchMethodException e) { ++ throw new IllegalStateException( ++ valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null)); ++ } ++ } ++ ++ @NotNull ++ @Override ++ public V apply(@Nullable K input) { ++ try { ++ return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance()); ++ } catch (Exception e) { ++ throw new ExceptionInInitializerError(e); ++ } ++ } ++ ++ @Override ++ public int hashCode() { ++ return super.hashCode(); ++ } ++ ++ @Override ++ public boolean equals(Object object) { ++ return false; ++ } ++ } ++ ++ /** ++ * Due to java stuff, you will need to cast it to (Function) for some cases ++ * ++ * @param Type ++ */ ++ public abstract static class Feeder implements Function { ++ @Nullable ++ @Override ++ public T apply(@Nullable Object input) { ++ return apply(); ++ } ++ ++ @Nullable ++ public abstract T apply(); ++ } ++} +diff --git a/src/main/java/co/aikar/util/MRUMapCache.java b/src/main/java/co/aikar/util/MRUMapCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3e61a926620a67daec3af54b72a1b911eaef2ed4 +--- /dev/null ++++ b/src/main/java/co/aikar/util/MRUMapCache.java +@@ -0,0 +1,112 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ ++package co.aikar.util; ++ ++import java.util.AbstractMap; ++import java.util.Collection; ++import java.util.Map; ++import java.util.Set; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result. ++ * ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ */ ++@Deprecated(forRemoval = true) ++public class MRUMapCache extends AbstractMap { ++ final Map backingMap; ++ Object cacheKey; ++ V cacheValue; ++ public MRUMapCache(@NotNull final Map backingMap) { ++ this.backingMap = backingMap; ++ } ++ ++ public int size() {return backingMap.size();} ++ ++ public boolean isEmpty() {return backingMap.isEmpty();} ++ ++ public boolean containsKey(@Nullable Object key) { ++ return key != null && key.equals(cacheKey) || backingMap.containsKey(key); ++ } ++ ++ public boolean containsValue(@Nullable Object value) { ++ return value != null && value == cacheValue || backingMap.containsValue(value); ++ } ++ ++ @Nullable ++ public V get(@Nullable Object key) { ++ if (cacheKey != null && cacheKey.equals(key)) { ++ return cacheValue; ++ } ++ cacheKey = key; ++ return cacheValue = backingMap.get(key); ++ } ++ ++ @Nullable ++ public V put(@Nullable K key, @Nullable V value) { ++ cacheKey = key; ++ return cacheValue = backingMap.put(key, value); ++ } ++ ++ @Nullable ++ public V remove(@Nullable Object key) { ++ if (key != null && key.equals(cacheKey)) { ++ cacheKey = null; ++ } ++ return backingMap.remove(key); ++ } ++ ++ public void putAll(@NotNull Map m) {backingMap.putAll(m);} ++ ++ public void clear() { ++ cacheKey = null; ++ cacheValue = null; ++ backingMap.clear(); ++ } ++ ++ @NotNull ++ public Set keySet() {return backingMap.keySet();} ++ ++ @NotNull ++ public Collection values() {return backingMap.values();} ++ ++ @NotNull ++ public Set> entrySet() {return backingMap.entrySet();} ++ ++ /** ++ * Wraps the specified map with a most recently used cache ++ * ++ * @param map Map to be wrapped ++ * @param Key Type of the Map ++ * @param Value Type of the Map ++ * @return Map ++ */ ++ @NotNull ++ public static Map of(@NotNull Map map) { ++ return new MRUMapCache(map); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 6391011464ac0c95d4da7fb9c698f35c58b40922..a327c71f110fc0330a3a43ab118565d35801eb32 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -870,7 +870,6 @@ public final class Bukkit { + */ + public static void reload() { + server.reload(); +- org.spigotmc.CustomTimingsHandler.reload(); // Spigot + } + + /** +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 01f8e0811f8b337acac31819a85bb44b189b3c21..a1bffe44764fc3e1bb96bf014c56025b0bde7507 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1978,6 +1978,26 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + throw new UnsupportedOperationException("Not supported yet."); + } + ++ // Paper start ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig() ++ { ++ throw new UnsupportedOperationException( "Not supported yet." ); ++ } ++ ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getPaperConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Paper end ++ + /** + * Sends the component to the player + * +diff --git a/src/main/java/org/bukkit/command/BufferedCommandSender.java b/src/main/java/org/bukkit/command/BufferedCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..45ed63797b13e114bf3795c80a6c3967d8eb2351 +--- /dev/null ++++ b/src/main/java/org/bukkit/command/BufferedCommandSender.java +@@ -0,0 +1,25 @@ ++package org.bukkit.command; ++ ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public class BufferedCommandSender implements MessageCommandSender { ++ private final StringBuffer buffer = new StringBuffer(); ++ @Override ++ public void sendMessage(@NotNull String message) { ++ buffer.append(message); ++ buffer.append("\n"); ++ } ++ ++ @NotNull ++ public String getBuffer() { ++ return buffer.toString(); ++ } ++ ++ public void reset() { ++ this.buffer.setLength(0); ++ } ++} +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index 6686d025222dc50156347a1757c88da02f882eec..cee16db367907cfa4b432dc6969f403321a855ea 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -33,7 +33,16 @@ public abstract class Command { + protected String usageMessage; + private String permission; + private net.kyori.adventure.text.Component permissionMessage; // Paper +- public org.spigotmc.CustomTimingsHandler timings; // Spigot ++ /** ++ * @deprecated Timings will be removed in the future ++ */ ++ @Deprecated(forRemoval = true) ++ public co.aikar.timings.Timing timings; // Paper ++ /** ++ * @deprecated Timings will be removed in the future ++ */ ++ @Deprecated(forRemoval = true) ++ @NotNull public String getTimingName() {return getName();} // Paper + + protected Command(@NotNull String name) { + this(name, "", "/" + name, new ArrayList()); +@@ -47,7 +56,6 @@ public abstract class Command { + this.usageMessage = (usageMessage == null) ? "/" + name : usageMessage; + this.aliases = aliases; + this.activeAliases = new ArrayList(aliases); +- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + } + + /** +@@ -245,7 +253,6 @@ public abstract class Command { + } + this.nextLabel = name; + if (!isRegistered()) { +- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot + this.label = name; + return true; + } +diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +index d6c8938b1e13b63116b7b0e074ea8ef5997f8dc3..a6ad94ef98a1df1d2842635d850bc990b0137849 100644 +--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java ++++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java +@@ -9,6 +9,7 @@ public class FormattedCommandAlias extends Command { + + public FormattedCommandAlias(@NotNull String alias, @NotNull String[] formatStrings) { + super(alias); ++ timings = co.aikar.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot + this.formatStrings = formatStrings; + } + +@@ -113,6 +114,10 @@ public class FormattedCommandAlias extends Command { + return formatString; + } + ++ @NotNull ++ @Override // Paper ++ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Paper ++ + private static boolean inRange(int i, int j, int k) { + return i >= j && i <= k; + } +diff --git a/src/main/java/org/bukkit/command/MessageCommandSender.java b/src/main/java/org/bukkit/command/MessageCommandSender.java +new file mode 100644 +index 0000000000000000000000000000000000000000..946d2f0ef37c6cf895caf8d3c6963c7889e0567b +--- /dev/null ++++ b/src/main/java/org/bukkit/command/MessageCommandSender.java +@@ -0,0 +1,138 @@ ++package org.bukkit.command; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionAttachment; ++import org.bukkit.permissions.PermissionAttachmentInfo; ++import org.bukkit.plugin.Plugin; ++ ++import java.util.Set; ++import java.util.UUID; ++ ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * For when all you care about is just messaging ++ * ++ * @deprecated Timings will be removed in the future ++ */ ++@Deprecated(forRemoval = true) ++public interface MessageCommandSender extends CommandSender { ++ ++ @Override ++ default void sendMessage(@NotNull String[] messages) { ++ for (String message : messages) { ++ sendMessage(message); ++ } ++ } ++ ++ @Override ++ default void sendMessage(@Nullable UUID sender, @NotNull String message) { ++ sendMessage(message); ++ } ++ ++ @Override ++ default void sendMessage(@Nullable UUID sender, @NotNull String[] messages) { ++ for (String message : messages) { ++ sendMessage(message); ++ } ++ } ++ ++ @NotNull ++ @Override ++ default Server getServer() { ++ return Bukkit.getServer(); ++ } ++ ++ // Paper start ++ @Override ++ default net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component name() { ++ throw new UnsupportedOperationException(); ++ } ++ // Paper end ++ ++ @NotNull ++ @Override ++ default String getName() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default boolean isOp() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default void setOp(boolean value) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default boolean isPermissionSet(@NotNull String name) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default boolean isPermissionSet(@NotNull Permission perm) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default boolean hasPermission(@NotNull String name) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default boolean hasPermission(@NotNull Permission perm) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default void removeAttachment(@NotNull PermissionAttachment attachment) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ default void recalculatePermissions() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default Set getEffectivePermissions() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @NotNull ++ @Override ++ default Spigot spigot() { ++ throw new UnsupportedOperationException(); ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index 9207ae900cb4cc8ce41dd4e63d7ad8b35b0ac048..36fc2c35395c72f8b81a2a2f3265fd205384ce26 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -16,7 +16,6 @@ import org.bukkit.command.defaults.BukkitCommand; + import org.bukkit.command.defaults.HelpCommand; + import org.bukkit.command.defaults.PluginsCommand; + import org.bukkit.command.defaults.ReloadCommand; +-import org.bukkit.command.defaults.TimingsCommand; + import org.bukkit.command.defaults.VersionCommand; + import org.bukkit.entity.Player; + import org.bukkit.util.StringUtil; +@@ -36,7 +35,7 @@ public class SimpleCommandMap implements CommandMap { + register("bukkit", new VersionCommand("version")); + register("bukkit", new ReloadCommand("reload")); + //register("bukkit", new PluginsCommand("plugins")); // Paper +- register("bukkit", new TimingsCommand("timings")); ++ register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper + } + + public void setFallbackCommands() { +@@ -68,6 +67,7 @@ public class SimpleCommandMap implements CommandMap { + */ + @Override + public boolean register(@NotNull String label, @NotNull String fallbackPrefix, @NotNull Command command) { ++ command.timings = co.aikar.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Paper + label = label.toLowerCase(Locale.ROOT).trim(); + fallbackPrefix = fallbackPrefix.toLowerCase(Locale.ROOT).trim(); + boolean registered = register(label, command, false, fallbackPrefix); +@@ -144,16 +144,22 @@ public class SimpleCommandMap implements CommandMap { + return false; + } + ++ // Paper start - Plugins do weird things to workaround normal registration ++ if (target.timings == null) { ++ target.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, target); ++ } ++ // Paper end ++ + try { +- target.timings.startTiming(); // Spigot ++ try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources + // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) + target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); +- target.timings.stopTiming(); // Spigot ++ } // target.timings.stopTiming(); // Spigot // Paper + } catch (CommandException ex) { +- target.timings.stopTiming(); // Spigot ++ //target.timings.stopTiming(); // Spigot // Paper + throw ex; + } catch (Throwable ex) { +- target.timings.stopTiming(); // Spigot ++ //target.timings.stopTiming(); // Spigot // Paper + throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); + } + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +deleted file mode 100644 +index 516d7fc7812aac343782861d0d567f54aa578c2a..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ /dev/null +@@ -1,250 +0,0 @@ +-package org.bukkit.command.defaults; +- +-import com.google.common.base.Preconditions; +-import com.google.common.collect.ImmutableList; +-import java.io.File; +-import java.io.IOException; +-import java.io.PrintStream; +-import java.util.ArrayList; +-import java.util.List; +-import org.bukkit.Bukkit; +-import org.bukkit.ChatColor; +-import org.bukkit.command.CommandSender; +-import org.bukkit.event.Event; +-import org.bukkit.event.HandlerList; +-import org.bukkit.plugin.Plugin; +-import org.bukkit.plugin.RegisteredListener; +-import org.bukkit.plugin.TimedRegisteredListener; +-import org.bukkit.util.StringUtil; +-import org.jetbrains.annotations.NotNull; +- +-// Spigot start +-// CHECKSTYLE:OFF +-import java.io.ByteArrayOutputStream; +-import java.io.OutputStream; +-import java.net.HttpURLConnection; +-import java.net.URL; +-import java.util.logging.Level; +-import org.bukkit.command.RemoteConsoleCommandSender; +-import org.bukkit.plugin.SimplePluginManager; +-import org.spigotmc.CustomTimingsHandler; +-// CHECKSTYLE:ON +-// Spigot end +- +-public class TimingsCommand extends BukkitCommand { +- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot +- public static long timingStart = 0; // Spigot +- +- public TimingsCommand(@NotNull String name) { +- super(name); +- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot +- this.usageMessage = "/timings "; // Spigot +- this.setPermission("bukkit.command.timings"); +- } +- +- // Spigot start - redesigned Timings Command +- public void executeSpigotTimings(@NotNull CommandSender sender, @NotNull String[] args) { +- if ("on".equals(args[0])) { +- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(true); +- CustomTimingsHandler.reload(); +- sender.sendMessage("Enabled Timings & Reset"); +- return; +- } else if ("off".equals(args[0])) { +- ((SimplePluginManager) Bukkit.getPluginManager()).useTimings(false); +- sender.sendMessage("Disabled Timings"); +- return; +- } +- +- if (!Bukkit.getPluginManager().useTimings()) { +- sender.sendMessage("Please enable timings by typing /timings on"); +- return; +- } +- +- boolean paste = "paste".equals(args[0]); +- if ("reset".equals(args[0])) { +- CustomTimingsHandler.reload(); +- sender.sendMessage("Timings reset"); +- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { +- long sampleTime = System.nanoTime() - timingStart; +- int index = 0; +- File timingFolder = new File("timings"); +- timingFolder.mkdirs(); +- File timings = new File(timingFolder, "timings.txt"); +- ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; +- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); +- PrintStream fileTimings = null; +- try { +- fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); +- +- CustomTimingsHandler.printTimings(fileTimings); +- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)"); +- +- fileTimings.println(""); +- fileTimings.println(Bukkit.spigot().getConfig().saveToString()); +- fileTimings.println(""); +- +- if (paste) { +- new PasteThread(sender, bout).start(); +- return; +- } +- +- sender.sendMessage("Timings written to " + timings.getPath()); +- sender.sendMessage("Paste contents of file into form at http://www.spigotmc.org/go/timings to read results."); +- +- } catch (IOException e) { +- } finally { +- if (fileTimings != null) { +- fileTimings.close(); +- } +- } +- } +- } +- // Spigot end +- +- @Override +- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { +- if (!testPermission(sender)) return true; +- if (args.length < 1) { // Spigot +- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); +- return false; +- } +- // Spigot start +- if (true) { +- executeSpigotTimings(sender, args); +- return true; +- } +- // Spigot end +- if (!sender.getServer().getPluginManager().useTimings()) { +- sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); +- return true; +- } +- +- boolean separate = "separate".equalsIgnoreCase(args[0]); +- if ("reset".equalsIgnoreCase(args[0])) { +- for (HandlerList handlerList : HandlerList.getHandlerLists()) { +- for (RegisteredListener listener : handlerList.getRegisteredListeners()) { +- if (listener instanceof TimedRegisteredListener) { +- ((TimedRegisteredListener) listener).reset(); +- } +- } +- } +- sender.sendMessage("Timings reset"); +- } else if ("merged".equalsIgnoreCase(args[0]) || separate) { +- +- int index = 0; +- int pluginIdx = 0; +- File timingFolder = new File("timings"); +- timingFolder.mkdirs(); +- File timings = new File(timingFolder, "timings.txt"); +- File names = null; +- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); +- PrintStream fileTimings = null; +- PrintStream fileNames = null; +- try { +- fileTimings = new PrintStream(timings); +- if (separate) { +- names = new File(timingFolder, "names" + index + ".txt"); +- fileNames = new PrintStream(names); +- } +- for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { +- pluginIdx++; +- long totalTime = 0; +- if (separate) { +- fileNames.println(pluginIdx + " " + plugin.getDescription().getFullName()); +- fileTimings.println("Plugin " + pluginIdx); +- } else { +- fileTimings.println(plugin.getDescription().getFullName()); +- } +- for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { +- if (listener instanceof TimedRegisteredListener) { +- TimedRegisteredListener trl = (TimedRegisteredListener) listener; +- long time = trl.getTotalTime(); +- int count = trl.getCount(); +- if (count == 0) continue; +- long avg = time / count; +- totalTime += time; +- Class eventClass = trl.getEventClass(); +- if (count > 0 && eventClass != null) { +- fileTimings.println(" " + eventClass.getSimpleName() + (trl.hasMultiple() ? " (and sub-classes)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); +- } +- } +- } +- fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); +- } +- sender.sendMessage("Timings written to " + timings.getPath()); +- if (separate) sender.sendMessage("Names written to " + names.getPath()); +- } catch (IOException e) { +- } finally { +- if (fileTimings != null) { +- fileTimings.close(); +- } +- if (fileNames != null) { +- fileNames.close(); +- } +- } +- } else { +- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); +- return false; +- } +- return true; +- } +- +- @NotNull +- @Override +- public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { +- Preconditions.checkArgument(sender != null, "Sender cannot be null"); +- Preconditions.checkArgument(args != null, "Arguments cannot be null"); +- Preconditions.checkArgument(alias != null, "Alias cannot be null"); +- +- if (args.length == 1) { +- return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS, new ArrayList(TIMINGS_SUBCOMMANDS.size())); +- } +- return ImmutableList.of(); +- } +- +- // Spigot start +- private static class PasteThread extends Thread { +- +- private final CommandSender sender; +- private final ByteArrayOutputStream bout; +- +- public PasteThread(@NotNull CommandSender sender, @NotNull ByteArrayOutputStream bout) { +- super("Timings paste thread"); +- this.sender = sender; +- this.bout = bout; +- } +- +- @Override +- public synchronized void start() { +- if (sender instanceof RemoteConsoleCommandSender) { +- run(); +- } else { +- super.start(); +- } +- } +- +- @Override +- public void run() { +- try { +- HttpURLConnection con = (HttpURLConnection) new URL("https://timings.spigotmc.org/paste").openConnection(); +- con.setDoOutput(true); +- con.setRequestMethod("POST"); +- con.setInstanceFollowRedirects(false); +- +- OutputStream out = con.getOutputStream(); +- out.write(bout.toByteArray()); +- out.close(); +- +- com.google.gson.JsonObject location = new com.google.gson.Gson().fromJson(new java.io.InputStreamReader(con.getInputStream()), com.google.gson.JsonObject.class); +- con.getInputStream().close(); +- +- String pasteID = location.get("key").getAsString(); +- sender.sendMessage(ChatColor.GREEN + "Timings results can be viewed at https://www.spigotmc.org/go/timings?url=" + pasteID); +- } catch (IOException ex) { +- sender.sendMessage(ChatColor.RED + "Error pasting timings, check your console for more information"); +- Bukkit.getServer().getLogger().log(Level.WARNING, "Could not paste timings", ex); +- } +- } +- } +- // Spigot end +-} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 64d32c377d0303ed28011a5f002274de3c16b383..a06daeeee71a5ca58fbc1e13453d9116eadbcac2 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2771,7 +2771,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + @Deprecated // Paper + public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { + throw new UnsupportedOperationException("Not supported yet."); ++ ++ } ++ ++ // Paper start ++ /** ++ * @return the player's ping ++ * @deprecated use {@link Player#getPing()} ++ */ ++ @Deprecated ++ public int getPing() { ++ throw new UnsupportedOperationException( "Not supported yet." ); + } ++ // Paper end + } + + @NotNull +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index d6f3c8da8bae1f70e0f9bee3e688a04801a3b546..b03f3e0ce9fdb0bb587cf1a1c10b8cfaa2eab09e 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -381,7 +381,6 @@ public final class SimplePluginManager implements PluginManager { + } + } + +- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot + return result.toArray(new Plugin[result.size()]); + } + +@@ -429,9 +428,9 @@ public final class SimplePluginManager implements PluginManager { + + if (result != null) { + plugins.add(result); +- lookupNames.put(result.getDescription().getName(), result); ++ lookupNames.put(result.getDescription().getName().toLowerCase(java.util.Locale.ENGLISH), result); // Paper + for (String provided : result.getDescription().getProvides()) { +- lookupNames.putIfAbsent(provided, result); ++ lookupNames.putIfAbsent(provided.toLowerCase(java.util.Locale.ENGLISH), result); // Paper + } + } + +@@ -461,7 +460,7 @@ public final class SimplePluginManager implements PluginManager { + @Nullable + public synchronized Plugin getPlugin(@NotNull String name) { + if (true) {return this.paperPluginManager.getPlugin(name);} // Paper +- return lookupNames.get(name.replace(' ', '_')); ++ return lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper + } + + @Override +@@ -689,7 +688,8 @@ public final class SimplePluginManager implements PluginManager { + throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); + } + +- if (useTimings) { ++ executor = new co.aikar.timings.TimedEventExecutor(executor, plugin, null, event); // Paper ++ if (false) { // Spigot - RL handles useTimings check now // Paper + getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); + } else { + getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); +@@ -924,7 +924,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + public boolean useTimings() { + if (true) {return this.paperPluginManager.useTimings();} // Paper +- return useTimings; ++ return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot + } + + /** +@@ -932,8 +932,9 @@ public final class SimplePluginManager implements PluginManager { + * + * @param use True if per event timing code should be used + */ ++ @Deprecated(forRemoval = true) + public void useTimings(boolean use) { +- useTimings = use; ++ co.aikar.timings.Timings.setTimingsEnabled(use); // Paper + } + + // Paper start +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 70ac93d420d0a8528428a3d038a2ef6a86d2fddd..2e4a0a66151b358cc89d8eea26002f9fda16ee48 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -55,7 +55,6 @@ public final class JavaPluginLoader implements PluginLoader { + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; + private final List loaders = new CopyOnWriteArrayList(); + private final LibraryLoader libraryLoader; +- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot + + /** + * This class was not meant to be constructed explicitly +@@ -294,27 +293,21 @@ public final class JavaPluginLoader implements PluginLoader { + } + } + +- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName() + "(" + eventClass.getSimpleName() + ")", pluginParentTimer); // Spigot +- EventExecutor executor = new EventExecutor() { ++ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper + @Override +- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper + try { + if (!eventClass.isAssignableFrom(event.getClass())) { + return; + } +- // Spigot start +- boolean isAsync = event.isAsynchronous(); +- if (!isAsync) timings.startTiming(); + method.invoke(listener, event); +- if (!isAsync) timings.stopTiming(); +- // Spigot end + } catch (InvocationTargetException ex) { + throw new EventException(ex.getCause()); + } catch (Throwable t) { + throw new EventException(t); + } + } +- }; ++ }, plugin, method, eventClass); // Paper + if (false) { // Spigot - RL handles useTimings check now + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); + } else { +diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java +index 5ca863b3692b2e1b58e7fb4d82f554a92cc4f01e..612958a331575d1da2715531ebdf6b1168f2e860 100644 +--- a/src/main/java/org/bukkit/util/CachedServerIcon.java ++++ b/src/main/java/org/bukkit/util/CachedServerIcon.java +@@ -2,6 +2,7 @@ package org.bukkit.util; + + import org.bukkit.Server; + import org.bukkit.event.server.ServerListPingEvent; ++import org.jetbrains.annotations.Nullable; + + /** + * This is a cached version of a server-icon. It's internal representation +@@ -12,4 +13,9 @@ import org.bukkit.event.server.ServerListPingEvent; + * @see Server#loadServerIcon(java.io.File) + * @see ServerListPingEvent#setServerIcon(CachedServerIcon) + */ +-public interface CachedServerIcon {} ++public interface CachedServerIcon { ++ ++ @Nullable ++ public String getData(); // Paper ++ ++} +diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java +index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..12946bd55fcf7c40d39081779a7fa30049ee6165 100644 +--- a/src/main/java/org/spigotmc/CustomTimingsHandler.java ++++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java +@@ -1,137 +1,67 @@ ++/* ++ * This file is licensed under the MIT License (MIT). ++ * ++ * Copyright (c) 2014 Daniel Ennis ++ * ++ * 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. ++ */ + package org.spigotmc; + +-import java.io.PrintStream; +-import java.util.Queue; +-import java.util.concurrent.ConcurrentLinkedQueue; + import org.bukkit.Bukkit; +-import org.bukkit.World; +-import org.bukkit.command.defaults.TimingsCommand; + import org.jetbrains.annotations.NotNull; +-import org.jetbrains.annotations.Nullable; ++import org.bukkit.plugin.AuthorNagException; ++import co.aikar.timings.Timing; ++import co.aikar.timings.Timings; ++import co.aikar.timings.TimingsManager; ++ ++import java.lang.reflect.Method; ++import java.util.logging.Level; + + /** +- * Provides custom timing sections for /timings merged. ++ * This is here for legacy purposes incase any plugin used it. ++ * ++ * If you use this, migrate ASAP as this will be removed in the future! ++ * ++ * @deprecated ++ * @see co.aikar.timings.Timings#of + */ +-public class CustomTimingsHandler { +- +- private static Queue HANDLERS = new ConcurrentLinkedQueue(); +- /*========================================================================*/ +- private final String name; +- private final CustomTimingsHandler parent; +- private long count = 0; +- private long start = 0; +- private long timingDepth = 0; +- private long totalTime = 0; +- private long curTickTotal = 0; +- private long violations = 0; ++@Deprecated(forRemoval = true) ++public final class CustomTimingsHandler { ++ private final Timing handler; + + public CustomTimingsHandler(@NotNull String name) { +- this(name, null); +- } +- +- public CustomTimingsHandler(@NotNull String name, @Nullable CustomTimingsHandler parent) { +- this.name = name; +- this.parent = parent; +- HANDLERS.add(this); +- } +- +- /** +- * Prints the timings and extra data to the given stream. +- * +- * @param printStream output stream +- */ +- public static void printTimings(@NotNull PrintStream printStream) { +- printStream.println("Minecraft"); +- for (CustomTimingsHandler timings : HANDLERS) { +- long time = timings.totalTime; +- long count = timings.count; +- if (count == 0) { +- continue; +- } +- long avg = time / count; +- +- printStream.println(" " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations); +- } +- printStream.println("# Version " + Bukkit.getVersion()); +- int entities = 0; +- int livingEntities = 0; +- for (World world : Bukkit.getWorlds()) { +- entities += world.getEntities().size(); +- livingEntities += world.getLivingEntities().size(); +- } +- printStream.println("# Entities " + entities); +- printStream.println("# LivingEntities " + livingEntities); +- } +- +- /** +- * Resets all timings. +- */ +- public static void reload() { +- if (Bukkit.getPluginManager().useTimings()) { +- for (CustomTimingsHandler timings : HANDLERS) { +- timings.reset(); +- } +- } +- TimingsCommand.timingStart = System.nanoTime(); +- } +- +- /** +- * Ticked every tick by CraftBukkit to count the number of times a timer +- * caused TPS loss. +- */ +- public static void tick() { +- if (Bukkit.getPluginManager().useTimings()) { +- for (CustomTimingsHandler timings : HANDLERS) { +- if (timings.curTickTotal > 50000000) { +- timings.violations += Math.ceil(timings.curTickTotal / 50000000); +- } +- timings.curTickTotal = 0; +- timings.timingDepth = 0; // incase reset messes this up +- } +- } +- } ++ Timing timing; + +- /** +- * Starts timing to track a section of code. +- */ +- public void startTiming() { +- // If second condtion fails we are already timing +- if (Bukkit.getPluginManager().useTimings() && ++timingDepth == 1) { +- start = System.nanoTime(); +- if (parent != null && ++parent.timingDepth == 1) { +- parent.start = start; +- } ++ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); ++ try { ++ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); ++ ofSafe.setAccessible(true); ++ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); ++ timing = Timings.NULL_HANDLER; + } ++ handler = timing; + } + +- /** +- * Stops timing a section of code. +- */ +- public void stopTiming() { +- if (Bukkit.getPluginManager().useTimings()) { +- if (--timingDepth != 0 || start == 0) { +- return; +- } +- long diff = System.nanoTime() - start; +- totalTime += diff; +- curTickTotal += diff; +- count++; +- start = 0; +- if (parent != null) { +- parent.stopTiming(); +- } +- } +- } ++ public void startTiming() { handler.startTiming(); } ++ public void stopTiming() { handler.stopTiming(); } + +- /** +- * Reset this timer, setting all values to zero. +- */ +- public void reset() { +- count = 0; +- violations = 0; +- curTickTotal = 0; +- totalTime = 0; +- start = 0; +- timingDepth = 0; +- } + } diff --git a/patches/api/0012-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0012-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 000000000000..5a2340eb8fdf --- /dev/null +++ b/patches/api/0012-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Tue, 18 May 2021 14:42:26 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index a327c71f110fc0330a3a43ab118565d35801eb32..60ad479817c95aef809f73c6688cd6b2a0bb91df 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -83,6 +83,20 @@ public final class Bukkit { + return server; + } + ++ /** ++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, ++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. ++ * ++ *

      Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this ++ * directory manually when determining the location in which to store their data and configuration files.

      ++ * ++ * @return plugins directory ++ */ ++ @NotNull ++ public static File getPluginsFolder() { ++ return server.getPluginsFolder(); ++ } ++ + /** + * Attempts to set the {@link Server} singleton. + *

      +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a1bffe44764fc3e1bb96bf014c56025b0bde7507..f5005063c33d5e7ac030c4d43cb042c18c799284 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -68,6 +68,18 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper + ++ /** ++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, ++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. ++ * ++ *

      Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this ++ * directory manually when determining the location in which to store their data and configuration files.

      ++ * ++ * @return plugins directory ++ */ ++ @NotNull ++ File getPluginsFolder(); ++ + /** + * Used for all administrative messages, such as an operator using a + * command. +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index b03f3e0ce9fdb0bb587cf1a1c10b8cfaa2eab09e..48b66054913c8b53e6e7fd34615c2ab54727693f 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -117,9 +117,22 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Plugin[] loadPlugins(@NotNull File directory) { ++ // Paper start - extra jars ++ return this.loadPlugins(directory, java.util.Collections.emptyList()); ++ } ++ @NotNull ++ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) { ++ // Paper end + if (true) { + List pluginList = new ArrayList<>(); + java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory)); ++ for (File file : extraPluginJars) { ++ try { ++ pluginList.add(this.paperPluginManager.loadPlugin(file)); ++ } catch (Exception e) { ++ this.server.getLogger().log(Level.SEVERE, "Plugin loading error!", e); ++ } ++ } + return pluginList.toArray(new Plugin[0]); + } + Preconditions.checkArgument(directory != null, "Directory cannot be null"); +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 2e4a0a66151b358cc89d8eea26002f9fda16ee48..b412aaf08901d169ac9fc89b36f9d6ccb95c53d3 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -93,7 +93,7 @@ public final class JavaPluginLoader implements PluginLoader { + throw new InvalidPluginException(ex); + } + +- final File parentFile = file.getParentFile(); ++ final File parentFile = this.server.getPluginsFolder(); // Paper + final File dataFolder = new File(parentFile, description.getName()); + @SuppressWarnings("deprecation") + final File oldDataFolder = new File(parentFile, description.getRawName()); diff --git a/patches/api/0013-Player-affects-spawning-API.patch b/patches/api/0013-Player-affects-spawning-API.patch new file mode 100644 index 000000000000..3a62dc90c906 --- /dev/null +++ b/patches/api/0013-Player-affects-spawning-API.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Mon, 29 Feb 2016 17:22:34 -0600 +Subject: [PATCH] Player affects spawning API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index a06daeeee71a5ca58fbc1e13453d9116eadbcac2..bc64083c02bce93a22521173c9430eb5469ba8a6 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2623,6 +2623,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + @Deprecated // Paper + public String getLocale(); + ++ // Paper start ++ /** ++ * Get whether the player can affect mob spawning ++ * ++ * @return if the player can affect mob spawning ++ */ ++ public boolean getAffectsSpawning(); ++ ++ /** ++ * Set whether the player can affect mob spawning ++ * ++ * @param affects Whether the player can affect mob spawning ++ */ ++ public void setAffectsSpawning(boolean affects); ++ // Paper end ++ + /** + * Update the list of commands sent to the client. + *
      diff --git a/patches/api/0014-Add-getTPS-method.patch b/patches/api/0014-Add-getTPS-method.patch new file mode 100644 index 000000000000..b97e3f77435e --- /dev/null +++ b/patches/api/0014-Add-getTPS-method.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 29 Feb 2016 17:24:57 -0600 +Subject: [PATCH] Add getTPS method + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 60ad479817c95aef809f73c6688cd6b2a0bb91df..e4f7ff41d7205994fef87989a7955d7b8fe4d7f4 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2132,6 +2132,17 @@ public final class Bukkit { + return server.getEntity(uuid); + } + ++ // Paper start ++ /** ++ * Gets the current server TPS ++ * @return current server TPS (1m, 5m, 15m in Paper-Server) ++ */ ++ @NotNull ++ public static double[] getTPS() { ++ return server.getTPS(); ++ } ++ // Paper end ++ + /** + * Get the advancement specified by this key. + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index f5005063c33d5e7ac030c4d43cb042c18c799284..4f15cc4bcc07d3061dd94b20fc77f549ddfcbb6b 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1815,6 +1815,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Nullable + Entity getEntity(@NotNull UUID uuid); + ++ // Paper start ++ /** ++ * Gets the current server TPS ++ * ++ * @return current server TPS (1m, 5m, 15m in Paper-Server) ++ */ ++ @NotNull ++ public double[] getTPS(); ++ // Paper end ++ + /** + * Get the advancement specified by this key. + * diff --git a/patches/api/0015-Expose-server-build-information.patch b/patches/api/0015-Expose-server-build-information.patch new file mode 100644 index 000000000000..a5cae3c9f322 --- /dev/null +++ b/patches/api/0015-Expose-server-build-information.patch @@ -0,0 +1,533 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 27 May 2019 01:10:06 -0500 +Subject: [PATCH] Expose server build information + +Co-authored-by: Professor Bloodstone +Co-authored-by: Mark Vainomaa +Co-authored-by: masmc05 +Co-authored-by: Riley Park + +diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java +new file mode 100644 +index 0000000000000000000000000000000000000000..023cc52a9e28e1238c7452c0f3f577f2850fd861 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java +@@ -0,0 +1,47 @@ ++package com.destroystokyo.paper.util; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import org.bukkit.Bukkit; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++public interface VersionFetcher { ++ ++ /** ++ * Amount of time to cache results for in milliseconds ++ *

      ++ * Negative values will never cache. ++ * ++ * @return cache time ++ */ ++ long getCacheTime(); ++ ++ /** ++ * Gets the version message to cache and show to command senders. ++ * ++ *

      NOTE: This is run in a new thread separate from that of the command processing thread

      ++ * ++ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) ++ * @return the message to show when requesting a version ++ */ ++ Component getVersionMessage(String serverVersion); ++ ++ @ApiStatus.Internal ++ class DummyVersionFetcher implements VersionFetcher { ++ ++ @Override ++ public long getCacheTime() { ++ return -1; ++ } ++ ++ @Override ++ public Component getVersionMessage(final String serverVersion) { ++ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); ++ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); ++ new Throwable().printStackTrace(); ++ return Component.text("Unable to check for updates. No version provider set.", NamedTextColor.RED); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..652ff54e7c50412503725d628bfe72ed03059790 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java +@@ -0,0 +1,122 @@ ++package io.papermc.paper; ++ ++import java.time.Instant; ++import java.util.Optional; ++import java.util.OptionalInt; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.util.Services; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Information about the current server build. ++ */ ++@NullMarked ++@ApiStatus.NonExtendable ++public interface ServerBuildInfo { ++ /** ++ * The brand id for Paper. ++ */ ++ Key BRAND_PAPER_ID = Key.key("papermc", "paper"); ++ ++ /** ++ * Gets the {@code ServerBuildInfo}. ++ * ++ * @return the {@code ServerBuildInfo} ++ */ ++ static ServerBuildInfo buildInfo() { ++ // ++ final class Holder { ++ static final Optional INSTANCE = Services.service(ServerBuildInfo.class); ++ } ++ // ++ return Holder.INSTANCE.orElseThrow(); ++ } ++ ++ /** ++ * Gets the brand id of the server. ++ * ++ * @return the brand id of the server (e.g. "papermc:paper") ++ */ ++ Key brandId(); ++ ++ /** ++ * Checks if the current server supports the specified brand. ++ * ++ * @param brandId the brand to check (e.g. "papermc:folia") ++ * @return {@code true} if the server supports the specified brand ++ */ ++ @ApiStatus.Experimental ++ boolean isBrandCompatible(final Key brandId); ++ ++ /** ++ * Gets the brand name of the server. ++ * ++ * @return the brand name of the server (e.g. "Paper") ++ */ ++ String brandName(); ++ ++ /** ++ * Gets the Minecraft version id. ++ * ++ * @return the Minecraft version id (e.g. "1.20.4", "1.20.2-pre2", "23w31a") ++ */ ++ String minecraftVersionId(); ++ ++ /** ++ * Gets the Minecraft version name. ++ * ++ * @return the Minecraft version name (e.g. "1.20.4", "1.20.2 Pre-release 2", "23w31a") ++ */ ++ String minecraftVersionName(); ++ ++ /** ++ * Gets the build number. ++ * ++ * @return the build number ++ */ ++ OptionalInt buildNumber(); ++ ++ /** ++ * Gets the build time. ++ * ++ * @return the build time ++ */ ++ Instant buildTime(); ++ ++ /** ++ * Gets the git commit branch. ++ * ++ * @return the git commit branch ++ */ ++ Optional gitBranch(); ++ ++ /** ++ * Gets the git commit hash. ++ * ++ * @return the git commit hash ++ */ ++ Optional gitCommit(); ++ ++ /** ++ * Creates a string representation of the server build information. ++ * ++ * @param representation the type of representation ++ * @return a string ++ */ ++ String asString(final StringRepresentation representation); ++ ++ /** ++ * String representation types. ++ */ ++ enum StringRepresentation { ++ /** ++ * A simple version string, in format {@code --}. ++ */ ++ VERSION_SIMPLE, ++ /** ++ * A simple version string, in format {@code --@ ()}. ++ */ ++ VERSION_FULL, ++ } ++} +diff --git a/src/main/java/io/papermc/paper/util/JarManifests.java b/src/main/java/io/papermc/paper/util/JarManifests.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7915a70d676b1205dcae39259f670af258a1ab9b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/JarManifests.java +@@ -0,0 +1,38 @@ ++package io.papermc.paper.util; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.net.URL; ++import java.util.Collections; ++import java.util.Map; ++import java.util.WeakHashMap; ++import java.util.jar.Manifest; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@NullMarked ++@ApiStatus.Internal ++public final class JarManifests { ++ private JarManifests() { ++ } ++ ++ private static final Map MANIFESTS = Collections.synchronizedMap(new WeakHashMap<>()); ++ ++ public static @Nullable Manifest manifest(final Class clazz) { ++ return MANIFESTS.computeIfAbsent(clazz.getClassLoader(), classLoader -> { ++ final String classLocation = "/" + clazz.getName().replace(".", "/") + ".class"; ++ final URL resource = clazz.getResource(classLocation); ++ if (resource == null) { ++ return null; ++ } ++ final String classFilePath = resource.toString().replace("\\", "/"); ++ final String archivePath = classFilePath.substring(0, classFilePath.length() - classLocation.length()); ++ try (final InputStream stream = new URL(archivePath + "/META-INF/MANIFEST.MF").openStream()) { ++ return new Manifest(stream); ++ } catch (final IOException ex) { ++ return null; ++ } ++ }); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index e4f7ff41d7205994fef87989a7955d7b8fe4d7f4..75e0c5b884363be03876103e0d66e67de03c4856 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -110,13 +110,26 @@ public final class Bukkit { + } + + Bukkit.server = server; +- server.getLogger().info("This server is running " + getName() + " version " + getVersion() + " (Implementing API version " + getBukkitVersion() + ")"); ++ // Paper start - add git information ++ server.getLogger().info(getVersionMessage()); ++ } ++ /** ++ * Gets message describing the version server is running. ++ * ++ * @return message describing the version server is running ++ */ ++ @NotNull ++ public static String getVersionMessage() { ++ final io.papermc.paper.ServerBuildInfo version = io.papermc.paper.ServerBuildInfo.buildInfo(); ++ return "This server is running " + getName() + " version " + version.asString(io.papermc.paper.ServerBuildInfo.StringRepresentation.VERSION_FULL) + " (Implementing API version " + getBukkitVersion() + ")"; ++ // Paper end + } + + /** + * Gets the name of this server implementation. + * + * @return name of this server implementation ++ * @see io.papermc.paper.ServerBuildInfo#brandName() + */ + @NotNull + public static String getName() { +@@ -127,6 +140,7 @@ public final class Bukkit { + * Gets the version string of this server implementation. + * + * @return version of this server implementation ++ * @see io.papermc.paper.ServerBuildInfo + */ + @NotNull + public static String getVersion() { +@@ -143,6 +157,20 @@ public final class Bukkit { + return server.getBukkitVersion(); + } + ++ // Paper start - expose game version ++ /** ++ * Gets the version of game this server implements ++ * ++ * @return version of game ++ * @see io.papermc.paper.ServerBuildInfo#minecraftVersionId() ++ * @see io.papermc.paper.ServerBuildInfo#minecraftVersionName() ++ */ ++ @NotNull ++ public static String getMinecraftVersion() { ++ return server.getMinecraftVersion(); ++ } ++ // Paper end ++ + /** + * Gets a view of all currently logged in players. This {@linkplain + * Collections#unmodifiableCollection(Collection) view} is a reused +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 4f15cc4bcc07d3061dd94b20fc77f549ddfcbb6b..2ed640d5a0027f7a94a5cf4555741c27c9b1b3a4 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -120,6 +120,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public String getBukkitVersion(); + ++ // Paper start - expose game version ++ /** ++ * Gets the version of game this server implements ++ * ++ * @return version of game ++ */ ++ @NotNull ++ String getMinecraftVersion(); ++ // Paper end ++ + /** + * Gets a view of all currently logged in players. This {@linkplain + * Collections#unmodifiableCollection(Collection) view} is a reused +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index aec092e019667d53faf3e7352799772804d5d260..012b46c82d9d06d1d2da8da626fc5cde6e9e2ca4 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -156,4 +156,13 @@ public interface UnsafeValues { + return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); + } + // Paper end ++ ++ // Paper start ++ /** ++ * Called once by the version command on first use, then cached. ++ */ ++ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { ++ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java +index 263208d3cba36cb80c9ee4e3022ef702ea113df2..e64bb57f74e6d6f78927be228825b3e0bdf41f48 100644 +--- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java +@@ -25,8 +25,25 @@ import org.bukkit.plugin.Plugin; + import org.bukkit.plugin.PluginDescriptionFile; + import org.bukkit.util.StringUtil; + import org.jetbrains.annotations.NotNull; ++// Paper start - version command 2.0 ++import com.destroystokyo.paper.util.VersionFetcher; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.kyori.adventure.text.format.TextDecoration; ++import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; ++// Paper end - version command 2.0 + + public class VersionCommand extends BukkitCommand { ++ private VersionFetcher versionFetcher; // Paper - version command 2.0 ++ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration ++ if (versionFetcher == null) { ++ versionFetcher = Bukkit.getUnsafe().getVersionFetcher(); ++ } ++ ++ return versionFetcher; ++ } ++ + public VersionCommand(@NotNull String name) { + super(name); + +@@ -41,7 +58,7 @@ public class VersionCommand extends BukkitCommand { + if (!testPermission(sender)) return true; + + if (args.length == 0) { +- sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); ++ //sender.sendMessage("This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); // Paper - moved to setVersionMessage + sendVersion(sender); + } else { + StringBuilder name = new StringBuilder(); +@@ -80,8 +97,17 @@ public class VersionCommand extends BukkitCommand { + + private void describeToSender(@NotNull Plugin plugin, @NotNull CommandSender sender) { + PluginDescriptionFile desc = plugin.getDescription(); +- sender.sendMessage(ChatColor.GREEN + desc.getName() + ChatColor.WHITE + " version " + ChatColor.GREEN + desc.getVersion()); +- ++ // Paper start - version command 2.0 ++ sender.sendMessage( ++ Component.text() ++ .append(Component.text(desc.getName(), NamedTextColor.GREEN)) ++ .append(Component.text(" version ")) ++ .append(Component.text(desc.getVersion(), NamedTextColor.GREEN) ++ .hoverEvent(Component.text("Click to copy to clipboard", NamedTextColor.WHITE)) ++ .clickEvent(ClickEvent.copyToClipboard(desc.getVersion())) ++ ) ++ ); ++ // Paper end - version command 2.0 + if (desc.getDescription() != null) { + sender.sendMessage(desc.getDescription()); + } +@@ -147,14 +173,14 @@ public class VersionCommand extends BukkitCommand { + + private final ReentrantLock versionLock = new ReentrantLock(); + private boolean hasVersion = false; +- private String versionMessage = null; ++ private Component versionMessage = null; // Paper + private final Set versionWaiters = new HashSet(); + private boolean versionTaskStarted = false; + private long lastCheck = 0; + + private void sendVersion(@NotNull CommandSender sender) { + if (hasVersion) { +- if (System.currentTimeMillis() - lastCheck > 21600000) { ++ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier + lastCheck = System.currentTimeMillis(); + hasVersion = false; + } else { +@@ -169,7 +195,7 @@ public class VersionCommand extends BukkitCommand { + return; + } + versionWaiters.add(sender); +- sender.sendMessage("Checking version, please wait..."); ++ sender.sendMessage(Component.text("Checking version, please wait...", NamedTextColor.WHITE, TextDecoration.ITALIC)); // Paper + if (!versionTaskStarted) { + versionTaskStarted = true; + new Thread(new Runnable() { +@@ -187,6 +213,13 @@ public class VersionCommand extends BukkitCommand { + + private void obtainVersion() { + String version = Bukkit.getVersion(); ++ // Paper start ++ if (version.startsWith("null")) { // running from ide? ++ setVersionMessage(Component.text("Unknown version, custom build?", NamedTextColor.YELLOW)); ++ return; ++ } ++ setVersionMessage(getVersionFetcher().getVersionMessage(version)); ++ /* + if (version == null) version = "Custom"; + String[] parts = version.substring(0, version.indexOf(' ')).split("-"); + if (parts.length == 4) { +@@ -216,11 +249,24 @@ public class VersionCommand extends BukkitCommand { + } else { + setVersionMessage("Unknown version, custom build?"); + } ++ */ ++ // Paper end + } + +- private void setVersionMessage(@NotNull String msg) { ++ // Paper start ++ private void setVersionMessage(final @NotNull Component msg) { + lastCheck = System.currentTimeMillis(); +- versionMessage = msg; ++ final Component message = Component.textOfChildren( ++ Component.text(Bukkit.getVersionMessage(), NamedTextColor.WHITE), ++ Component.newline(), ++ msg ++ ); ++ this.versionMessage = Component.text() ++ .append(message) ++ .hoverEvent(Component.text("Click to copy to clipboard", NamedTextColor.WHITE)) ++ .clickEvent(ClickEvent.copyToClipboard(PlainTextComponentSerializer.plainText().serialize(message))) ++ .build(); ++ // Paper end + versionLock.lock(); + try { + hasVersion = true; +diff --git a/src/test/java/io/papermc/paper/TestServerBuildInfo.java b/src/test/java/io/papermc/paper/TestServerBuildInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..17be27a869c1047a7a9440fb8f3717260d4abbd0 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/TestServerBuildInfo.java +@@ -0,0 +1,59 @@ ++package io.papermc.paper; ++ ++import java.time.Instant; ++import java.util.Optional; ++import java.util.OptionalInt; ++import net.kyori.adventure.key.Key; ++import org.jetbrains.annotations.NotNull; ++ ++public class TestServerBuildInfo implements ServerBuildInfo { ++ @Override ++ public @NotNull Key brandId() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean isBrandCompatible(final @NotNull Key brandId) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull String brandName() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull String minecraftVersionId() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull String minecraftVersionName() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull OptionalInt buildNumber() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull Instant buildTime() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull Optional gitBranch() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull Optional gitCommit() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull String asString(final @NotNull StringRepresentation representation) { ++ return ""; ++ } ++} +diff --git a/src/test/resources/META-INF/services/io.papermc.paper.ServerBuildInfo b/src/test/resources/META-INF/services/io.papermc.paper.ServerBuildInfo +new file mode 100644 +index 0000000000000000000000000000000000000000..64e2f8559b9c5a52e0a3229d3d12f65e9af145b3 +--- /dev/null ++++ b/src/test/resources/META-INF/services/io.papermc.paper.ServerBuildInfo +@@ -0,0 +1 @@ ++io.papermc.paper.TestServerBuildInfo diff --git a/patches/api/0016-Entity-Origin-API.patch b/patches/api/0016-Entity-Origin-API.patch new file mode 100644 index 000000000000..ca30d1d77fb8 --- /dev/null +++ b/patches/api/0016-Entity-Origin-API.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 17:50:31 -0600 +Subject: [PATCH] Entity Origin API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index d7f95863922bf332c674d538eb187015fadae9d8..411297f66520774a4072c9e15aa9bdf03a527208 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -791,5 +791,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + default net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { + return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName()))); + } ++ ++ /** ++ * Gets the location where this entity originates from. ++ *

      ++ * This value can be null if the entity hasn't yet been added to the world. ++ * ++ * @return Location where entity originates or null if not yet added ++ */ ++ @Nullable ++ Location getOrigin(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java +index 5d7d940cdad7915efa639b8940a17dc97b60ecd8..315dcf9da29e077a819f602ebf1c76286164b264 100644 +--- a/src/main/java/org/bukkit/entity/FallingBlock.java ++++ b/src/main/java/org/bukkit/entity/FallingBlock.java +@@ -126,4 +126,15 @@ public interface FallingBlock extends Entity { + * @param damage the max damage to set. Must be >= 0 + */ + void setMaxDamage(int damage); ++ ++ /** ++ * Gets the source block location of the FallingBlock ++ * ++ * @return the source block location the FallingBlock was spawned from ++ * @deprecated replaced by {@link Entity#getOrigin()} ++ */ ++ @Deprecated ++ default org.bukkit.Location getSourceLoc() { ++ return this.getOrigin(); ++ } + } +diff --git a/src/main/java/org/bukkit/entity/TNTPrimed.java b/src/main/java/org/bukkit/entity/TNTPrimed.java +index a23cfdf66877f0a61eae700de084c76e6ee7b431..0813bd913c8fdb2001963ce3e82c07c2af105418 100644 +--- a/src/main/java/org/bukkit/entity/TNTPrimed.java ++++ b/src/main/java/org/bukkit/entity/TNTPrimed.java +@@ -53,4 +53,15 @@ public interface TNTPrimed extends Explosive { + * @param source the source of this primed TNT + */ + public void setSource(@Nullable Entity source); ++ ++ /** ++ * Gets the source block location of the TNTPrimed ++ * ++ * @return the source block location the TNTPrimed was spawned from ++ * @deprecated replaced by {@link Entity#getOrigin()} ++ */ ++ @Deprecated ++ default org.bukkit.Location getSourceLoc() { ++ return this.getOrigin(); ++ } + } diff --git a/patches/api/0017-Add-view-distance-API.patch b/patches/api/0017-Add-view-distance-API.patch new file mode 100644 index 000000000000..562b99a9f16a --- /dev/null +++ b/patches/api/0017-Add-view-distance-API.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 18:05:37 -0600 +Subject: [PATCH] Add view distance API + +Add per player no-tick, tick, and send view distances. + +Also add send/no-tick view distance to World. + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index ed87e82eb0e30bdea6f7760bb80addcb3bbe59cc..683357f685b1d5f52151a5e78fc5265ebf9d32c2 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -2968,6 +2968,66 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @NotNull + public Set getFeatureFlags(); + ++ // Paper start - view distance api ++ /** ++ * Sets the view distance for this world. ++ * @param viewDistance view distance in [2, 32] ++ */ ++ void setViewDistance(int viewDistance); ++ ++ /** ++ * Sets the simulation distance for this world. ++ * @param simulationDistance simulation distance in [2, 32] ++ */ ++ void setSimulationDistance(int simulationDistance); ++ ++ /** ++ * Returns the no-tick view distance for this world. ++ *

      ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

      ++ * @return The no-tick view distance for this world. ++ * @deprecated Use {@link #getViewDistance()} ++ */ ++ @Deprecated ++ default int getNoTickViewDistance() { ++ return this.getViewDistance(); ++ } ++ ++ /** ++ * Sets the no-tick view distance for this world. ++ *

      ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

      ++ * @param viewDistance view distance in [2, 32] ++ * @deprecated Use {@link #setViewDistance(int)} ++ */ ++ @Deprecated ++ default void setNoTickViewDistance(int viewDistance) { ++ this.setViewDistance(viewDistance); ++ } ++ ++ /** ++ * Gets the sending view distance for this world. ++ *

      ++ * Sending view distance is the view distance where chunks will load in for players in this world. ++ *

      ++ * @return The sending view distance for this world. ++ */ ++ int getSendViewDistance(); ++ ++ /** ++ * Sets the sending view distance for this world. ++ *

      ++ * Sending view distance is the view distance where chunks will load in for players in this world. ++ *

      ++ * @param viewDistance view distance in [2, 32] or -1 ++ */ ++ void setSendViewDistance(int viewDistance); ++ // Paper end - view distance api ++ + /** + * Gets all generated structures that intersect the chunk at the given + * coordinates.
      +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index bc64083c02bce93a22521173c9430eb5469ba8a6..2073aca572a1b751e895373f32fffba0edf026a5 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2637,6 +2637,82 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param affects Whether the player can affect mob spawning + */ + public void setAffectsSpawning(boolean affects); ++ ++ /** ++ * Gets the view distance for this player ++ * ++ * @return the player's view distance ++ * @see org.bukkit.World#getViewDistance() ++ */ ++ public int getViewDistance(); ++ ++ /** ++ * Sets the view distance for this player ++ * ++ * @param viewDistance the player's view distance ++ * @see org.bukkit.World#setViewDistance(int) ++ */ ++ public void setViewDistance(int viewDistance); ++ ++ /** ++ * Gets the simulation distance for this player ++ * ++ * @return the player's simulation distance ++ */ ++ public int getSimulationDistance(); ++ ++ /** ++ * Sets the simulation distance for this player ++ * ++ * @param simulationDistance the player's new simulation distance ++ */ ++ public void setSimulationDistance(int simulationDistance); ++ ++ /** ++ * Gets the no-ticking view distance for this player. ++ *

      ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

      ++ * @return The no-tick view distance for this player. ++ * @deprecated Use {@link #getViewDistance()} ++ */ ++ @Deprecated ++ default int getNoTickViewDistance() { ++ return this.getViewDistance(); ++ } ++ ++ /** ++ * Sets the no-ticking view distance for this player. ++ *

      ++ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not ++ * be set to tick. ++ *

      ++ * @param viewDistance view distance in [2, 32] or -1 ++ * @deprecated Use {@link #setViewDistance(int)} ++ */ ++ @Deprecated ++ default void setNoTickViewDistance(int viewDistance) { ++ this.setViewDistance(viewDistance); ++ } ++ ++ /** ++ * Gets the sending view distance for this player. ++ *

      ++ * Sending view distance is the view distance where chunks will load in for players. ++ *

      ++ * @return The sending view distance for this player. ++ */ ++ public int getSendViewDistance(); ++ ++ /** ++ * Sets the sending view distance for this player. ++ *

      ++ * Sending view distance is the view distance where chunks will load in for players. ++ *

      ++ * @param viewDistance view distance in [2, 32] or -1 ++ */ ++ public void setSendViewDistance(int viewDistance); + // Paper end + + /** diff --git a/patches/api/0018-Add-BeaconEffectEvent.patch b/patches/api/0018-Add-BeaconEffectEvent.patch new file mode 100644 index 000000000000..15619bb49566 --- /dev/null +++ b/patches/api/0018-Add-BeaconEffectEvent.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Mon, 29 Feb 2016 18:09:40 -0600 +Subject: [PATCH] Add BeaconEffectEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..741d0e73bc635a545c94c4b1254cee8f41ba8925 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/block/BeaconEffectEvent.java +@@ -0,0 +1,88 @@ ++package com.destroystokyo.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.potion.PotionEffect; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when a beacon effect is being applied to a player. ++ */ ++@NullMarked ++public class BeaconEffectEvent extends BlockEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Player player; ++ private final boolean primary; ++ private PotionEffect effect; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public BeaconEffectEvent(final Block block, final PotionEffect effect, final Player player, final boolean primary) { ++ super(block); ++ this.effect = effect; ++ this.player = player; ++ this.primary = primary; ++ } ++ ++ /** ++ * Gets the potion effect being applied. ++ * ++ * @return Potion effect ++ */ ++ public PotionEffect getEffect() { ++ return this.effect; ++ } ++ ++ /** ++ * Sets the potion effect that will be applied. ++ * ++ * @param effect Potion effect ++ */ ++ public void setEffect(final PotionEffect effect) { ++ this.effect = effect; ++ } ++ ++ /** ++ * Gets the player who the potion effect is being applied to. ++ * ++ * @return Affected player ++ */ ++ public Player getPlayer() { ++ return this.player; ++ } ++ ++ /** ++ * Gets whether the effect is a primary beacon effect. ++ * ++ * @return {@code true} if this event represents a primary effect ++ */ ++ public boolean isPrimary() { ++ return this.primary; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0019-Expose-server-CommandMap.patch b/patches/api/0019-Expose-server-CommandMap.patch new file mode 100644 index 000000000000..9fa19450c816 --- /dev/null +++ b/patches/api/0019-Expose-server-CommandMap.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Mon, 29 Feb 2016 19:48:59 -0600 +Subject: [PATCH] Expose server CommandMap + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 75e0c5b884363be03876103e0d66e67de03c4856..81b3800e86bcd20b47df13e9c9ef3a83abfcb7c6 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2361,6 +2361,19 @@ public final class Bukkit { + return server.getUnsafe(); + } + ++ ++ // Paper start ++ /** ++ * Gets the active {@link org.bukkit.command.CommandMap} ++ * ++ * @return the active command map ++ */ ++ @NotNull ++ public static org.bukkit.command.CommandMap getCommandMap() { ++ return server.getCommandMap(); ++ } ++ // Paper end ++ + @NotNull + public static Server.Spigot spigot() { + return server.spigot(); +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 2ed640d5a0027f7a94a5cf4555741c27c9b1b3a4..1b18d3916f3972675d9371ec5c6e020d70a723f6 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1835,6 +1835,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + public double[] getTPS(); + // Paper end + ++ // Paper start ++ /** ++ * Gets the active {@link org.bukkit.command.CommandMap} ++ * ++ * @return the active command map ++ */ ++ @NotNull ++ org.bukkit.command.CommandMap getCommandMap(); ++ + /** + * Get the advancement specified by this key. + * diff --git a/patches/api/0020-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api/0020-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch new file mode 100644 index 000000000000..9aa815bb7799 --- /dev/null +++ b/patches/api/0020-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 19:54:32 -0600 +Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses + +Change Javadoc to be accurate + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 81b3800e86bcd20b47df13e9c9ef3a83abfcb7c6..1ada54827acfaacab0a32ae5d55def952547c352 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -472,6 +472,30 @@ public final class Bukkit { + return server.broadcastMessage(message); + } + ++ // Paper start ++ /** ++ * Sends the component to all online players. ++ * ++ * @param component the component to send ++ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ server.broadcast(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to all online players. ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods on {@link #getServer()} that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public static void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ server.broadcast(components); ++ } ++ // Paper end ++ + /** + * Gets the name of the update folder. The update folder is used to safely + * update plugins at the right moment on a plugin load. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 1b18d3916f3972675d9371ec5c6e020d70a723f6..93d924c586803161820707af823c352f7c5d40e1 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -383,6 +383,30 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Deprecated // Paper + public int broadcastMessage(@NotNull String message); + ++ // Paper start ++ /** ++ * Sends the component to all online players. ++ * ++ * @param component the component to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ spigot().broadcast(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to all online players. ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Deprecated ++ public default void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().broadcast(components); ++ } ++ // Paper end ++ + /** + * Gets the name of the update folder. The update folder is used to safely + * update plugins at the right moment on a plugin load. +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 2073aca572a1b751e895373f32fffba0edf026a5..17f55697d02d7b9c9b42c4b89a33db9207622a36 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1254,6 +1254,42 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendMap(@NotNull MapView map); + ++ // Paper start ++ /** ++ * Sends the component to the player ++ * ++ * @param component the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Override ++ @Deprecated ++ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ spigot().sendMessage(component); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the player ++ * ++ * @param components the components to send ++ * @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component} ++ */ ++ @Override ++ @Deprecated ++ public default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().sendMessage(components); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the specified screen position of this player ++ * ++ * @param position the screen position ++ * @param components the components to send ++ */ ++ public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { ++ spigot().sendMessage(position, components); ++ } ++ // Paper end ++ + /** + * Send a hurt animation. This fakes incoming damage towards the player from + * the given yaw relative to the player's direction. diff --git a/patches/api/0021-Add-exception-reporting-event.patch b/patches/api/0021-Add-exception-reporting-event.patch new file mode 100644 index 000000000000..c446fdb186c3 --- /dev/null +++ b/patches/api/0021-Add-exception-reporting-event.patch @@ -0,0 +1,581 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Mon, 29 Feb 2016 20:24:35 -0600 +Subject: [PATCH] Add exception reporting event + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..95a5a59e6bd88345177fca0b12008ddd689cb448 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/ServerExceptionEvent.java +@@ -0,0 +1,43 @@ ++package com.destroystokyo.paper.event.server; ++ ++import com.destroystokyo.paper.exception.ServerException; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called whenever an exception is thrown in a recoverable section of the server. ++ */ ++@NullMarked ++public class ServerExceptionEvent extends Event { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final ServerException exception; ++ ++ @ApiStatus.Internal ++ public ServerExceptionEvent(final ServerException exception) { ++ super(!Bukkit.isPrimaryThread()); ++ this.exception = exception; ++ } ++ ++ /** ++ * Gets the wrapped exception that was thrown. ++ * ++ * @return Exception thrown ++ */ ++ public ServerException getException() { ++ return this.exception; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6fb39af0479a818f7f1465bcdfe505ab4ff7da1a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerCommandException.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Thrown when a command throws an exception ++ */ ++public class ServerCommandException extends ServerException { ++ ++ private final Command command; ++ private final CommandSender commandSender; ++ private final String[] arguments; ++ ++ public ServerCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ public ServerCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(cause); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ protected ServerCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ this.commandSender = checkNotNull(commandSender, "commandSender"); ++ this.arguments = checkNotNull(arguments, "arguments"); ++ this.command = checkNotNull(command, "command"); ++ } ++ ++ /** ++ * Gets the command which threw the exception ++ * ++ * @return exception throwing command ++ */ ++ public Command getCommand() { ++ return command; ++ } ++ ++ /** ++ * Gets the command sender which executed the command request ++ * ++ * @return command sender of exception thrown command request ++ */ ++ public CommandSender getCommandSender() { ++ return commandSender; ++ } ++ ++ /** ++ * Gets the arguments which threw the exception for the command ++ * ++ * @return arguments of exception thrown command request ++ */ ++ public String[] getArguments() { ++ return arguments; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..410b24139535cd5d8439ad581c43c61b5757fbf6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerEventException.java +@@ -0,0 +1,52 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.*; ++ ++/** ++ * Exception thrown when a server event listener throws an exception ++ */ ++public class ServerEventException extends ServerPluginException { ++ ++ private final Listener listener; ++ private final Event event; ++ ++ public ServerEventException(String message, Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(message, cause, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ public ServerEventException(Throwable cause, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(cause, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ protected ServerEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Listener listener, Event event) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ this.listener = checkNotNull(listener, "listener"); ++ this.event = checkNotNull(event, "event"); ++ } ++ ++ /** ++ * Gets the listener which threw the exception ++ * ++ * @return event listener ++ */ ++ public Listener getListener() { ++ return listener; ++ } ++ ++ /** ++ * Gets the event which caused the exception ++ * ++ * @return event ++ */ ++ public Event getEvent() { ++ return event; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c06ea3942447d4824b83ff839cb449fb818dede1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerException.java +@@ -0,0 +1,23 @@ ++package com.destroystokyo.paper.exception; ++ ++/** ++ * Wrapper exception for all exceptions that are thrown by the server. ++ */ ++public class ServerException extends Exception { ++ ++ public ServerException(String message) { ++ super(message); ++ } ++ ++ public ServerException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ ++ public ServerException(Throwable cause) { ++ super(cause); ++ } ++ ++ protected ServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c3effca7c9d6c904cbe248d312b74e2cd360acf +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerInternalException.java +@@ -0,0 +1,36 @@ ++package com.destroystokyo.paper.exception; ++ ++import java.util.logging.Level; ++import org.bukkit.Bukkit; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++ ++/** ++ * Thrown when the internal server throws a recoverable exception. ++ */ ++public class ServerInternalException extends ServerException { ++ ++ public ServerInternalException(String message) { ++ super(message); ++ } ++ ++ public ServerInternalException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ ++ public ServerInternalException(Throwable cause) { ++ super(cause); ++ } ++ ++ protected ServerInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ } ++ ++ public static void reportInternalException(Throwable cause) { ++ try { ++ Bukkit.getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(cause))); ++ ; ++ } catch (Throwable t) { ++ Bukkit.getLogger().log(Level.WARNING, "Exception posting ServerExceptionEvent", t); // Don't want to rethrow! ++ } ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f016ba3b1b62e554a9bacbb9635f2dbe441b3c4e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginEnableDisableException.java +@@ -0,0 +1,20 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.plugin.Plugin; ++ ++/** ++ * Thrown whenever there is an exception with any enabling or disabling of plugins. ++ */ ++public class ServerPluginEnableDisableException extends ServerPluginException { ++ public ServerPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) { ++ super(message, cause, responsiblePlugin); ++ } ++ ++ public ServerPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) { ++ super(cause, responsiblePlugin); ++ } ++ ++ protected ServerPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..be3f92e3c6bcefe8b78da701b75121275001882e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginException.java +@@ -0,0 +1,36 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Wrapper exception for all cases to which a plugin can be immediately blamed for ++ */ ++public class ServerPluginException extends ServerException { ++ public ServerPluginException(String message, Throwable cause, Plugin responsiblePlugin) { ++ super(message, cause); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ public ServerPluginException(Throwable cause, Plugin responsiblePlugin) { ++ super(cause); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ protected ServerPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) { ++ super(message, cause, enableSuppression, writableStackTrace); ++ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin"); ++ } ++ ++ private final Plugin responsiblePlugin; ++ ++ /** ++ * Gets the plugin which is directly responsible for the exception being thrown ++ * ++ * @return plugin which is responsible for the exception throw ++ */ ++ public Plugin getResponsiblePlugin() { ++ return responsiblePlugin; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2faef4cb358ec65e32a6aba6426f0dd7ddf90d2a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerPluginMessageException.java +@@ -0,0 +1,64 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.plugin.Plugin; ++ ++import static com.google.common.base.Preconditions.*; ++ ++/** ++ * Thrown when an incoming plugin message channel throws an exception ++ */ ++public class ServerPluginMessageException extends ServerPluginException { ++ ++ private final Player player; ++ private final String channel; ++ private final byte[] data; ++ ++ public ServerPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(message, cause, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ public ServerPluginMessageException(Throwable cause, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(cause, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ protected ServerPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, Player player, String channel, byte[] data) { ++ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin); ++ this.player = checkNotNull(player, "player"); ++ this.channel = checkNotNull(channel, "channel"); ++ this.data = checkNotNull(data, "data"); ++ } ++ ++ /** ++ * Gets the channel to which the error occurred from receiving data from ++ * ++ * @return exception channel ++ */ ++ public String getChannel() { ++ return channel; ++ } ++ ++ /** ++ * Gets the data to which the error occurred from ++ * ++ * @return exception data ++ */ ++ public byte[] getData() { ++ return data; ++ } ++ ++ /** ++ * Gets the player which the plugin message causing the exception originated from ++ * ++ * @return exception player ++ */ ++ public Player getPlayer() { ++ return player; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d0b2d4a9b3e5bdeec0e4ea7ab69858d86aa3715 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerSchedulerException.java +@@ -0,0 +1,37 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.scheduler.BukkitTask; ++ ++import static com.google.common.base.Preconditions.checkNotNull; ++ ++/** ++ * Thrown when a plugin's scheduler fails with an exception ++ */ ++public class ServerSchedulerException extends ServerPluginException { ++ ++ private final BukkitTask task; ++ ++ public ServerSchedulerException(String message, Throwable cause, BukkitTask task) { ++ super(message, cause, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ public ServerSchedulerException(Throwable cause, BukkitTask task) { ++ super(cause, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ protected ServerSchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, BukkitTask task) { ++ super(message, cause, enableSuppression, writableStackTrace, task.getOwner()); ++ this.task = checkNotNull(task, "task"); ++ } ++ ++ /** ++ * Gets the task which threw the exception ++ * ++ * @return exception throwing task ++ */ ++ public BukkitTask getTask() { ++ return task; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078cd9521a1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/exception/ServerTabCompleteException.java +@@ -0,0 +1,22 @@ ++package com.destroystokyo.paper.exception; ++ ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++/** ++ * Called when a tab-complete request throws an exception ++ */ ++public class ServerTabCompleteException extends ServerCommandException { ++ ++ public ServerTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, command, commandSender, arguments); ++ } ++ ++ public ServerTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) { ++ super(cause, command, commandSender, arguments); ++ } ++ ++ protected ServerTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) { ++ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments); ++ } ++} +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index 36fc2c35395c72f8b81a2a2f3265fd205384ce26..c7fa1d235cea78bda4656ed66b8d42b119cc50fb 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -156,11 +156,14 @@ public class SimpleCommandMap implements CommandMap { + target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length)); + } // target.timings.stopTiming(); // Spigot // Paper + } catch (CommandException ex) { ++ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper + //target.timings.stopTiming(); // Spigot // Paper + throw ex; + } catch (Throwable ex) { + //target.timings.stopTiming(); // Spigot // Paper +- throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); ++ String msg = "Unhandled exception executing '" + commandLine + "' in " + target; ++ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper ++ throw new CommandException(msg, ex); + } + + // return true as command was handled +@@ -239,7 +242,9 @@ public class SimpleCommandMap implements CommandMap { + } catch (CommandException ex) { + throw ex; + } catch (Throwable ex) { +- throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex); ++ String msg = "Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target; ++ server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerTabCompleteException(msg, ex, target, sender, args))); // Paper ++ throw new CommandException(msg, ex); + } + } + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index 48b66054913c8b53e6e7fd34615c2ab54727693f..001465eedafa51ac027a4db51cba6223edfe1171 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -528,7 +528,8 @@ public final class SimplePluginManager implements PluginManager { + try { + plugin.getPluginLoader().enablePlugin(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while enabling " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); + } + + HandlerList.bakeAll(); +@@ -551,32 +552,37 @@ public final class SimplePluginManager implements PluginManager { + try { + plugin.getPluginLoader().disablePlugin(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while disabling " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getScheduler().cancelTasks(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while cancelling tasks for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getServicesManager().unregisterAll(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering services for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering services for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + HandlerList.unregisterAll(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering events for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering events for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { + server.getMessenger().unregisterIncomingPluginChannel(plugin); + server.getMessenger().unregisterOutgoingPluginChannel(plugin); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred (in the plugin loader) while unregistering plugin channels for " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for " ++ + plugin.getDescription().getFullName() + " (Is it up to date?)", ex, plugin); // Paper + } + + try { +@@ -589,6 +595,13 @@ public final class SimplePluginManager implements PluginManager { + } + } + ++ // Paper start ++ private void handlePluginException(String msg, Throwable ex, Plugin plugin) { ++ server.getLogger().log(Level.SEVERE, msg, ex); ++ callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin))); ++ } ++ // Paper end ++ + @Override + public void clearPlugins() { + if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper +@@ -654,7 +667,13 @@ public final class SimplePluginManager implements PluginManager { + )); + } + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(), ex); ++ // Paper start - error reporting ++ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); ++ server.getLogger().log(Level.SEVERE, msg, ex); ++ if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop ++ callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); ++ } ++ // Paper end + } + } + } diff --git a/patches/api/0022-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/patches/api/0022-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch new file mode 100644 index 000000000000..02e7138c1061 --- /dev/null +++ b/patches/api/0022-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Tue, 8 Mar 2016 13:05:59 -0800 +Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender + + +diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java +index 70fec73328227725f519af845ecbdce8be2fa4e2..04e7cd0e4e2d0eb38fb2862ce6688a4470f30d6b 100644 +--- a/src/main/java/org/bukkit/command/CommandSender.java ++++ b/src/main/java/org/bukkit/command/CommandSender.java +@@ -1,6 +1,9 @@ + package org.bukkit.command; + + import java.util.UUID; ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.identity.Identity; ++import net.kyori.adventure.text.Component; + import org.bukkit.Server; + import org.bukkit.permissions.Permissible; + import org.jetbrains.annotations.NotNull; +@@ -168,5 +171,33 @@ public interface CommandSender extends net.kyori.adventure.audience.Audience, Pe + default void sendPlainMessage(final @NotNull String message) { + this.sendMessage(net.kyori.adventure.text.Component.text(message)); + } ++ ++ /** ++ * Sends the component to the sender ++ * ++ *

      If this sender does not support sending full components then ++ * the component will be sent as legacy text.

      ++ * ++ * @param component the component to send ++ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead ++ */ ++ @Deprecated ++ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { ++ this.sendMessage(component.toLegacyText()); ++ } ++ ++ /** ++ * Sends an array of components as a single message to the sender ++ * ++ *

      If this sender does not support sending full components then ++ * the components will be sent as legacy text.

      ++ * ++ * @param components the components to send ++ * @deprecated use {@link #sendMessage(Identity, Component, MessageType)} instead ++ */ ++ @Deprecated ++ default void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) { ++ this.sendMessage(new net.md_5.bungee.api.chat.TextComponent(components).toLegacyText()); ++ } + // Paper end + } diff --git a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/patches/api/0023-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch rename to patches/api/0023-Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/patches/api/0024-Player-Tab-List-and-Title-APIs.patch b/patches/api/0024-Player-Tab-List-and-Title-APIs.patch new file mode 100644 index 000000000000..07f2e6f80157 --- /dev/null +++ b/patches/api/0024-Player-Tab-List-and-Title-APIs.patch @@ -0,0 +1,569 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Mon, 29 Feb 2016 20:02:40 -0600 +Subject: [PATCH] Player Tab List and Title APIs + +Co-authored-by: Fruxz + +diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java +new file mode 100644 +index 0000000000000000000000000000000000000000..20a028450667edf102b59b6b50ac6e890f2c34ab +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Title.java +@@ -0,0 +1,420 @@ ++package com.destroystokyo.paper; ++ ++import net.md_5.bungee.api.chat.BaseComponent; ++import net.md_5.bungee.api.chat.TextComponent; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.List; ++ ++import static com.google.common.base.Preconditions.checkArgument; ++import static com.google.common.base.Preconditions.checkNotNull; ++import static com.google.common.base.Preconditions.checkState; ++ ++/** ++ * Represents a title to may be sent to a {@link Player}. ++ * ++ *

      A title can be sent without subtitle text.

      ++ * ++ * @deprecated use {@link net.kyori.adventure.title.Title} ++ */ ++@Deprecated(since = "1.16.5") ++public final class Title { ++ ++ /** ++ * The default number of ticks for the title to fade in. ++ */ ++ public static final int DEFAULT_FADE_IN = 20; ++ /** ++ * The default number of ticks for the title to stay. ++ */ ++ public static final int DEFAULT_STAY = 200; ++ /** ++ * The default number of ticks for the title to fade out. ++ */ ++ public static final int DEFAULT_FADE_OUT = 20; ++ ++ private final BaseComponent[] title; ++ private final BaseComponent[] subtitle; ++ private final int fadeIn; ++ private final int stay; ++ private final int fadeOut; ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull BaseComponent title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull BaseComponent[] title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values and no subtitle. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @throws NullPointerException if the title is null ++ */ ++ public Title(@NotNull String title) { ++ this(title, null); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Create a title with the default time values. ++ * ++ *

      Times use default values.

      ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ */ ++ public Title(@NotNull String title, @Nullable String subtitle) { ++ this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT); ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ * @throws IllegalArgumentException if any of the times are negative ++ */ ++ public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) { ++ this( ++ new BaseComponent[]{checkNotNull(title, "title")}, ++ subtitle == null ? null : new BaseComponent[]{subtitle}, ++ fadeIn, ++ stay, ++ fadeOut ++ ); ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ * @throws IllegalArgumentException if any of the times are negative ++ */ ++ public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) { ++ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); ++ checkArgument(stay >= 0, "Negative stay: %s", stay); ++ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); ++ this.title = checkNotNull(title, "title"); ++ this.subtitle = subtitle; ++ this.fadeIn = fadeIn; ++ this.stay = stay; ++ this.fadeOut = fadeOut; ++ } ++ ++ /** ++ * Creates a new title. ++ * ++ *

      It is recommended to the {@link BaseComponent} constrctors.

      ++ * ++ * @param title the main text of the title ++ * @param subtitle the secondary text of the title ++ * @param fadeIn the number of ticks for the title to fade in ++ * @param stay the number of ticks for the title to stay on screen ++ * @param fadeOut the number of ticks for the title to fade out ++ */ ++ public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) { ++ this( ++ TextComponent.fromLegacyText(checkNotNull(title, "title")), ++ subtitle == null ? null : TextComponent.fromLegacyText(subtitle), ++ fadeIn, ++ stay, ++ fadeOut ++ ); ++ } ++ ++ /** ++ * Gets the text of this title ++ * ++ * @return the text ++ */ ++ @NotNull ++ public BaseComponent[] getTitle() { ++ return this.title; ++ } ++ ++ /** ++ * Gets the text of this title's subtitle ++ * ++ * @return the text ++ */ ++ @Nullable ++ public BaseComponent[] getSubtitle() { ++ return this.subtitle; ++ } ++ ++ /** ++ * Gets the number of ticks to fade in. ++ * ++ *

      The returned value is never negative.

      ++ * ++ * @return the number of ticks to fade in ++ */ ++ public int getFadeIn() { ++ return this.fadeIn; ++ } ++ ++ /** ++ * Gets the number of ticks to stay. ++ * ++ *

      The returned value is never negative.

      ++ * ++ * @return the number of ticks to stay ++ */ ++ public int getStay() { ++ return this.stay; ++ } ++ ++ /** ++ * Gets the number of ticks to fade out. ++ * ++ *

      The returned value is never negative.

      ++ * ++ * @return the number of ticks to fade out ++ */ ++ public int getFadeOut() { ++ return this.fadeOut; ++ } ++ ++ /** ++ * Sends the title directly to an player ++ * ++ * @param player the receiver of the title ++ */ ++ public void send(@NotNull Player player) { ++ player.sendTitle(this); ++ } ++ ++ /** ++ * Sends the title directly to the defined players ++ * ++ * @param players the receivers of the title ++ */ ++ public void send(@NotNull Collection players) { ++ for (Player player : players) { ++ player.sendTitle(this); ++ } ++ } ++ ++ /** ++ * Sends the title directly to the defined players ++ * ++ * @param players the receivers of the title ++ */ ++ public void send(@NotNull Player[] players) { ++ for (Player player : players) { ++ player.sendTitle(this); ++ } ++ } ++ ++ /** ++ * Sends the title directly to all online players ++ */ ++ public void broadcast() { ++ send(Bukkit.getOnlinePlayers()); ++ } ++ ++ @NotNull ++ public static Builder builder() { ++ return new Builder(); ++ } ++ ++ /** ++ * A builder for creating titles ++ */ ++ public static final class Builder { ++ ++ private BaseComponent[] title; ++ private BaseComponent[] subtitle; ++ private int fadeIn = DEFAULT_FADE_IN; ++ private int stay = DEFAULT_STAY; ++ private int fadeOut = DEFAULT_FADE_OUT; ++ ++ /** ++ * Sets the title to the given text. ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull BaseComponent title) { ++ return this.title(new BaseComponent[]{checkNotNull(title, "title")}); ++ } ++ ++ /** ++ * Sets the title to the given text. ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull BaseComponent[] title) { ++ this.title = checkNotNull(title, "title"); ++ return this; ++ } ++ ++ /** ++ * Sets the title to the given text. ++ * ++ *

      It is recommended to the {@link BaseComponent} methods.

      ++ * ++ * @param title the title text ++ * @return this builder instance ++ * @throws NullPointerException if the title is null ++ */ ++ @NotNull ++ public Builder title(@NotNull String title) { ++ return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title"))); ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable BaseComponent subtitle) { ++ return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle}); ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable BaseComponent[] subtitle) { ++ this.subtitle = subtitle; ++ return this; ++ } ++ ++ /** ++ * Sets the subtitle to the given text. ++ * ++ *

      It is recommended to the {@link BaseComponent} methods.

      ++ * ++ * @param subtitle the title text ++ * @return this builder instance ++ */ ++ @NotNull ++ public Builder subtitle(@Nullable String subtitle) { ++ return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle)); ++ } ++ ++ /** ++ * Sets the number of ticks for the title to fade in ++ * ++ * @param fadeIn the number of ticks to fade in ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder fadeIn(int fadeIn) { ++ checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn); ++ this.fadeIn = fadeIn; ++ return this; ++ } ++ ++ ++ /** ++ * Sets the number of ticks for the title to stay. ++ * ++ * @param stay the number of ticks to stay ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder stay(int stay) { ++ checkArgument(stay >= 0, "Negative stay: %s", stay); ++ this.stay = stay; ++ return this; ++ } ++ ++ /** ++ * Sets the number of ticks for the title to fade out. ++ * ++ * @param fadeOut the number of ticks to fade out ++ * @return this builder instance ++ * @throws IllegalArgumentException if it is negative ++ */ ++ @NotNull ++ public Builder fadeOut(int fadeOut) { ++ checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut); ++ this.fadeOut = fadeOut; ++ return this; ++ } ++ ++ /** ++ * Create a title based on the values in the builder. ++ * ++ * @return a title from the values in this builder ++ * @throws IllegalStateException if title isn't specified ++ */ ++ @NotNull ++ public Title build() { ++ checkState(title != null, "Title not specified"); ++ return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut); ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 17f55697d02d7b9c9b42c4b89a33db9207622a36..01fcff92daec5d4bf4b2b9213925cd2604cdec98 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1288,6 +1288,131 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { + spigot().sendMessage(position, components); + } ++ ++ /** ++ * Set the text displayed in the player list header and footer for this player ++ * ++ * @param header content for the top of the player list ++ * @param footer content for the bottom of the player list ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent[] header, @Nullable net.md_5.bungee.api.chat.BaseComponent[] footer); ++ ++ /** ++ * Set the text displayed in the player list header and footer for this player ++ * ++ * @param header content for the top of the player list ++ * @param footer content for the bottom of the player list ++ * @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void setPlayerListHeaderFooter(@Nullable net.md_5.bungee.api.chat.BaseComponent header, @Nullable net.md_5.bungee.api.chat.BaseComponent footer); ++ ++ /** ++ * Update the times for titles displayed to the player ++ * ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Update the subtitle of titles displayed to the player ++ * ++ * @param subtitle Subtitle to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle); ++ ++ /** ++ * Update the subtitle of titles displayed to the player ++ * ++ * @param subtitle Subtitle to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle); ++ ++ /** ++ * Show the given title to the player, along with the last subtitle set, using the last set times ++ * ++ * @param title Title to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title); ++ ++ /** ++ * Show the given title to the player, along with the last subtitle set, using the last set times ++ * ++ * @param title Title to set ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title); ++ ++ /** ++ * Show the given title and subtitle to the player using the given times ++ * ++ * @param title big text ++ * @param subtitle little text under it ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent[] title, @Nullable net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Show the given title and subtitle to the player using the given times ++ * ++ * @param title big text ++ * @param subtitle little text under it ++ * @param fadeInTicks ticks to fade-in ++ * @param stayTicks ticks to stay visible ++ * @param fadeOutTicks ticks to fade-out ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ public void showTitle(@Nullable net.md_5.bungee.api.chat.BaseComponent title, @Nullable net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks); ++ ++ /** ++ * Show the title to the player, overriding any previously displayed title. ++ * ++ *

      This method overrides any previous title, use {@link #updateTitle(com.destroystokyo.paper.Title)} to change the existing one.

      ++ * ++ * @param title the title to send ++ * @throws NullPointerException if the title is null ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ void sendTitle(@NotNull com.destroystokyo.paper.Title title); ++ ++ /** ++ * Show the title to the player, overriding any previously displayed title. ++ * ++ *

      This method doesn't override previous titles, but changes their values.

      ++ * ++ * @param title the title to send ++ * @throws NullPointerException if title is null ++ * @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)} ++ */ ++ @Deprecated ++ void updateTitle(@NotNull com.destroystokyo.paper.Title title); ++ ++ /** ++ * Hide any title that is currently visible to the player ++ * ++ * @deprecated use {@link #clearTitle()} ++ */ ++ @Deprecated ++ public void hideTitle(); + // Paper end + + /** diff --git a/patches/api/0025-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api/0025-Add-methods-for-working-with-arrows-stuck-in-living-.patch new file mode 100644 index 000000000000..895f0ff60829 --- /dev/null +++ b/patches/api/0025-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: mrapple +Date: Sun, 25 Nov 2012 13:47:27 -0600 +Subject: [PATCH] Add methods for working with arrows stuck in living entities + +Upstream added methods for this so the original methods +are now deprecated + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 7afa4674a79f24db6344f02038ed9e2310c9cc66..598c88f02a764abe62f9f10833b2c499a0fb00ff 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -243,12 +243,44 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + public int getArrowsInBody(); + ++ // Paper start ++ /** ++ * Set the amount of arrows in the entity's body. ++ *

      ++ * Does not fire the {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent}. ++ * ++ * @param count amount of arrows in entity's body ++ */ ++ default void setArrowsInBody(final int count) { ++ this.setArrowsInBody(count, false); ++ } ++ // Paper end ++ + /** + * Set the amount of arrows in the entity's body. + * + * @param count amount of arrows in entity's body ++ * @param fireEvent whether to fire the {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent} event ++ */ ++ void setArrowsInBody(int count, boolean fireEvent); // Paper ++ ++ // Paper start - Add methods for working with arrows stuck in living entities ++ /** ++ * Sets the amount of ticks before the next arrow gets removed from the entities body. ++ *

      ++ * A value of 0 will cause the server to re-calculate the amount of ticks on the next tick. ++ * ++ * @param ticks Amount of ticks + */ +- public void setArrowsInBody(int count); ++ void setNextArrowRemoval(@org.jetbrains.annotations.Range(from = 0, to = Integer.MAX_VALUE) int ticks); ++ ++ /** ++ * Gets the amount of ticks before the next arrow gets removed from the entities body. ++ * ++ * @return ticks Amount of ticks ++ */ ++ int getNextArrowRemoval(); ++ // Paper end - Add methods for working with arrows stuck in living entities + + /** + * Returns the living entity's current maximum no damage ticks. +@@ -787,4 +819,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + * @return Whether the entity is invisible + */ + public boolean isInvisible(); ++ ++ // Paper start ++ /** ++ * Get the number of arrows stuck in this entity ++ * @return Number of arrows stuck ++ * @deprecated use {@link #getArrowsInBody()} ++ */ ++ @Deprecated ++ int getArrowsStuck(); ++ ++ /** ++ * Set the number of arrows stuck in this entity ++ * ++ * @param arrows Number of arrows to stick in this entity ++ * @deprecated use {@link #setArrowsInBody(int, boolean)}. This method previously fired {@link org.bukkit.event.entity.ArrowBodyCountChangeEvent} so if ++ * you want to retain exact functionality, pass {@code true} for {@code fireEvent}. ++ */ ++ @Deprecated ++ void setArrowsStuck(int arrows); ++ // Paper end + } diff --git a/patches/api/0026-Complete-resource-pack-API.patch b/patches/api/0026-Complete-resource-pack-API.patch new file mode 100644 index 000000000000..ec794ae5352a --- /dev/null +++ b/patches/api/0026-Complete-resource-pack-API.patch @@ -0,0 +1,212 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 4 Apr 2015 22:59:54 -0400 +Subject: [PATCH] Complete resource pack API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 01fcff92daec5d4bf4b2b9213925cd2604cdec98..cb758b5907aa0c214123550fe14ccfdacbc6b208 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2252,6 +2252,180 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void setResourcePack(@NotNull UUID uuid, @NotNull String url, byte @Nullable [] hash, net.kyori.adventure.text.@Nullable Component prompt, boolean force); + // Paper end + ++ // Paper start - more resource pack API ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached the same ++ * resource pack in the past, it will perform a quick timestamp check ++ * over the network to determine if the resource pack has changed and ++ * needs to be downloaded again. When this request is sent for the very ++ * first time from a given server, the client will first display a ++ * confirmation GUI to the player before proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of ++ * the resource pack file. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ */ ++ default void setResourcePack(final @NotNull String url, final @NotNull String hash) { ++ this.setResourcePack(url, hash, false); ++ } ++ ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached the same ++ * resource pack in the past, it will perform a quick timestamp check ++ * over the network to determine if the resource pack has changed and ++ * needs to be downloaded again. When this request is sent for the very ++ * first time from a given server, the client will first display a ++ * confirmation GUI to the player before proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of ++ * the resource pack file. ++ * @param required Marks if the resource pack should be required by the client ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ */ ++ default void setResourcePack(final @NotNull String url, final @NotNull String hash, final boolean required) { ++ this.setResourcePack(url, hash, required, null); ++ } ++ ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached the same ++ * resource pack in the past, it will perform a quick timestamp check ++ * over the network to determine if the resource pack has changed and ++ * needs to be downloaded again. When this request is sent for the very ++ * first time from a given server, the client will first display a ++ * confirmation GUI to the player before proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      ++ * ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of ++ * the resource pack file. ++ * @param required Marks if the resource pack should be required by the client ++ * @param resourcePackPrompt A Prompt to be displayed in the client request ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ */ ++ default void setResourcePack(final @NotNull String url, final @NotNull String hash, final boolean required, final net.kyori.adventure.text.@Nullable Component resourcePackPrompt) { ++ this.setResourcePack(UUID.nameUUIDFromBytes(url.getBytes(java.nio.charset.StandardCharsets.UTF_8)), url, hash, resourcePackPrompt, required); ++ } ++ ++ /** ++ * Request that the player's client download and switch resource packs. ++ *

      ++ * The player's client will download the new resource pack asynchronously ++ * in the background, and will automatically switch to it once the ++ * download is complete. If the client has downloaded and cached the same ++ * resource pack in the past, it will perform a quick timestamp check ++ * over the network to determine if the resource pack has changed and ++ * needs to be downloaded again. When this request is sent for the very ++ * first time from a given server, the client will first display a ++ * confirmation GUI to the player before proceeding with the download. ++ *

      ++ * Notes: ++ *

        ++ *
      • Players can disable server resources on their client, in which ++ * case this method will have no affect on them. ++ *
      • To remove a resource pack you can use ++ * {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}. ++ *
      ++ * ++ * @param uuid Unique resource pack ID. ++ * @param url The URL from which the client will download the resource ++ * pack. The string must contain only US-ASCII characters and should ++ * be encoded as per RFC 1738. ++ * @param hash A 40 character hexadecimal and lowercase SHA-1 digest of ++ * the resource pack file. ++ * @param resourcePackPrompt A Prompt to be displayed in the client request ++ * @param required Marks if the resource pack should be required by the client ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ */ ++ default void setResourcePack(final @NotNull UUID uuid, final @NotNull String url, final @NotNull String hash, final net.kyori.adventure.text.@Nullable Component resourcePackPrompt, final boolean required) { ++ this.sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest.resourcePackRequest() ++ .required(required) ++ .replace(true) ++ .prompt(resourcePackPrompt) ++ .packs(net.kyori.adventure.resource.ResourcePackInfo.resourcePackInfo(uuid, java.net.URI.create(url), hash)) ++ ); ++ } ++ ++ /** ++ * Gets the most recent resource pack status from the player. ++ * ++ * @return the most recent status or null ++ */ ++ org.bukkit.event.player.PlayerResourcePackStatusEvent.@Nullable Status getResourcePackStatus(); ++ ++ /** ++ * Gets the most recent pack hash from the player. ++ * ++ * @return the most recent hash or null ++ * @deprecated This is no longer sent from the client and will always be null ++ */ ++ @Deprecated(forRemoval = true, since = "1.13.2") ++ @org.jetbrains.annotations.Contract("-> null") ++ default @Nullable String getResourcePackHash() { ++ return null; ++ } ++ ++ /** ++ * Gets if the last resource pack status from the player ++ * was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED}. ++ * ++ * @return true if last status was successfully loaded ++ */ ++ default boolean hasResourcePack() { ++ return this.getResourcePackStatus() == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; ++ } ++ // Paper end - more resource pack API ++ + /** + * Request that the player's client download and include another resource pack. + *

      +diff --git a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java +index e2c4f9a0456cef345772d57b4d9c6e7d9598dd53..e4c32b21ab013703a6a1b07a1ad564d914ebe83f 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerResourcePackStatusEvent.java +@@ -21,6 +21,16 @@ public class PlayerResourcePackStatusEvent extends PlayerEvent { + this.status = resourcePackStatus; + } + ++ // Paper start - add hash (not used anymore) ++ /** ++ * @deprecated Hash does not seem to ever be set ++ */ ++ @Deprecated(forRemoval = true) ++ public String getHash() { ++ return null; ++ } ++ // Paper end ++ + /** + * Gets the unique ID of this pack. + * diff --git a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch b/patches/api/0027-Add-a-call-helper-to-Event.patch similarity index 100% rename from Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch rename to patches/api/0027-Add-a-call-helper-to-Event.patch diff --git a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch b/patches/api/0028-Add-sender-name-to-commands.yml-replacement.patch similarity index 100% rename from Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch rename to patches/api/0028-Add-sender-name-to-commands.yml-replacement.patch diff --git a/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch new file mode 100644 index 000000000000..0db1a8a7c050 --- /dev/null +++ b/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William +Date: Fri, 18 Mar 2016 03:28:07 -0400 +Subject: [PATCH] Add command to reload permissions.yml and require confirm to + reload + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 1ada54827acfaacab0a32ae5d55def952547c352..13fa39ed3d5ffa8a459d68d1e240e869ba42ac32 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2396,6 +2396,13 @@ public final class Bukkit { + public static org.bukkit.command.CommandMap getCommandMap() { + return server.getCommandMap(); + } ++ ++ /** ++ * Reload the Permissions in permissions.yml ++ */ ++ public static void reloadPermissions() { ++ server.reloadPermissions(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 93d924c586803161820707af823c352f7c5d40e1..6567d1746f5cf16c9f3518203dd9916ff916ca68 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2096,4 +2096,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + Spigot spigot(); + // Spigot end ++ ++ void reloadPermissions(); // Paper + } +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..5fa9d648bc780e874f658597f1a24715bccac5cb 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -13,15 +13,35 @@ public class ReloadCommand extends BukkitCommand { + public ReloadCommand(@NotNull String name) { + super(name); + this.description = "Reloads the server configuration and plugins"; +- this.usageMessage = "/reload"; ++ this.usageMessage = "/reload [permissions]"; // Paper + this.setPermission("bukkit.command.reload"); + this.setAliases(Arrays.asList("rl")); + } + + @Override +- public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { ++ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper + if (!testPermission(sender)) return true; + ++ // Paper start - Reload permissions.yml & require confirm ++ boolean confirmed = System.getProperty("LetMeReload") != null; ++ if (args.length == 1) { ++ if (args[0].equalsIgnoreCase("permissions")) { ++ Bukkit.getServer().reloadPermissions(); ++ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Permissions successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN)); ++ return true; ++ } else if ("confirm".equalsIgnoreCase(args[0])) { ++ confirmed = true; ++ } else { ++ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Usage: " + usageMessage, net.kyori.adventure.text.format.NamedTextColor.RED)); ++ return true; ++ } ++ } ++ if (!confirmed) { ++ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Are you sure you wish to reload your server? Doing so may cause bugs and memory leaks. It is recommended to restart instead of using /reload. To confirm, please type ", net.kyori.adventure.text.format.NamedTextColor.RED).append(net.kyori.adventure.text.Component.text("/reload confirm", net.kyori.adventure.text.format.NamedTextColor.YELLOW))); ++ return true; ++ } ++ // Paper end ++ + Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues when using some plugins."); + Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); + Bukkit.reload(); +@@ -33,6 +53,6 @@ public class ReloadCommand extends BukkitCommand { + @NotNull + @Override + public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { +- return Collections.emptyList(); ++ return java.util.Collections.singletonList("permissions"); // Paper + } + } diff --git a/patches/api/0030-Custom-replacement-for-eaten-items.patch b/patches/api/0030-Custom-replacement-for-eaten-items.patch new file mode 100644 index 000000000000..90a728214859 --- /dev/null +++ b/patches/api/0030-Custom-replacement-for-eaten-items.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sun, 21 Jun 2015 15:05:21 -0400 +Subject: [PATCH] Custom replacement for eaten items + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java +index 36b16b6076321310b6ed60e515064e506b706b58..3208dedfb6769e3e8c2ebeb17c0e02d80adf233a 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java +@@ -24,6 +24,7 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { + private boolean isCancelled = false; + private ItemStack item; + private final EquipmentSlot hand; ++ @Nullable private ItemStack replacement; // Paper + + /** + * @param player the player consuming +@@ -82,6 +83,29 @@ public class PlayerItemConsumeEvent extends PlayerEvent implements Cancellable { + return hand; + } + ++ // Paper start ++ /** ++ * Return the custom item stack that will replace the consumed item, or null if no ++ * custom replacement has been set (which means the default replacement will be used). ++ * ++ * @return The custom item stack that will replace the consumed item or null ++ */ ++ @Nullable ++ public ItemStack getReplacement() { ++ return this.replacement; ++ } ++ ++ /** ++ * Set a custom item stack to replace the consumed item. Pass null to clear any custom ++ * stack that has been set and use the default replacement. ++ * ++ * @param replacement Replacement item to set, null to clear any custom stack and use default ++ */ ++ public void setReplacement(@Nullable ItemStack replacement) { ++ this.replacement = replacement; ++ } ++ // Paper end ++ + @Override + public boolean isCancelled() { + return this.isCancelled; diff --git a/patches/api/0031-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/api/0031-Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 000000000000..23dad970bc3a --- /dev/null +++ b/patches/api/0031-Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 20:26:34 -0400 +Subject: [PATCH] Entity AddTo/RemoveFrom World Events + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..11f8540a4752cf4d2112eff48bcca3b935c9f8b1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityAddToWorldEvent.java +@@ -0,0 +1,44 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.World; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired any time an entity is being added to the world for any reason (including a chunk loading). ++ *

      ++ * Not to be confused with {@link CreatureSpawnEvent} ++ */ ++@NullMarked ++public class EntityAddToWorldEvent extends EntityEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final World world; ++ ++ @ApiStatus.Internal ++ public EntityAddToWorldEvent(final Entity entity, final World world) { ++ super(entity); ++ this.world = world; ++ } ++ ++ /** ++ * @return The world that the entity is being added to ++ */ ++ public World getWorld() { ++ return this.world; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5ad5632d4d47d8b42e4f2af19c0fe6cf94ac5643 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java +@@ -0,0 +1,42 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.World; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired any time an entity is being removed from a world for any reason (including a chunk unloading). ++ * Note: The entity is updated prior to this event being called, as such, the entity's world may not be equal to {@link #getWorld()}. ++ */ ++@NullMarked ++public class EntityRemoveFromWorldEvent extends EntityEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final World world; ++ ++ @ApiStatus.Internal ++ public EntityRemoveFromWorldEvent(final Entity entity, final World world) { ++ super(entity); ++ this.world = world; ++ } ++ ++ /** ++ * @return The world that the entity is being removed from ++ */ ++ public World getWorld() { ++ return this.world; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/entity/EntityRemoveEvent.java b/src/main/java/org/bukkit/event/entity/EntityRemoveEvent.java +index e32df91d911bae42c8137c6f952a6ac6a94d27e0..8ed5d1ccc44951089999db360219b556db89b4ba 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityRemoveEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityRemoveEvent.java +@@ -1,5 +1,6 @@ + package org.bukkit.event.entity; + ++import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; + import org.bukkit.entity.Entity; + import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.ApiStatus; +@@ -11,8 +12,9 @@ import org.jetbrains.annotations.NotNull; + * This event should only be used for monitoring. The result + * of modifying the entity during or after this event is unspecified. + * This event is not called for a {@link org.bukkit.entity.Player}. ++ * @deprecated use {@link EntityRemoveFromWorldEvent} instead + */ +-@ApiStatus.Experimental ++@Deprecated(forRemoval = true) + public class EntityRemoveEvent extends EntityEvent { + + private static final HandlerList handlers = new HandlerList(); +@@ -112,5 +114,6 @@ public class EntityRemoveEvent extends EntityEvent { + * When the chunk an entity is in gets unloaded. + */ + UNLOAD, ++ DISCARD + } + } diff --git a/patches/api/0032-EntityPathfindEvent.patch b/patches/api/0032-EntityPathfindEvent.patch new file mode 100644 index 000000000000..5a2e0c0ffaf0 --- /dev/null +++ b/patches/api/0032-EntityPathfindEvent.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 28 Mar 2016 21:15:34 -0400 +Subject: [PATCH] EntityPathfindEvent + +Fires when an Entity decides to start moving to a location. + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8624e0a528985c9b118f5e8a0f33d3286af2fc36 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityPathfindEvent.java +@@ -0,0 +1,84 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Fired when an Entity decides to start moving towards a location. ++ *

      ++ * This event does not fire for the entities actual movement. Only when it ++ * is choosing to start moving to a location. ++ */ ++@NullMarked ++public class EntityPathfindEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final @Nullable Entity targetEntity; ++ private final Location location; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityPathfindEvent(final Entity entity, final Location location, final @Nullable Entity targetEntity) { ++ super(entity); ++ this.targetEntity = targetEntity; ++ this.location = location; ++ } ++ ++ /** ++ * The Entity that is pathfinding. ++ * ++ * @return The Entity that is pathfinding. ++ */ ++ @Override ++ public Entity getEntity() { ++ return this.entity; ++ } ++ ++ /** ++ * If the Entity is trying to pathfind to an entity, this is the entity in relation. ++ *
      ++ * Otherwise, this will return {@code null}. ++ * ++ * @return The entity target or {@code null} ++ */ ++ public @Nullable Entity getTargetEntity() { ++ return this.targetEntity; ++ } ++ ++ /** ++ * The Location of where the entity is about to move to. ++ *
      ++ * Note that if the target happened to of been an entity ++ * ++ * @return Location of where the entity is trying to pathfind to. ++ */ ++ public Location getLoc() { ++ return this.location.clone(); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0033-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/patches/api/0033-Reduce-thread-synchronization-in-MetadataStoreBase.patch new file mode 100644 index 000000000000..9bc7e49e8df9 --- /dev/null +++ b/patches/api/0033-Reduce-thread-synchronization-in-MetadataStoreBase.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: crast +Date: Sat, 1 Jun 2013 13:52:30 -0600 +Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase + +Use ConcurrentHashMap to allow thread-safe access methods and very +limited synchronized portions to allow much higher concurrency in +MetadataStore as well as far less locking, especially on reads + +diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +index 6886a7003fb76d07e0fa9c1c352c56480f08a0db..a0698522f01619c9d37474f4bd55a17de58fff89 100644 +--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java ++++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +@@ -12,7 +12,7 @@ import org.bukkit.plugin.Plugin; + import org.jetbrains.annotations.NotNull; + + public abstract class MetadataStoreBase { +- private Map> metadataMap = new HashMap>(); ++ private Map> metadataMap = new java.util.concurrent.ConcurrentHashMap>(); // Paper + + /** + * Adds a metadata value to an object. Each metadata value is owned by a +@@ -46,7 +46,9 @@ public abstract class MetadataStoreBase { + entry = new WeakHashMap(1); + metadataMap.put(key, entry); + } +- entry.put(owningPlugin, newMetadataValue); ++ synchronized (entry) { ++ entry.put(owningPlugin, newMetadataValue); ++ } + } + + /** +@@ -60,10 +62,11 @@ public abstract class MetadataStoreBase { + * @see MetadataStore#getMetadata(Object, String) + */ + @NotNull +- public synchronized List getMetadata(@NotNull T subject, @NotNull String metadataKey) { ++ public List getMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper + String key = disambiguate(subject, metadataKey); +- if (metadataMap.containsKey(key)) { +- Collection values = metadataMap.get(key).values(); ++ Map entry = metadataMap.get(key); ++ if (entry != null) { ++ Collection values = entry.values(); + return Collections.unmodifiableList(new ArrayList(values)); + } else { + return Collections.emptyList(); +@@ -78,7 +81,7 @@ public abstract class MetadataStoreBase { + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ +- public synchronized boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { ++ public boolean hasMetadata(@NotNull T subject, @NotNull String metadataKey) { // Paper + String key = disambiguate(subject, metadataKey); + return metadataMap.containsKey(key); + } +@@ -94,17 +97,18 @@ public abstract class MetadataStoreBase { + * @see MetadataStore#removeMetadata(Object, String, + * org.bukkit.plugin.Plugin) + */ +- public synchronized void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { ++ public void removeMetadata(@NotNull T subject, @NotNull String metadataKey, @NotNull Plugin owningPlugin) { // Paper + Preconditions.checkArgument(owningPlugin != null, "Plugin cannot be null"); + String key = disambiguate(subject, metadataKey); + Map entry = metadataMap.get(key); + if (entry == null) { + return; + } +- +- entry.remove(owningPlugin); +- if (entry.isEmpty()) { +- metadataMap.remove(key); ++ synchronized (entry) { ++ entry.remove(owningPlugin); ++ if (entry.isEmpty()) { ++ metadataMap.remove(key); ++ } + } + } + +@@ -117,7 +121,7 @@ public abstract class MetadataStoreBase { + * @throws IllegalArgumentException If plugin is null + * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) + */ +- public synchronized void invalidateAll(@NotNull Plugin owningPlugin) { ++ public void invalidateAll(@NotNull Plugin owningPlugin) { // Paper + Preconditions.checkArgument(owningPlugin != null, "Plugin cannot be null"); + for (Map values : metadataMap.values()) { + if (values.containsKey(owningPlugin)) { diff --git a/patches/api/0034-Add-MetadataStoreBase.removeAll-Plugin.patch b/patches/api/0034-Add-MetadataStoreBase.removeAll-Plugin.patch new file mode 100644 index 000000000000..2496de742350 --- /dev/null +++ b/patches/api/0034-Add-MetadataStoreBase.removeAll-Plugin.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 16 Jul 2013 21:26:50 -0400 +Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin) + +So that on reload, metadata will be cleared + +diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +index a0698522f01619c9d37474f4bd55a17de58fff89..a298baaa7a126515bb2802dd311f8487f3e5533f 100644 +--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java ++++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +@@ -5,6 +5,7 @@ import java.util.ArrayList; + import java.util.Collection; + import java.util.Collections; + import java.util.HashMap; ++import java.util.Iterator; // Paper + import java.util.List; + import java.util.Map; + import java.util.WeakHashMap; +@@ -130,6 +131,26 @@ public abstract class MetadataStoreBase { + } + } + ++ /** ++ * Removes all metadata in the metadata store that originates from the ++ * given plugin. ++ * ++ * @param owningPlugin the plugin requesting the invalidation. ++ * @throws IllegalArgumentException If plugin is null ++ */ ++ public void removeAll(@NotNull Plugin owningPlugin) { ++ Preconditions.checkNotNull(owningPlugin, "Plugin cannot be null"); ++ for (Iterator> iterator = metadataMap.values().iterator(); iterator.hasNext(); ) { ++ Map values = iterator.next(); ++ if (values.containsKey(owningPlugin)) { ++ values.remove(owningPlugin); ++ } ++ if (values.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ + /** + * Creates a unique name for the object receiving metadata by combining + * unique data from the subject with a metadataKey. diff --git a/patches/api/0035-Add-PlayerUseUnknownEntityEvent.patch b/patches/api/0035-Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 000000000000..49715a5255d3 --- /dev/null +++ b/patches/api/0035-Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Sat, 2 Apr 2016 05:08:36 -0400 +Subject: [PATCH] Add PlayerUseUnknownEntityEvent + +Adds the PlayerUseUnknownEntityEvent to be used by plugins dealing with +virtual entities/entities that are not actually known to the server. + +Co-authored-by: Nassim Jahnke + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9ff2bbf7f99df45cc626cad60bec4d14a8a04e3e +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerUseUnknownEntityEvent.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.util.Vector; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Represents an event that is called when a player right-clicks an unknown entity. ++ * Useful for plugins dealing with virtual entities (entities that aren't actually spawned on the server). ++ *
      ++ * This event may be called multiple times per interaction with different interaction hands ++ * and with or without the clicked position. ++ */ ++@NullMarked ++public class PlayerUseUnknownEntityEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final int entityId; ++ private final boolean attack; ++ private final EquipmentSlot hand; ++ private final @Nullable Vector clickedPosition; ++ ++ @ApiStatus.Internal ++ public PlayerUseUnknownEntityEvent(final Player player, final int entityId, final boolean attack, final EquipmentSlot hand, final @Nullable Vector clickedPosition) { ++ super(player); ++ this.entityId = entityId; ++ this.attack = attack; ++ this.hand = hand; ++ this.clickedPosition = clickedPosition; ++ } ++ ++ /** ++ * Returns the entity id of the unknown entity that was interacted with. ++ * ++ * @return the entity id of the entity that was interacted with ++ */ ++ public int getEntityId() { ++ return this.entityId; ++ } ++ ++ /** ++ * Returns whether the interaction was an attack. ++ * ++ * @return {@code true} if the player is attacking the entity, {@code false} if the player is interacting with the entity ++ */ ++ public boolean isAttack() { ++ return this.attack; ++ } ++ ++ /** ++ * Returns the hand used to perform this interaction. ++ * ++ * @return the hand used to interact ++ */ ++ public EquipmentSlot getHand() { ++ return this.hand; ++ } ++ ++ /** ++ * Returns the position relative to the entity that was clicked, or {@code null} if not available. ++ * See {@link PlayerInteractAtEntityEvent} for more details. ++ * ++ * @return the position relative to the entity that was clicked, or {@code null} if not available ++ * @see PlayerInteractAtEntityEvent ++ */ ++ public @Nullable Vector getClickedRelativePosition() { ++ return this.clickedPosition != null ? this.clickedPosition.clone() : null; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0036-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/api/0036-Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 000000000000..30a767b777a4 --- /dev/null +++ b/patches/api/0036-Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,270 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 13 Apr 2016 20:20:18 -0700 +Subject: [PATCH] Add handshake event to allow plugins to handle client + handshaking logic themselves + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aea04fb357f5728195fd9c9bdcd6304a0b953c45 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerHandshakeEvent.java +@@ -0,0 +1,257 @@ ++package com.destroystokyo.paper.event.player; ++ ++import com.google.common.base.Preconditions; ++import java.util.UUID; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * This event is fired during a player handshake. ++ *

      ++ * If there are no listeners listening to this event, the logic default ++ * to your server platform will be run. ++ * ++ *

      WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS

      ++ */ ++@NullMarked ++public class PlayerHandshakeEvent extends Event implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final String originalHandshake; ++ private final String originalSocketAddressHostname; ++ private @Nullable String serverHostname; ++ private @Nullable String socketAddressHostname; ++ private @Nullable UUID uniqueId; ++ private @Nullable String propertiesJson; ++ private boolean failed; ++ private Component failMessage = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.YELLOW); ++ ++ private boolean cancelled; ++ ++ @Deprecated ++ @ApiStatus.Internal ++ public PlayerHandshakeEvent(final String originalHandshake, final boolean cancelled) { ++ this(originalHandshake, "127.0.0.1", cancelled); ++ } ++ ++ @ApiStatus.Internal ++ public PlayerHandshakeEvent(final String originalHandshake, final String originalSocketAddressHostname, final boolean cancelled) { ++ super(true); ++ this.originalHandshake = originalHandshake; ++ this.originalSocketAddressHostname = originalSocketAddressHostname; ++ this.cancelled = cancelled; ++ } ++ ++ /** ++ * Determines if this event is cancelled. ++ *

      ++ * When this event is cancelled, custom handshake logic will not ++ * be processed. ++ * ++ * @return {@code true} if this event is cancelled, {@code false} otherwise ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Sets if this event is cancelled. ++ *

      ++ * When this event is cancelled, custom handshake logic will not ++ * be processed. ++ * ++ * @param cancel {@code true} if this event is cancelled, {@code false} otherwise ++ */ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ /** ++ * Gets the original handshake string. ++ * ++ * @return the original handshake string ++ */ ++ public String getOriginalHandshake() { ++ return this.originalHandshake; ++ } ++ ++ /** ++ * Gets the original socket address hostname. ++ * ++ *

      This does not include the port.

      ++ *

      In cases where this event is manually fired and the plugin wasn't updated yet, the default is {@code "127.0.0.1"}.

      ++ * ++ * @return the original socket address hostname ++ */ ++ public String getOriginalSocketAddressHostname() { ++ return this.originalSocketAddressHostname; ++ } ++ ++ /** ++ * Gets the server hostname string. ++ * ++ *

      This should not include the port.

      ++ * ++ * @return the server hostname string ++ */ ++ public @Nullable String getServerHostname() { ++ return this.serverHostname; ++ } ++ ++ /** ++ * Sets the server hostname string. ++ * ++ *

      This should not include the port.

      ++ * ++ * @param serverHostname the server hostname string ++ */ ++ public void setServerHostname(final String serverHostname) { ++ this.serverHostname = serverHostname; ++ } ++ ++ /** ++ * Gets the socket address hostname string. ++ * ++ *

      This should not include the port.

      ++ * ++ * @return the socket address hostname string ++ */ ++ public @Nullable String getSocketAddressHostname() { ++ return this.socketAddressHostname; ++ } ++ ++ /** ++ * Sets the socket address hostname string. ++ * ++ *

      This should not include the port.

      ++ * ++ * @param socketAddressHostname the socket address hostname string ++ */ ++ public void setSocketAddressHostname(final String socketAddressHostname) { ++ this.socketAddressHostname = socketAddressHostname; ++ } ++ ++ /** ++ * Gets the unique id. ++ * ++ * @return the unique id ++ */ ++ public @Nullable UUID getUniqueId() { ++ return this.uniqueId; ++ } ++ ++ /** ++ * Sets the unique id. ++ * ++ * @param uniqueId the unique id ++ */ ++ public void setUniqueId(final UUID uniqueId) { ++ this.uniqueId = uniqueId; ++ } ++ ++ /** ++ * Gets the profile properties. ++ * ++ *

      This should be a valid JSON string.

      ++ * ++ * @return the profile properties, as JSON ++ */ ++ public @Nullable String getPropertiesJson() { ++ return this.propertiesJson; ++ } ++ ++ /** ++ * Determines if authentication failed. ++ *

      ++ * When {@code true}, the client connecting will be disconnected ++ * with the {@link #getFailMessage() fail message}. ++ * ++ * @return {@code true} if authentication failed, {@code false} otherwise ++ */ ++ public boolean isFailed() { ++ return this.failed; ++ } ++ ++ /** ++ * Sets if authentication failed and the client should be disconnected. ++ *

      ++ * When {@code true}, the client connecting will be disconnected ++ * with the {@link #getFailMessage() fail message}. ++ * ++ * @param failed {@code true} if authentication failed, {@code false} otherwise ++ */ ++ public void setFailed(final boolean failed) { ++ this.failed = failed; ++ } ++ ++ /** ++ * Sets the profile properties. ++ * ++ *

      This should be a valid JSON string.

      ++ * ++ * @param propertiesJson the profile properties, as JSON ++ */ ++ public void setPropertiesJson(final String propertiesJson) { ++ this.propertiesJson = propertiesJson; ++ } ++ ++ /** ++ * Gets the message to display to the client when authentication fails. ++ * ++ * @return the message to display to the client ++ */ ++ public Component failMessage() { ++ return this.failMessage; ++ } ++ ++ /** ++ * Sets the message to display to the client when authentication fails. ++ * ++ * @param failMessage the message to display to the client ++ */ ++ public void failMessage(final Component failMessage) { ++ this.failMessage = failMessage; ++ } ++ ++ /** ++ * Gets the message to display to the client when authentication fails. ++ * ++ * @return the message to display to the client ++ * @deprecated use {@link #failMessage()} ++ */ ++ @Deprecated ++ public String getFailMessage() { ++ return LegacyComponentSerializer.legacySection().serialize(this.failMessage()); ++ } ++ ++ /** ++ * Sets the message to display to the client when authentication fails. ++ * ++ * @param failMessage the message to display to the client ++ * @deprecated use {@link #failMessage(Component)} ++ */ ++ @Deprecated ++ public void setFailMessage(final String failMessage) { ++ Preconditions.checkArgument(failMessage != null && !failMessage.isEmpty(), "fail message cannot be null or empty"); ++ this.failMessage(LegacyComponentSerializer.legacySection().deserialize(failMessage)); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0037-Arrow-pickup-rule-API.patch b/patches/api/0037-Arrow-pickup-rule-API.patch new file mode 100644 index 000000000000..37a434e032c0 --- /dev/null +++ b/patches/api/0037-Arrow-pickup-rule-API.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jedediah Smith +Date: Fri, 4 Mar 2016 03:13:18 -0500 +Subject: [PATCH] Arrow pickup rule API + + +diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java +index 9cebf79b6217063fbce395b655261ee4ab0f4e45..c901990454ec930169b0dc561987bea101f9b6ae 100644 +--- a/src/main/java/org/bukkit/entity/AbstractArrow.java ++++ b/src/main/java/org/bukkit/entity/AbstractArrow.java +@@ -186,4 +186,38 @@ public interface AbstractArrow extends Projectile { + */ + CREATIVE_ONLY + } ++ ++ // Paper start ++ /** ++ * Gets the {@link PickupRule} for this arrow. ++ * ++ *

      This is generally {@link PickupRule#ALLOWED} only if the arrow was ++ * not fired from a bow with the infinity enchantment.

      ++ * ++ * @return The pickup rule ++ * @deprecated Use {@link Arrow#getPickupStatus()} as an upstream compatible replacement for this function ++ */ ++ @Deprecated ++ default PickupRule getPickupRule() { ++ return PickupRule.valueOf(this.getPickupStatus().name()); ++ } ++ ++ /** ++ * Set the rule for which players can pickup this arrow as an item. ++ * ++ * @param rule The pickup rule ++ * @deprecated Use {@link Arrow#setPickupStatus(PickupStatus)} with {@link PickupStatus} as an upstream compatible replacement for this function ++ */ ++ @Deprecated ++ default void setPickupRule(PickupRule rule) { ++ this.setPickupStatus(PickupStatus.valueOf(rule.name())); ++ } ++ ++ @Deprecated ++ enum PickupRule { ++ DISALLOWED, ++ ALLOWED, ++ CREATIVE_ONLY; ++ } ++ // Paper end + } diff --git a/Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/api/0038-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/api/0038-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/patches/api/0039-LootTable-API.patch b/patches/api/0039-LootTable-API.patch new file mode 100644 index 000000000000..75ed22dfb5ff --- /dev/null +++ b/patches/api/0039-LootTable-API.patch @@ -0,0 +1,463 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 1 May 2016 15:19:49 -0400 +Subject: [PATCH] LootTable API + +Provides API to control what Loot Table an object uses. + +Also provides an Event to control if a lootable inventory should +auto replenish for a player. + +Provides methods to determine players looted state for an object + +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6a03252d66a3e13c1960568ea23f6dcc673f34af +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.block.Block; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents an Inventory that can generate loot, such as Chests inside of Fortresses and Mineshafts ++ */ ++@NullMarked ++public interface LootableBlockInventory extends LootableInventory { ++ ++ /** ++ * Gets the block that is lootable ++ * @return The Block ++ */ ++ Block getBlock(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..31ca54dea65dc0363a0ff7991ba5be3b06533876 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java +@@ -0,0 +1,17 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.entity.Entity; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents an Inventory that can generate loot, such as Minecarts inside of Mineshafts ++ */ ++@NullMarked ++public interface LootableEntityInventory extends LootableInventory { ++ ++ /** ++ * Gets the entity that is lootable ++ * @return The Entity ++ */ ++ Entity getEntity(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9fb621200fb3969e8e440341e906acc3547b4039 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java +@@ -0,0 +1,128 @@ ++package com.destroystokyo.paper.loottable; ++ ++import java.util.UUID; ++import org.bukkit.entity.Player; ++import org.bukkit.loot.Lootable; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Represents an Inventory that contains a Loot Table associated to it that will ++ * automatically fill on first open. ++ *

      ++ * A new feature and API is provided to support automatically refreshing the contents ++ * of the inventory based on that Loot Table after a configurable amount of time has passed. ++ *

      ++ * The behavior of how the Inventory is filled based on the loot table may vary based ++ * on Minecraft versions and the Loot Table feature. ++ */ ++@NullMarked ++public interface LootableInventory extends Lootable { ++ ++ /** ++ * Server owners have to enable whether an object in a world should refill ++ * ++ * @return If the world this inventory is currently in has Replenishable Lootables enabled ++ */ ++ boolean isRefillEnabled(); ++ ++ /** ++ * Whether this object has ever been filled ++ * ++ * @return Has ever been filled ++ */ ++ boolean hasBeenFilled(); ++ ++ /** ++ * Has this player ever looted this block ++ * ++ * @param player The player to check ++ * @return Whether this player has looted this block ++ */ ++ default boolean hasPlayerLooted(final Player player) { ++ return this.hasPlayerLooted(player.getUniqueId()); ++ } ++ ++ /** ++ * Checks if this player can loot this block. Takes into account the "restrict player reloot" settings ++ * ++ * @param player the player to check ++ * @return Whether this player can loot this block ++ */ ++ boolean canPlayerLoot(UUID player); ++ ++ /** ++ * Has this player ever looted this block ++ * ++ * @param player The player to check ++ * @return Whether this player has looted this block ++ */ ++ boolean hasPlayerLooted(UUID player); ++ ++ /** ++ * Gets the timestamp, in milliseconds, of when the player last looted this object ++ * ++ * @param player The player to check ++ * @return Timestamp last looted, or null if player has not looted this object ++ */ ++ default @Nullable Long getLastLooted(final Player player) { ++ return this.getLastLooted(player.getUniqueId()); ++ } ++ ++ /** ++ * Gets the timestamp, in milliseconds, of when the player last looted this object ++ * ++ * @param player The player to check ++ * @return Timestamp last looted, or null if player has not looted this object ++ */ ++ @Nullable Long getLastLooted(UUID player); ++ ++ /** ++ * Change the state of whether a player has looted this block ++ * ++ * @param player The player to change state for ++ * @param looted true to add player to looted list, false to remove ++ * @return The previous state of whether the player had looted this or not ++ */ ++ default boolean setHasPlayerLooted(final Player player, final boolean looted) { ++ return this.setHasPlayerLooted(player.getUniqueId(), looted); ++ } ++ ++ /** ++ * Change the state of whether a player has looted this block ++ * ++ * @param player The player to change state for ++ * @param looted true to add player to looted list, false to remove ++ * @return The previous state of whether the player had looted this or not ++ */ ++ boolean setHasPlayerLooted(UUID player, boolean looted); ++ ++ /** ++ * Returns Whether this object has been filled and now has a pending refill ++ * ++ * @return Has pending refill ++ */ ++ boolean hasPendingRefill(); ++ ++ /** ++ * Gets the timestamp in milliseconds that the Lootable object was last refilled ++ * ++ * @return -1 if it was never refilled, or timestamp in milliseconds ++ */ ++ long getLastFilled(); ++ ++ /** ++ * Gets the timestamp in milliseconds that the Lootable object will refill ++ * ++ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds ++ */ ++ long getNextRefill(); ++ ++ /** ++ * Sets the timestamp in milliseconds of the next refill for this object ++ * ++ * @param refillAt timestamp in milliseconds. -1 to clear next refill ++ * @return The previous scheduled time to refill, or -1 if was not scheduled ++ */ ++ long setNextRefill(long refillAt); ++} +diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..994c2183db89fc40d5991d5e1906e4bd04db6291 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java +@@ -0,0 +1,46 @@ ++package com.destroystokyo.paper.loottable; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final LootableInventory inventory; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public LootableInventoryReplenishEvent(final Player player, final LootableInventory inventory) { ++ super(player); ++ this.inventory = inventory; ++ } ++ ++ public LootableInventory getInventory() { ++ return this.inventory; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/org/bukkit/block/Barrel.java b/src/main/java/org/bukkit/block/Barrel.java +index aa1bb7a1a1c94b0b029bb60026efbc7f55584dd7..d3789b2b7dd71d7c1872a0d84698d35a1884101b 100644 +--- a/src/main/java/org/bukkit/block/Barrel.java ++++ b/src/main/java/org/bukkit/block/Barrel.java +@@ -5,4 +5,4 @@ import org.bukkit.loot.Lootable; + /** + * Represents a captured state of a Barrel. + */ +-public interface Barrel extends Container, Lootable, Lidded { } ++public interface Barrel extends Container, com.destroystokyo.paper.loottable.LootableBlockInventory, Lidded { } // Paper +diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java +index b451191312e4fb19f2131c2d0a0c0337953f6c7c..db6affbc78106b2d93b41953b624a0bca0ca1d72 100644 +--- a/src/main/java/org/bukkit/block/Chest.java ++++ b/src/main/java/org/bukkit/block/Chest.java +@@ -1,5 +1,7 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; // Paper ++import org.bukkit.Nameable; // Paper + import org.bukkit.inventory.Inventory; + import org.bukkit.loot.Lootable; + import org.jetbrains.annotations.NotNull; +@@ -7,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a captured state of a chest. + */ +-public interface Chest extends Container, Lootable, Lidded { ++public interface Chest extends Container, LootableBlockInventory, Lidded { // Paper + + /** + * Gets the inventory of the chest block represented by this block state. +diff --git a/src/main/java/org/bukkit/block/Crafter.java b/src/main/java/org/bukkit/block/Crafter.java +index e004920ec1e13daaa2f0969a5cf97b6a7de25df9..8d2dd78fc588a6817dfede8040b9909a7d5bde67 100644 +--- a/src/main/java/org/bukkit/block/Crafter.java ++++ b/src/main/java/org/bukkit/block/Crafter.java +@@ -7,7 +7,7 @@ import org.jetbrains.annotations.ApiStatus; + * Represents a captured state of a crafter. + */ + @ApiStatus.Experimental +-public interface Crafter extends Container, Lootable { ++public interface Crafter extends Container, com.destroystokyo.paper.loottable.LootableBlockInventory { // Paper - LootTable API + + /** + * Gets the number of ticks which this block will remain in the crafting +diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java +index 74cd194c9a98245dc52e7e352d7d6c046e1e5cf3..07af1a3f011d4b96275f919d302ac367198e923e 100644 +--- a/src/main/java/org/bukkit/block/Dispenser.java ++++ b/src/main/java/org/bukkit/block/Dispenser.java +@@ -1,5 +1,6 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.Nameable; + import org.bukkit.loot.Lootable; + import org.bukkit.projectiles.BlockProjectileSource; +@@ -8,7 +9,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a dispenser. + */ +-public interface Dispenser extends Container, Nameable, Lootable { ++public interface Dispenser extends Container, Nameable, LootableBlockInventory { // Paper + + /** + * Gets the BlockProjectileSource object for the dispenser. +diff --git a/src/main/java/org/bukkit/block/Dropper.java b/src/main/java/org/bukkit/block/Dropper.java +index 424392fb5ed4628199b0e73689522aa3c90740cb..c76202321e29ad67597ca3017eb8d9baf6787383 100644 +--- a/src/main/java/org/bukkit/block/Dropper.java ++++ b/src/main/java/org/bukkit/block/Dropper.java +@@ -1,11 +1,12 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.loot.Lootable; + + /** + * Represents a captured state of a dropper. + */ +-public interface Dropper extends Container, Lootable { ++public interface Dropper extends Container, LootableBlockInventory { // Paper + + /** + * Tries to drop a randomly selected item from the dropper's inventory, +diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java +index 58e493099810fb8d4705ecd49b4a5e1e1949b87b..7ade312f180b7e30871d3a3240c76325cc369c26 100644 +--- a/src/main/java/org/bukkit/block/Hopper.java ++++ b/src/main/java/org/bukkit/block/Hopper.java +@@ -1,8 +1,9 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.loot.Lootable; + + /** + * Represents a captured state of a hopper. + */ +-public interface Hopper extends Container, Lootable { } ++public interface Hopper extends Container, LootableBlockInventory { } // Paper +diff --git a/src/main/java/org/bukkit/block/ShulkerBox.java b/src/main/java/org/bukkit/block/ShulkerBox.java +index 387b2892886e1ccb2bd928e5111fb9bd41d777ab..5dc5318b0a451937228a8a059dfec1cd9de389a6 100644 +--- a/src/main/java/org/bukkit/block/ShulkerBox.java ++++ b/src/main/java/org/bukkit/block/ShulkerBox.java +@@ -1,5 +1,6 @@ + package org.bukkit.block; + ++import com.destroystokyo.paper.loottable.LootableBlockInventory; + import org.bukkit.DyeColor; + import org.bukkit.loot.Lootable; + import org.jetbrains.annotations.Nullable; +@@ -7,7 +8,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a ShulkerBox. + */ +-public interface ShulkerBox extends Container, Lootable, Lidded { ++public interface ShulkerBox extends Container, LootableBlockInventory, Lidded { // Paper + + /** + * Get the {@link DyeColor} corresponding to this ShulkerBox +diff --git a/src/main/java/org/bukkit/entity/ChestBoat.java b/src/main/java/org/bukkit/entity/ChestBoat.java +index 5b5c3be107fdaa6c55ceb1bca2c223ebc6ab7f43..4ebe1033c55dbd58d0794809435c935236fabcc2 100644 +--- a/src/main/java/org/bukkit/entity/ChestBoat.java ++++ b/src/main/java/org/bukkit/entity/ChestBoat.java +@@ -6,5 +6,5 @@ import org.bukkit.loot.Lootable; + /** + * A {@link Boat} with a chest. + */ +-public interface ChestBoat extends Boat, InventoryHolder, Lootable { ++public interface ChestBoat extends Boat, InventoryHolder, com.destroystokyo.paper.loottable.LootableEntityInventory { // Paper + } +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index 2926fa6071bc7640cc10280b5c3962b0ce7686f1..f3f62e13cc1b6172808c52f2d5f520f1f584e6db 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -61,4 +61,12 @@ public interface Mob extends LivingEntity, Lootable { + */ + @Nullable + public Sound getAmbientSound(); ++ ++ // Paper start - LootTable API ++ @Override ++ default void setLootTable(final @Nullable org.bukkit.loot.LootTable table, final long seed) { ++ this.setLootTable(table); ++ this.setSeed(seed); ++ } ++ // Paper end - LootTable API + } +diff --git a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java +index 937b99f8734d71b2ad33af142afbc251b81d9745..db69687a7ad4b18d17ab1677cae5d8dd4dcd3678 100644 +--- a/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/HopperMinecart.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity.minecart; + ++import com.destroystokyo.paper.loottable.LootableEntityInventory; + import org.bukkit.entity.Minecart; + import org.bukkit.inventory.InventoryHolder; + import org.bukkit.loot.Lootable; +@@ -7,7 +8,7 @@ import org.bukkit.loot.Lootable; + /** + * Represents a Minecart with a Hopper inside it + */ +-public interface HopperMinecart extends Minecart, InventoryHolder, Lootable { ++public interface HopperMinecart extends Minecart, InventoryHolder, LootableEntityInventory { + + /** + * Checks whether or not this Minecart will pick up +diff --git a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java +index 9ea403e6fd8e960d017660e0aec118abeda2c42b..238d118f7788b13cd86b7e9ea3a0fc38e2e09715 100644 +--- a/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/StorageMinecart.java +@@ -1,5 +1,6 @@ + package org.bukkit.entity.minecart; + ++import com.destroystokyo.paper.loottable.LootableEntityInventory; + import org.bukkit.entity.Minecart; + import org.bukkit.inventory.InventoryHolder; + import org.bukkit.loot.Lootable; +@@ -9,5 +10,5 @@ import org.bukkit.loot.Lootable; + * minecarts} have their own inventory that can be accessed using methods + * from the {@link InventoryHolder} interface. + */ +-public interface StorageMinecart extends Minecart, InventoryHolder, Lootable { ++public interface StorageMinecart extends Minecart, InventoryHolder, LootableEntityInventory { // Paper + } +diff --git a/src/main/java/org/bukkit/loot/Lootable.java b/src/main/java/org/bukkit/loot/Lootable.java +index b3e9347496fd60aa4f5d18ff256e8d4d73f2d9cd..649dd959035843604525a637dba639a4fbd34f97 100644 +--- a/src/main/java/org/bukkit/loot/Lootable.java ++++ b/src/main/java/org/bukkit/loot/Lootable.java +@@ -35,6 +35,31 @@ public interface Lootable { + @Nullable + LootTable getLootTable(); + ++ // Paper start ++ /** ++ * Set the loot table and seed for a container or entity at the same time. ++ * ++ * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have. ++ * @param seed the seed to used to generate loot. Default is 0. ++ */ ++ void setLootTable(final @Nullable LootTable table, final long seed); ++ ++ /** ++ * Returns whether or not this object has a Loot Table ++ * @return Has a loot table ++ */ ++ default boolean hasLootTable() { ++ return this.getLootTable() != null; ++ } ++ ++ /** ++ * Clears the associated Loot Table to this object ++ */ ++ default void clearLootTable() { ++ this.setLootTable(null); ++ } ++ // Paper end ++ + /** + * Set the seed used when this Loot Table generates loot. + * diff --git a/patches/api/0040-Add-EntityZapEvent.patch b/patches/api/0040-Add-EntityZapEvent.patch new file mode 100644 index 000000000000..04fa98d81a3d --- /dev/null +++ b/patches/api/0040-Add-EntityZapEvent.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaBlend +Date: Sun, 16 Oct 2016 23:19:34 -0700 +Subject: [PATCH] Add EntityZapEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..af2b1629f845ffe1559e7d580b482636cc6441d9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityZapEvent.java +@@ -0,0 +1,65 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import java.util.Collections; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.LightningStrike; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired when lightning strikes an entity ++ */ ++@NullMarked ++public class EntityZapEvent extends EntityTransformEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final LightningStrike bolt; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityZapEvent(final Entity entity, final LightningStrike bolt, final Entity replacementEntity) { ++ super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING); ++ this.bolt = bolt; ++ } ++ ++ /** ++ * Gets the lightning bolt that is striking the entity. ++ * ++ * @return The lightning bolt responsible for this event ++ */ ++ public LightningStrike getBolt() { ++ return this.bolt; ++ } ++ ++ /** ++ * Gets the entity that will replace the struck entity. ++ * ++ * @return The entity that will replace the struck entity ++ */ ++ public Entity getReplacementEntity() { ++ return super.getTransformedEntity(); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/entity/PigZapEvent.java b/src/main/java/org/bukkit/event/entity/PigZapEvent.java +index c5aa91c68ec24e3d07d7cb18ac8a75c4a8f743ca..7119dc013f087be7e01fc3fedc4361f76b4edae7 100644 +--- a/src/main/java/org/bukkit/event/entity/PigZapEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PigZapEvent.java +@@ -12,14 +12,14 @@ import org.jetbrains.annotations.NotNull; + /** + * Stores data for pigs being zapped + */ +-public class PigZapEvent extends EntityTransformEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); ++public class PigZapEvent extends com.destroystokyo.paper.event.entity.EntityZapEvent implements Cancellable { // Paper ++ // private static final HandlerList handlers = new HandlerList(); // Paper - moved in the super class + private boolean canceled; + private final PigZombie pigzombie; + private final LightningStrike bolt; + + public PigZapEvent(@NotNull final Pig pig, @NotNull final LightningStrike bolt, @NotNull final PigZombie pigzombie) { +- super(pig, Collections.singletonList((Entity) pigzombie), TransformReason.LIGHTNING); ++ super(pig, bolt, pigzombie); // Paper + this.bolt = bolt; + this.pigzombie = pigzombie; + } +@@ -63,6 +63,8 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { + return pigzombie; + } + ++ // Paper start ++ /* + @NotNull + @Override + public HandlerList getHandlers() { +@@ -73,4 +75,6 @@ public class PigZapEvent extends EntityTransformEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ */ ++ // Paper end + } diff --git a/patches/api/0041-Misc-Utils.patch b/patches/api/0041-Misc-Utils.patch new file mode 100644 index 000000000000..3b0d9dbfd7f7 --- /dev/null +++ b/patches/api/0041-Misc-Utils.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vemacs +Date: Wed, 23 Nov 2016 12:53:43 -0500 +Subject: [PATCH] Misc Utils + + +diff --git a/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ebaa12ecacd169f00e184fed95720d047eda8b9d +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/utils/CachedSizeConcurrentLinkedQueue.java +@@ -0,0 +1,37 @@ ++package com.destroystokyo.paper.utils; ++ ++import java.util.concurrent.ConcurrentLinkedQueue; ++import java.util.concurrent.atomic.LongAdder; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@NullMarked ++@ApiStatus.Internal ++public class CachedSizeConcurrentLinkedQueue extends ConcurrentLinkedQueue { ++ ++ private final LongAdder cachedSize = new LongAdder(); ++ ++ @Override ++ public boolean add(final E e) { ++ final boolean result = super.add(e); ++ if (result) { ++ this.cachedSize.increment(); ++ } ++ return result; ++ } ++ ++ @Override ++ public @Nullable E poll() { ++ final E result = super.poll(); ++ if (result != null) { ++ this.cachedSize.decrement(); ++ } ++ return result; ++ } ++ ++ @Override ++ public int size() { ++ return this.cachedSize.intValue(); ++ } ++} diff --git a/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch b/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch new file mode 100644 index 000000000000..18a95c3209c1 --- /dev/null +++ b/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: willies952002 +Date: Mon, 28 Nov 2016 10:16:39 -0500 +Subject: [PATCH] Allow Reloading of Command Aliases + +Reload the aliases stored in commands.yml + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 13fa39ed3d5ffa8a459d68d1e240e869ba42ac32..5660aa59d33ef2387839b9a67637672e6412088e 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2403,6 +2403,15 @@ public final class Bukkit { + public static void reloadPermissions() { + server.reloadPermissions(); + } ++ ++ /** ++ * Reload the Command Aliases in commands.yml ++ * ++ * @return Whether the reload was successful ++ */ ++ public static boolean reloadCommandAliases() { ++ return server.reloadCommandAliases(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 6567d1746f5cf16c9f3518203dd9916ff916ca68..2c0e3ce1e6bb9602e1af11711b573f0080aa6f4c 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2098,4 +2098,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + // Spigot end + + void reloadPermissions(); // Paper ++ ++ boolean reloadCommandAliases(); // Paper + } +diff --git a/src/main/java/org/bukkit/command/CommandMap.java b/src/main/java/org/bukkit/command/CommandMap.java +index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a884d0731 100644 +--- a/src/main/java/org/bukkit/command/CommandMap.java ++++ b/src/main/java/org/bukkit/command/CommandMap.java +@@ -128,4 +128,14 @@ public interface CommandMap { + */ + @Nullable + public List tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) throws IllegalArgumentException; ++ ++ // Paper start - Expose Known Commands ++ /** ++ * Return a Map of known commands ++ * ++ * @return known commands ++ */ ++ @NotNull ++ public java.util.Map getKnownCommands(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index c7fa1d235cea78bda4656ed66b8d42b119cc50fb..27243a1214bc4d7dbb46f0b9b254c8e3f8128419 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -294,4 +294,11 @@ public class SimpleCommandMap implements CommandMap { + } + } + } ++ ++ // Paper start - Expose Known Commands ++ @NotNull ++ public Map getKnownCommands() { ++ return knownCommands; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index 5fa9d648bc780e874f658597f1a24715bccac5cb..3ec32b46264cfff857b50129b5e0fa5584943ec6 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -13,7 +13,7 @@ public class ReloadCommand extends BukkitCommand { + public ReloadCommand(@NotNull String name) { + super(name); + this.description = "Reloads the server configuration and plugins"; +- this.usageMessage = "/reload [permissions]"; // Paper ++ this.usageMessage = "/reload [permissions|commands|confirm]"; // Paper + this.setPermission("bukkit.command.reload"); + this.setAliases(Arrays.asList("rl")); + } +@@ -29,6 +29,13 @@ public class ReloadCommand extends BukkitCommand { + Bukkit.getServer().reloadPermissions(); + Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Permissions successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN)); + return true; ++ } else if ("commands".equalsIgnoreCase(args[0])) { ++ if (Bukkit.getServer().reloadCommandAliases()) { ++ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("Command aliases successfully reloaded.", net.kyori.adventure.text.format.NamedTextColor.GREEN)); ++ } else { ++ Command.broadcastCommandMessage(sender, net.kyori.adventure.text.Component.text("An error occurred while trying to reload command aliases.", net.kyori.adventure.text.format.NamedTextColor.RED)); ++ } ++ return true; + } else if ("confirm".equalsIgnoreCase(args[0])) { + confirmed = true; + } else { +@@ -53,6 +60,6 @@ public class ReloadCommand extends BukkitCommand { + @NotNull + @Override + public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { +- return java.util.Collections.singletonList("permissions"); // Paper ++ return com.google.common.collect.Lists.newArrayList("permissions", "commands"); // Paper + } + } diff --git a/Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch b/patches/api/0043-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch rename to patches/api/0043-Add-source-to-PlayerExpChangeEvent.patch diff --git a/patches/api/0044-Add-ProjectileCollideEvent.patch b/patches/api/0044-Add-ProjectileCollideEvent.patch new file mode 100644 index 000000000000..9eaf9308b389 --- /dev/null +++ b/patches/api/0044-Add-ProjectileCollideEvent.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Techcable +Date: Fri, 16 Dec 2016 21:25:39 -0600 +Subject: [PATCH] Add ProjectileCollideEvent + +Now deprecated and replaced with ProjectileHitEvent + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b7df0e6ca024448784aaf4784930e565b8e5bdb3 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/ProjectileCollideEvent.java +@@ -0,0 +1,74 @@ ++package com.destroystokyo.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Projectile; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityDamageByEntityEvent; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a projectile collides with an entity ++ *

      ++ * This event is called before {@link EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying ++ * ++ * @deprecated Deprecated, use {@link org.bukkit.event.entity.ProjectileHitEvent} and check if there is a hit entity ++ */ ++@Deprecated(since = "1.19.3") ++public class ProjectileCollideEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @NotNull private final Entity collidedWith; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public ProjectileCollideEvent(@NotNull Projectile projectile, @NotNull Entity collidedWith) { ++ super(projectile); ++ this.collidedWith = collidedWith; ++ } ++ ++ /** ++ * Get the projectile that collided ++ * ++ * @return the projectile that collided ++ */ ++ @NotNull ++ public Projectile getEntity() { ++ return (Projectile) super.getEntity(); ++ } ++ ++ /** ++ * Get the entity the projectile collided with ++ * ++ * @return the entity collided with ++ */ ++ @NotNull ++ public Entity getCollidedWith() { ++ return this.collidedWith; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0045-Add-String-based-Action-Bar-API.patch b/patches/api/0045-Add-String-based-Action-Bar-API.patch new file mode 100644 index 000000000000..b96b2f3a312f --- /dev/null +++ b/patches/api/0045-Add-String-based-Action-Bar-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 20 Dec 2016 15:55:55 -0500 +Subject: [PATCH] Add String based Action Bar API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index cb758b5907aa0c214123550fe14ccfdacbc6b208..e014582d73fc821c0b6dcf19ae1f5dfdf510343c 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1255,6 +1255,39 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + public void sendMap(@NotNull MapView map); + + // Paper start ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * Use Section symbols for legacy color codes to send formatting. ++ * ++ * @param message The message to send ++ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(@NotNull String message); ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * Use supplied alternative character to the section symbol to represent legacy color codes. ++ * ++ * @param alternateChar Alternate symbol such as '&' ++ * @param message The message to send ++ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(char alternateChar, @NotNull String message); ++ ++ /** ++ * Sends an Action Bar message to the client. ++ * ++ * @param message The components to send ++ * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated ++ public void sendActionBar(@NotNull net.md_5.bungee.api.chat.BaseComponent... message); ++ + /** + * Sends the component to the player + * +@@ -1282,9 +1315,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + /** + * Sends an array of components as a single message to the specified screen position of this player + * ++ * @deprecated This is unlikely the API you want to use. See {@link #sendActionBar(String)} for a more proper Action Bar API. This deprecated API may send unsafe items to the client. + * @param position the screen position + * @param components the components to send + */ ++ @Deprecated + public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) { + spigot().sendMessage(position, components); + } diff --git a/patches/api/0046-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/api/0046-Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 000000000000..aad79a70b3d8 --- /dev/null +++ b/patches/api/0046-Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 21 Dec 2016 11:47:25 -0600 +Subject: [PATCH] Add API methods to control if armour stands can move + + +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index d08c5eb82eab8ad0ca7c8602b4d3d92fb0df02b3..6a1d563d1b7ea7e1060dfacfba98e4e1d4295790 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -344,4 +344,21 @@ public interface ArmorStand extends LivingEntity { + */ + ADDING; + } ++ // Paper start ++ /** ++ * Tests if this armor stand can move. ++ * ++ *

      The default value is {@code true}.

      ++ * ++ * @return {@code true} if this armour stand can move, {@code false} otherwise ++ */ ++ boolean canMove(); ++ ++ /** ++ * Sets if this armor stand can move. ++ * ++ * @param move {@code true} if this armour stand can move, {@code false} otherwise ++ */ ++ void setCanMove(boolean move); ++ // Paper end + } diff --git a/patches/api/0047-IllegalPacketEvent.patch b/patches/api/0047-IllegalPacketEvent.patch new file mode 100644 index 000000000000..44c4a8319817 --- /dev/null +++ b/patches/api/0047-IllegalPacketEvent.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 4 Dec 2016 01:19:14 -0500 +Subject: [PATCH] IllegalPacketEvent + +Fire an event when an illegal packet is received to let plugins handle it + +Lets plugins change the kick message and if it should kick or not. + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..44637928268c3efa951c340855f7caa63519a115 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/IllegalPacketEvent.java +@@ -0,0 +1,67 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated Not used ++ */ ++@Deprecated(since = "1.16.4") ++public class IllegalPacketEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ @Nullable private final String type; ++ @Nullable private final String exceptionMessage; ++ @Nullable private String kickMessage; ++ private boolean shouldKick = true; ++ ++ @ApiStatus.Internal ++ public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) { ++ super(player); ++ this.type = type; ++ this.kickMessage = kickMessage; ++ this.exceptionMessage = e.getMessage(); ++ } ++ ++ public boolean isShouldKick() { ++ return this.shouldKick; ++ } ++ ++ public void setShouldKick(boolean shouldKick) { ++ this.shouldKick = shouldKick; ++ } ++ ++ @Nullable ++ public String getKickMessage() { ++ return this.kickMessage; ++ } ++ ++ public void setKickMessage(@Nullable String kickMessage) { ++ this.kickMessage = kickMessage; ++ } ++ ++ @Nullable ++ public String getType() { ++ return this.type; ++ } ++ ++ @Nullable ++ public String getExceptionMessage() { ++ return this.exceptionMessage; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0048-Fireworks-API-s.patch b/patches/api/0048-Fireworks-API-s.patch new file mode 100644 index 000000000000..126f0b838d9b --- /dev/null +++ b/patches/api/0048-Fireworks-API-s.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 01:18:55 -0500 +Subject: [PATCH] Fireworks API's + +Get the Entity being boosted +Get the firework launcher + +diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java +index e750b34d7d067a5f2f5587853274b6f479cc4fd6..0d31aa0b22cf1e849572294e2cfe38b48c9210af 100644 +--- a/src/main/java/org/bukkit/entity/Firework.java ++++ b/src/main/java/org/bukkit/entity/Firework.java +@@ -111,4 +111,20 @@ public interface Firework extends Projectile { + * @param shotAtAngle the new shotAtAngle + */ + void setShotAtAngle(boolean shotAtAngle); ++ ++ // Paper start ++ @org.jetbrains.annotations.Nullable ++ public java.util.UUID getSpawningEntity(); ++ /** ++ * If this firework is boosting an entity, return it ++ * @deprecated use {@link #getAttachedTo()} ++ * @see #setAttachedTo(LivingEntity) ++ * @return The entity being boosted ++ */ ++ @org.jetbrains.annotations.Nullable ++ @Deprecated ++ default LivingEntity getBoostedEntity() { ++ return getAttachedTo(); ++ } ++ // Paper end + } diff --git a/patches/api/0049-PlayerTeleportEndGatewayEvent.patch b/patches/api/0049-PlayerTeleportEndGatewayEvent.patch new file mode 100644 index 000000000000..b52aaaead8d8 --- /dev/null +++ b/patches/api/0049-PlayerTeleportEndGatewayEvent.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 31 Dec 2016 20:29:33 -0500 +Subject: [PATCH] PlayerTeleportEndGatewayEvent + +Allows you to access the Gateway being used in a teleport event + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4488154d3f99f4281b08eef8a44c13fd896e538f +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerTeleportEndGatewayEvent.java +@@ -0,0 +1,32 @@ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.block.EndGateway; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired when a teleport is triggered for an End Gateway ++ */ ++@NullMarked ++public class PlayerTeleportEndGatewayEvent extends PlayerTeleportEvent { ++ ++ private final EndGateway gateway; ++ ++ @ApiStatus.Internal ++ public PlayerTeleportEndGatewayEvent(final Player player, final Location from, final Location to, final EndGateway gateway) { ++ super(player, from, to, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ this.gateway = gateway; ++ } ++ ++ /** ++ * The gateway triggering the teleport ++ * ++ * @return EndGateway used ++ */ ++ public EndGateway getGateway() { ++ return this.gateway; ++ } ++} diff --git a/patches/api/0050-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api/0050-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 000000000000..1913990a637b --- /dev/null +++ b/patches/api/0050-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:23:03 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 683357f685b1d5f52151a5e78fc5265ebf9d32c2..e5d3ccf6e1bc87db1f5602214371c0e8ed4d5431 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -49,6 +49,33 @@ import org.jetbrains.annotations.Nullable; + */ + public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed, net.kyori.adventure.audience.ForwardingAudience { // Paper + ++ // Paper start ++ /** ++ * @return The amount of Entities in this world ++ */ ++ int getEntityCount(); ++ ++ /** ++ * @return The amount of Tile Entities in this world ++ */ ++ int getTileEntityCount(); ++ ++ /** ++ * @return The amount of Tickable Tile Entities in this world ++ */ ++ int getTickableTileEntityCount(); ++ ++ /** ++ * @return The amount of Chunks in this world ++ */ ++ int getChunkCount(); ++ ++ /** ++ * @return The amount of Players in this world ++ */ ++ int getPlayerCount(); ++ // Paper end ++ + /** + * Gets the {@link Block} at the given coordinates + * diff --git a/Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/api/0051-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/api/0051-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch new file mode 100644 index 000000000000..338c9e637d42 --- /dev/null +++ b/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Fri, 9 Jun 2017 07:24:24 -0700 +Subject: [PATCH] Add configuration option to prevent player names from being + suggested + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 5660aa59d33ef2387839b9a67637672e6412088e..29e13fd7c94c5c50e81b804e6dffc8721164f1d1 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2412,6 +2412,16 @@ public final class Bukkit { + public static boolean reloadCommandAliases() { + return server.reloadCommandAliases(); + } ++ ++ /** ++ * Checks if player names should be suggested when a command returns {@code null} as ++ * their tab completion result. ++ * ++ * @return true if player names should be suggested ++ */ ++ public static boolean suggestPlayerNamesWhenNullTabCompletions() { ++ return server.suggestPlayerNamesWhenNullTabCompletions(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 2c0e3ce1e6bb9602e1af11711b573f0080aa6f4c..4225105fef7aee264b34d1687762b5fc8dccbc47 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2100,4 +2100,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + void reloadPermissions(); // Paper + + boolean reloadCommandAliases(); // Paper ++ ++ // Paper start - allow preventing player name suggestions by default ++ /** ++ * Checks if player names should be suggested when a command returns {@code null} as ++ * their tab completion result. ++ * ++ * @return true if player names should be suggested ++ */ ++ boolean suggestPlayerNamesWhenNullTabCompletions(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java +index cee16db367907cfa4b432dc6969f403321a855ea..0ee08b6cd80e72ae67e1316ddbb58b7c1d47e5ce 100644 +--- a/src/main/java/org/bukkit/command/Command.java ++++ b/src/main/java/org/bukkit/command/Command.java +@@ -107,7 +107,7 @@ public abstract class Command { + Preconditions.checkArgument(args != null, "Arguments cannot be null"); + Preconditions.checkArgument(alias != null, "Alias cannot be null"); + +- if (args.length == 0) { ++ if (args.length == 0 || !sender.getServer().suggestPlayerNamesWhenNullTabCompletions()) { // Paper - allow preventing player name suggestions by default) { + return ImmutableList.of(); + } + diff --git a/patches/api/0053-Fix-upstream-javadocs.patch b/patches/api/0053-Fix-upstream-javadocs.patch new file mode 100644 index 000000000000..914dbd429384 --- /dev/null +++ b/patches/api/0053-Fix-upstream-javadocs.patch @@ -0,0 +1,1890 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 10 Jun 2017 16:59:40 -0500 +Subject: [PATCH] Fix upstream javadocs + + +diff --git a/src/main/java/org/bukkit/BanList.java b/src/main/java/org/bukkit/BanList.java +index ac38b4af280cc7f52c70c238a6f4f9cccab1241d..5829aca9e5aa700bd95f19db3ae032100f74d5a3 100644 +--- a/src/main/java/org/bukkit/BanList.java ++++ b/src/main/java/org/bukkit/BanList.java +@@ -38,6 +38,9 @@ public interface BanList { + + /** + * Gets a {@link BanEntry} by target. ++ *

      ++ * Bans by name for ban type {@link Type#NAME NAME} are no longer supported and this method will return ++ * null when trying to request them. The replacement is bans by UUID. + * + * @param target entry parameter to search for + * @return the corresponding entry, or null if none found +@@ -59,6 +62,9 @@ public interface BanList { + /** + * Adds a ban to this list. If a previous ban exists, this will + * update the previous entry. ++ *

      ++ * Bans by name for ban type {@link Type#NAME NAME} are no longer supported and this method will return ++ * null when trying to request them. The replacement is bans by UUID. + * + * @param target the target of the ban + * @param reason reason for the ban, null indicates implementation default +@@ -139,6 +145,9 @@ public interface BanList { + /** + * Gets if a {@link BanEntry} exists for the target, indicating an active + * ban status. ++ *

      ++ * Bans by name for ban type {@link Type#NAME NAME} are no longer supported. ++ * The replacement is bans by UUID. + * + * @param target the target to find + * @return true if a {@link BanEntry} exists for the target, indicating an +@@ -161,6 +170,9 @@ public interface BanList { + /** + * Removes the specified target from this list, therefore indicating a + * "not banned" status. ++ *

      ++ * Bans by name for ban type {@link Type#NAME NAME} are no longer supported. ++ * The replacement is bans by UUID. + * + * @param target the target to remove from this list + */ +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 29e13fd7c94c5c50e81b804e6dffc8721164f1d1..bacdb1742ecb98bb10651b0582500449bf904910 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1538,6 +1538,8 @@ public final class Bukkit { + + /** + * Gets every player that has ever played on this server. ++ *

      ++ * This method can be expensive as it loads all the player data files from the disk. + * + * @return an array containing all previous players + */ +@@ -2059,7 +2061,7 @@ public final class Bukkit { + * server will pause most functions after this time if there are no players + * online. + *

      +- * A value of less than 0 will disable the setting ++ * A value of less than 1 will disable the setting + * + * @param seconds the pause threshold in seconds + */ +diff --git a/src/main/java/org/bukkit/ChunkSnapshot.java b/src/main/java/org/bukkit/ChunkSnapshot.java +index 8832a2e0907299fb5f379b6938bbbc8e98688478..725d7944ce066ac56ed86b31628f00eb46cdcf64 100644 +--- a/src/main/java/org/bukkit/ChunkSnapshot.java ++++ b/src/main/java/org/bukkit/ChunkSnapshot.java +@@ -136,7 +136,7 @@ public interface ChunkSnapshot { + * Get raw biome temperature at given coordinates + * + * @param x X-coordinate (0-15) +- * @param y Y-coordinate (0-15) ++ * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive)) + * @param z Z-coordinate (0-15) + * @return temperature at given coordinate + */ +diff --git a/src/main/java/org/bukkit/HeightMap.java b/src/main/java/org/bukkit/HeightMap.java +index db6fcd635e295e561642d49941fd8e611247d38e..344b2b5d9207d2645bc5417d1ec00dd0a0b95604 100644 +--- a/src/main/java/org/bukkit/HeightMap.java ++++ b/src/main/java/org/bukkit/HeightMap.java +@@ -12,8 +12,7 @@ public enum HeightMap { + */ + MOTION_BLOCKING, + /** +- * The highest block that blocks motion or contains a fluid or is in the +- * {@link Tag#LEAVES}. ++ * The highest block that blocks motion or contains a fluid, excluding leaves. + */ + MOTION_BLOCKING_NO_LEAVES, + /** +diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java +index bc23886a62312fc9e222ff2c6e7a7f325397d36a..ecf9f941e618608b98feaac46df3f10ec951c186 100644 +--- a/src/main/java/org/bukkit/Particle.java ++++ b/src/main/java/org/bukkit/Particle.java +@@ -207,7 +207,7 @@ public enum Particle implements Keyed { + } + + /** +- * Options which can be applied to redstone dust particles - a particle ++ * Options which can be applied to dust particles - a particle + * color and size. + */ + public static class DustOptions { +diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bukkit/RegionAccessor.java +index 4c9fd558fbf7f57a948fbb7f80f4651048c0fb57..458119a9ef7ce8e1f59bd47caa5b4bc698715440 100644 +--- a/src/main/java/org/bukkit/RegionAccessor.java ++++ b/src/main/java/org/bukkit/RegionAccessor.java +@@ -158,7 +158,7 @@ public interface RegionAccessor { + * Creates a tree at the given {@link Location} + * + * @param location Location to spawn the tree +- * @param random Random to use to generated the tree ++ * @param random Random to use to generate the tree + * @param type Type of the tree to create + * @return true if the tree was created successfully, otherwise false + */ +@@ -170,14 +170,14 @@ public interface RegionAccessor { + * The provided consumer gets called for every block which gets changed + * as a result of the tree generation. When the consumer gets called no + * modifications to the world are done yet. Which means, that calling +- * {@link #getBlockState(Location)} in the consumer while return the state ++ * {@link #getBlockState(Location)} in the consumer will return the state + * of the block before the generation. + *

      + * Modifications done to the {@link BlockState} in the consumer are respected, + * which means that it is not necessary to call {@link BlockState#update()} + * + * @param location Location to spawn the tree +- * @param random Random to use to generated the tree ++ * @param random Random to use to generate the tree + * @param type Type of the tree to create + * @param stateConsumer The consumer which should get called for every block which gets changed + * @return true if the tree was created successfully, otherwise false +@@ -197,7 +197,7 @@ public interface RegionAccessor { + * If it returns {@code false} the block won't get set in the world. + * + * @param location Location to spawn the tree +- * @param random Random to use to generated the tree ++ * @param random Random to use to generate the tree + * @param type Type of the tree to create + * @param statePredicate The predicate which should get used to test if a block should be set or not. + * @return true if the tree was created successfully, otherwise false +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 4225105fef7aee264b34d1687762b5fc8dccbc47..a506e618448c3bf4b56f54f8fe00d7158df29dd7 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -581,13 +581,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * + *

      + * Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. +- *

      +- * Minecraft default: 1. +- *
      +- * Note: the {@link SpawnCategory#MISC} are not consider. + * + * @param spawnCategory the category of spawn + * @return the default ticks per {@link SpawnCategory} mobs spawn value ++ * @throws IllegalArgumentException if the category is {@link SpawnCategory#MISC} + */ + public int getTicksPerSpawns(@NotNull SpawnCategory spawnCategory); + +@@ -1298,6 +1295,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + + /** + * Gets every player that has ever played on this server. ++ *

      ++ * This method can be expensive as it loads all the player data files from the disk. + * + * @return an array containing all previous players + */ +@@ -1740,7 +1739,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * Sets the pause when empty threshold seconds. To save resources, the + * pause most functions after this time if there are no players online. + *

      +- * A value of less than 0 will disable the setting ++ * A value of less than 1 will disable the setting + * + * @param seconds the pause threshold in seconds + */ +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index e5d3ccf6e1bc87db1f5602214371c0e8ed4d5431..369e92f2b5e4b8fc7f5bf8a97058e827c91e4c59 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -2766,7 +2766,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + /** + * Find the closest nearby structure of a given {@link StructureType}. + * Finding unexplored structures can, and will, block if the world is +- * looking in chunks that gave not generated yet. This can lead to the world ++ * looking in chunks that have not generated yet. This can lead to the world + * temporarily freezing while locating an unexplored structure. + *

      + * The {@code radius} is not a rigid square radius. Each structure may alter +@@ -2800,7 +2800,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + /** + * Find the closest nearby structure of a given {@link StructureType}. + * Finding unexplored structures can, and will, block if the world is +- * looking in chunks that gave not generated yet. This can lead to the world ++ * looking in chunks that have not generated yet. This can lead to the world + * temporarily freezing while locating an unexplored structure. + *

      + * The {@code radius} is not a rigid square radius. Each structure may alter +@@ -2833,7 +2833,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + /** + * Find the closest nearby structure of a given {@link Structure}. Finding + * unexplored structures can, and will, block if the world is looking in +- * chunks that gave not generated yet. This can lead to the world ++ * chunks that have not generated yet. This can lead to the world + * temporarily freezing while locating an unexplored structure. + *

      + * The {@code radius} is not a rigid square radius. Each structure may alter +diff --git a/src/main/java/org/bukkit/attribute/AttributeModifier.java b/src/main/java/org/bukkit/attribute/AttributeModifier.java +index ecf3897bd2dbdeebfa09a00a692724a013b0186d..b90af00a8eb83d4c1b183fbc4f1e9eae84c9074b 100644 +--- a/src/main/java/org/bukkit/attribute/AttributeModifier.java ++++ b/src/main/java/org/bukkit/attribute/AttributeModifier.java +@@ -129,8 +129,7 @@ public class AttributeModifier implements ConfigurationSerializable, Keyed { + } + + /** +- * Get the {@link EquipmentSlot} this AttributeModifier is active on, +- * or null if this modifier is applicable for any slot. ++ * Get the {@link EquipmentSlotGroup} this AttributeModifier is active on. + * + * @return the slot + */ +diff --git a/src/main/java/org/bukkit/block/Bed.java b/src/main/java/org/bukkit/block/Bed.java +index 20aaa7e15a71eef34ff4c06bad14464e7c9584dd..46778452893de3d8f1765994fb0c1ba62a90b315 100644 +--- a/src/main/java/org/bukkit/block/Bed.java ++++ b/src/main/java/org/bukkit/block/Bed.java +@@ -4,7 +4,22 @@ import org.bukkit.material.Colorable; + + /** + * Represents a captured state of a bed. +- * @deprecated does not provide useful information beyond the material itself + */ +-@Deprecated(since = "1.13") +-public interface Bed extends TileState, Colorable { } ++// Paper start ++// @Deprecated(since = "1.13") ++public interface Bed extends TileState, Colorable { ++ ++ @Override ++ @org.jetbrains.annotations.NotNull org.bukkit.DyeColor getColor(); ++ ++ /** ++ * Unsupported ++ * ++ * @throws UnsupportedOperationException not supported, set the block type ++ */ ++ @Override ++ @org.jetbrains.annotations.Contract("_ -> fail") ++ @Deprecated(forRemoval = true) ++ void setColor(@org.bukkit.UndefinedNullability("not supported") org.bukkit.DyeColor color); ++// Paper end ++} +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index ab65d9769b73780dc126b4f11f2ad4528e6ab0c0..f440da5941e11c30145175cf24162e1ba2b4e3cf 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -357,7 +357,7 @@ public interface Block extends Metadatable, Translatable { + * Gets the temperature of this block. + *

      + * If the raw biome temperature without adjusting for height effects is +- * required then please use {@link World#getTemperature(int, int)}. ++ * required then please use {@link World#getTemperature(int, int, int)}. + * + * @return Temperature of this block + */ +@@ -405,7 +405,10 @@ public interface Block extends Metadatable, Translatable { + boolean applyBoneMeal(@NotNull BlockFace face); + + /** +- * Returns a list of items which would drop by destroying this block ++ * Returns a list of items which could drop by destroying this block. ++ *

      ++ * The items are not guaranteed to be consistent across multiple calls to this ++ * method as this just uses the block type's loot table. + * + * @return a list of dropped items for this type of block + */ +@@ -413,8 +416,11 @@ public interface Block extends Metadatable, Translatable { + Collection getDrops(); + + /** +- * Returns a list of items which would drop by destroying this block with +- * a specific tool ++ * Returns a list of items which could drop by destroying this block with ++ * a specific tool. ++ *

      ++ * The items are not guaranteed to be consistent across multiple calls to this ++ * method as this just uses the block type's loot table. + * + * @param tool The tool or item in hand used for digging + * @return a list of dropped items for this type of block +@@ -423,8 +429,11 @@ public interface Block extends Metadatable, Translatable { + Collection getDrops(@Nullable ItemStack tool); + + /** +- * Returns a list of items which would drop by the entity destroying this +- * block with a specific tool ++ * Returns a list of items which could drop by the entity destroying this ++ * block with a specific tool. ++ *

      ++ * The items are not guaranteed to be consistent across multiple calls to this ++ * method as this just uses the block type's loot table. + * + * @param tool The tool or item in hand used for digging + * @param entity the entity destroying the block +diff --git a/src/main/java/org/bukkit/block/data/BlockData.java b/src/main/java/org/bukkit/block/data/BlockData.java +index 29fd06cb800f9b7cc91a120ccbe2980422ed9653..cd3b3e05cc825cfedec07f9a2a1e0b7b2a8866d6 100644 +--- a/src/main/java/org/bukkit/block/data/BlockData.java ++++ b/src/main/java/org/bukkit/block/data/BlockData.java +@@ -224,7 +224,7 @@ public interface BlockData extends Cloneable { + * {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE} + * {@link Material#CARROTS} -> {@link Material#CARROT} + * +- * @return placement material ++ * @return placement material or {@link Material#AIR} if it doesn't have one + */ + @NotNull + Material getPlacementMaterial(); +diff --git a/src/main/java/org/bukkit/block/data/FaceAttachable.java b/src/main/java/org/bukkit/block/data/FaceAttachable.java +index 9599e1237b9717ddbf84c3738bf6c1293e8b3c54..950266b4bb0a2fabeb9539c5676ed58f0b0fe620 100644 +--- a/src/main/java/org/bukkit/block/data/FaceAttachable.java ++++ b/src/main/java/org/bukkit/block/data/FaceAttachable.java +@@ -38,7 +38,7 @@ public interface FaceAttachable extends BlockData { + */ + WALL, + /** +- * The switch is mounted to the ceiling and pointing dowanrds. ++ * The switch is mounted to the ceiling and pointing downwards. + */ + CEILING; + } +diff --git a/src/main/java/org/bukkit/block/data/type/CommandBlock.java b/src/main/java/org/bukkit/block/data/type/CommandBlock.java +index 9a7122c907308e4e0a4d0eab815df16899503c19..3b1dab4c1c38477fbe651382f37fdb042ce67cd1 100644 +--- a/src/main/java/org/bukkit/block/data/type/CommandBlock.java ++++ b/src/main/java/org/bukkit/block/data/type/CommandBlock.java +@@ -4,7 +4,7 @@ import org.bukkit.block.data.Directional; + + /** + * 'conditional' denotes whether this command block is conditional or not, i.e. +- * will only execute if the preceeding command block also executed successfully. ++ * will only execute if the preceding command block also executed successfully. + */ + public interface CommandBlock extends Directional { + +diff --git a/src/main/java/org/bukkit/block/data/type/Gate.java b/src/main/java/org/bukkit/block/data/type/Gate.java +index 494f97d47b52bc99b13748c1b57730fbd37d8f51..ebc98607b93294847f95e793304bc5d2528de2a3 100644 +--- a/src/main/java/org/bukkit/block/data/type/Gate.java ++++ b/src/main/java/org/bukkit/block/data/type/Gate.java +@@ -5,7 +5,7 @@ import org.bukkit.block.data.Openable; + import org.bukkit.block.data.Powerable; + + /** +- * 'in_wall" indicates if the fence gate is attached to a wall, and if true the ++ * 'in_wall' indicates if the fence gate is attached to a wall, and if true the + * texture is lowered by a small amount to blend in better. + */ + public interface Gate extends Directional, Openable, Powerable { +diff --git a/src/main/java/org/bukkit/block/data/type/Switch.java b/src/main/java/org/bukkit/block/data/type/Switch.java +index df8c2d60e7cce0294d3a1b1a6a81367a56602c26..16ced762f498b0dadd22789fa5d121d644bebf3d 100644 +--- a/src/main/java/org/bukkit/block/data/type/Switch.java ++++ b/src/main/java/org/bukkit/block/data/type/Switch.java +@@ -21,7 +21,7 @@ public interface Switch extends Directional, FaceAttachable, Powerable { + * Sets the value of the 'face' property. + * + * @param face the new 'face' value +- * @deprecated use {@link #getAttachedFace()} ++ * @deprecated use {@link #setAttachedFace(AttachedFace)} + */ + @Deprecated(since = "1.15.2") + void setFace(@NotNull Face face); +@@ -42,7 +42,7 @@ public interface Switch extends Directional, FaceAttachable, Powerable { + */ + WALL, + /** +- * The switch is mounted to the ceiling and pointing dowanrds. ++ * The switch is mounted to the ceiling and pointing downwards. + */ + CEILING; + } +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index 6a1d563d1b7ea7e1060dfacfba98e4e1d4295790..c727b2d40efae8f08bdd159991afb8992568a58f 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -360,5 +360,8 @@ public interface ArmorStand extends LivingEntity { + * @param move {@code true} if this armour stand can move, {@code false} otherwise + */ + void setCanMove(boolean move); ++ ++ @Override ++ org.bukkit.inventory.@NotNull EntityEquipment getEquipment(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Arrow.java b/src/main/java/org/bukkit/entity/Arrow.java +index a292579c9fa6eeac92fb1a21fa8144fbef307dad..38e6a8dbb248ead98cfb36bfb077d4e9e95b2c77 100644 +--- a/src/main/java/org/bukkit/entity/Arrow.java ++++ b/src/main/java/org/bukkit/entity/Arrow.java +@@ -93,7 +93,7 @@ public interface Arrow extends AbstractArrow { + * Removes a custom potion effect from this arrow. + * + * @param type the potion effect type to remove +- * @return true if the an effect was removed as a result of this call ++ * @return true if the effect was removed as a result of this call + * @throws IllegalArgumentException if this operation would leave the Arrow + * in a state with no Custom Effects and PotionType.UNCRAFTABLE + */ +diff --git a/src/main/java/org/bukkit/entity/EnderDragon.java b/src/main/java/org/bukkit/entity/EnderDragon.java +index 1e56aef9188487d3e9c737e85025f601ab359a72..92cd35c87bad578c2b714761c93a5b72ebf4bc9e 100644 +--- a/src/main/java/org/bukkit/entity/EnderDragon.java ++++ b/src/main/java/org/bukkit/entity/EnderDragon.java +@@ -30,7 +30,7 @@ public interface EnderDragon extends ComplexLivingEntity, Boss, Mob, Enemy { + */ + FLY_TO_PORTAL, + /** +- * The dragon will land on on the portal. If the dragon is not near ++ * The dragon will land on the portal. If the dragon is not near + * the portal, it will fly to it before mounting. + */ + LAND_ON_PORTAL, +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 411297f66520774a4072c9e15aa9bdf03a527208..45d408f519767785b222c409170bbfecbd8d1931 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -180,9 +180,13 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + public List getNearbyEntities(double x, double y, double z); + + /** +- * Returns a unique id for this entity ++ * Returns the network protocol ID for this entity. This is ++ * not to be used as an identifier for the entity except in ++ * network-related operations. Use {@link #getUniqueId()} as ++ * an entity identifier instead. + * +- * @return Entity id ++ * @return the network protocol ID ++ * @see #getUniqueId() + */ + public int getEntityId(); + +diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java +index b21f42e653553b6dbd571a1e8fba1e5a04f3bbd1..c90a0a00be78200adf217e2b3a8302b59af3cf7c 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -22,6 +22,11 @@ import org.jetbrains.annotations.Nullable; + */ + public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder { + ++ // Paper start ++ @Override ++ org.bukkit.inventory.@NotNull EntityEquipment getEquipment(); ++ // Paper end ++ + /** + * Returns the name of this player + * +diff --git a/src/main/java/org/bukkit/entity/ItemFrame.java b/src/main/java/org/bukkit/entity/ItemFrame.java +index b688b3856cb3068a539fcecfbfa113f8ab4160a9..c275b881cbd11307a6dcc7190d7a7d4063000ad8 100644 +--- a/src/main/java/org/bukkit/entity/ItemFrame.java ++++ b/src/main/java/org/bukkit/entity/ItemFrame.java +@@ -75,7 +75,7 @@ public interface ItemFrame extends Hanging { + public void setRotation(@NotNull Rotation rotation) throws IllegalArgumentException; + + /** +- * Returns whether the item frame is be visible or not. ++ * Returns whether the item frame is visible or not. + * + * @return whether the item frame is visible or not + */ +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 598c88f02a764abe62f9f10833b2c499a0fb00ff..4b75a5e1ce788bc375d6147422e5bee6ef0c03be 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -502,7 +502,7 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + /** + * Sets the leash on this entity to be held by the supplied entity. + *

      +- * This method has no effect on EnderDragons, Withers, Players, or Bats. ++ * This method has no effect on players. + * Non-living entities excluding leashes will not persist as leash + * holders. + * +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index f3f62e13cc1b6172808c52f2d5f520f1f584e6db..ad5dbf310fe7b34c997bb339f09697222f862005 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -9,6 +9,10 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Mob extends LivingEntity, Lootable { + ++ // Paper start ++ @Override ++ org.bukkit.inventory.@org.jetbrains.annotations.NotNull EntityEquipment getEquipment(); ++ // Paper end + /** + * Instructs this Mob to set the specified LivingEntity as its target. + *

      +diff --git a/src/main/java/org/bukkit/entity/PigZombie.java b/src/main/java/org/bukkit/entity/PigZombie.java +index ae9eaaa8e38e1d9dfc459926c7fc51ddb89de84a..b2ec535bb1b0ce0c114ddd7638b90218b05cd835 100644 +--- a/src/main/java/org/bukkit/entity/PigZombie.java ++++ b/src/main/java/org/bukkit/entity/PigZombie.java +@@ -44,8 +44,6 @@ public interface PigZombie extends Zombie { + + /** + * Not applicable to this entity +- * +- * @return UnsuppotedOperationException + */ + @Override + public int getConversionTime(); +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index e014582d73fc821c0b6dcf19ae1f5dfdf510343c..5b12fa8c41a18ddfe08d82c138c0f71106c89d4d 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -492,15 +492,15 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + + /** + * Saves the players current location, health, inventory, motion, and +- * other information into the uuid.dat file, in the <main +- * world>/playerdata folder. ++ * other information into the <uuid>.dat file, in the ++ * <level-name>/playerdata/ folder. + */ + public void saveData(); + + /** + * Loads the players current location, health, inventory, motion, and +- * other information from the uuid.dat file, in the <main +- * world>/playerdata folder. ++ * other information from the <uuid>.dat file, in the ++ * <level-name>/playerdata/ folder. + *

      + * Note: This will overwrite the players current inventory, health, + * motion, etc, with the state from the saved dat file. +@@ -861,7 +861,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + /** + * Plays an effect to just this player. + * +- * @param the data based based on the type of the effect ++ * @param the data based on the type of the effect + * @param loc the location to play the effect at + * @param effect the {@link Effect} + * @param data a data bit needed for some effects +@@ -1272,7 +1272,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * Use supplied alternative character to the section symbol to represent legacy color codes. + * +- * @param alternateChar Alternate symbol such as '&' ++ * @param alternateChar Alternate symbol such as '&' + * @param message The message to send + * @deprecated use {@link #sendActionBar(net.kyori.adventure.text.Component)} + */ +@@ -1745,7 +1745,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + + /** + * Allows this player to see a player that was previously hidden. If +- * another another plugin had hidden the player too, then the player will ++ * another plugin had hidden the player too, then the player will + * remain hidden until the other plugin calls this method too. + * + * @param plugin Plugin that wants to show the player +@@ -1772,7 +1772,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + + /** + * Allows this player to see an entity that was previously hidden. If +- * another another plugin had hidden the entity too, then the entity will ++ * another plugin had hidden the entity too, then the entity will + * remain hidden until the other plugin calls this method too. + * + * @param plugin Plugin that wants to show the entity +@@ -1855,9 +1855,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * case this method will have no affect on them. Use the + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! +- *

    • There is no concept of resetting texture packs back to default +- * within Minecraft, so players will have to relog to do so or you +- * have to send an empty pack. + *
    • The request is send with "null" as the hash. This might result + * in newer versions not loading the pack correctly. + * +@@ -1891,9 +1888,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * case this method will have no affect on them. Use the + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! +- *
    • There is no concept of resetting resource packs back to default +- * within Minecraft, so players will have to relog to do so or you +- * have to send an empty pack. + *
    • The request is send with empty string as the hash. This might result + * in newer versions not loading the pack correctly. + * +@@ -1930,9 +1924,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * case this method will have no affect on them. Use the + * {@link PlayerResourcePackStatusEvent} to figure out whether or not + * the player loaded the pack! +- *
    • There is no concept of resetting resource packs back to default +- * within Minecraft, so players will have to relog to do so or you +- * have to send an empty pack. + *
    • The request is sent with empty string as the hash when the hash is + * not provided. This might result in newer versions not loading the + * pack correctly. +diff --git a/src/main/java/org/bukkit/entity/Slime.java b/src/main/java/org/bukkit/entity/Slime.java +index a5ad3250cebfeb302c58e0bfd6db1295913c927e..0a2d603bf6a3f60d3fa7d85df6ef2373fc93d848 100644 +--- a/src/main/java/org/bukkit/entity/Slime.java ++++ b/src/main/java/org/bukkit/entity/Slime.java +@@ -11,6 +11,16 @@ public interface Slime extends Mob, Enemy { + public int getSize(); + + /** ++ * Setting the size of the slime (regardless of previous size) ++ * will set the following attributes: ++ *
        ++ *
      • {@link org.bukkit.attribute.Attribute#MAX_HEALTH}
      • ++ *
      • {@link org.bukkit.attribute.Attribute#MOVEMENT_SPEED}
      • ++ *
      • {@link org.bukkit.attribute.Attribute#ATTACK_DAMAGE}
      • ++ *
      ++ * to their per-size defaults and heal the ++ * slime to its max health (assuming it's alive). ++ * + * @param sz The new size of the slime. + */ + public void setSize(int sz); +diff --git a/src/main/java/org/bukkit/entity/Sniffer.java b/src/main/java/org/bukkit/entity/Sniffer.java +index af5110b4160979c39cc1e5de6fa3bd7957b21403..15a0a733b0e5804655b5957cbf20831290d52a08 100644 +--- a/src/main/java/org/bukkit/entity/Sniffer.java ++++ b/src/main/java/org/bukkit/entity/Sniffer.java +@@ -12,8 +12,6 @@ public interface Sniffer extends Animals { + + /** + * Gets the locations explored by the sniffer. +- *
      +- * Note: the returned locations use sniffer's current world. + * + * @return a collection of locations + */ +@@ -22,9 +20,6 @@ public interface Sniffer extends Animals { + + /** + * Remove a location of the explored locations. +- *
      +- * Note: the location must be in the sniffer's current world for this +- * method to have any effect. + * + * @param location the location to remove + * @see #getExploredLocations() +diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java +index c48f13cc8ece0fa9913450e4402e496ce01a03fb..af4582f3e4687933dac6ccd43667a373f8daedb6 100644 +--- a/src/main/java/org/bukkit/entity/Villager.java ++++ b/src/main/java/org/bukkit/entity/Villager.java +@@ -224,7 +224,7 @@ public interface Villager extends AbstractVillager { + */ + Profession NITWIT = getProfession("nitwit"); + /** +- * Sheperd profession. Wears a brown robe. Shepherds primarily trade for ++ * Shepherd profession. Wears a brown robe. Shepherds primarily trade for + * wool items, and shears. + */ + Profession SHEPHERD = getProfession("shepherd"); +diff --git a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +index a0f6f1af304190b4c5db4b284d460f625eeb7801..7e21548cac8515c281ec86853e9272ab7695b24f 100644 +--- a/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockDropItemEvent.java +@@ -10,15 +10,19 @@ import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; + + /** +- * Called if a block broken by a player drops an item. ++ * Called after a block is broken by a player and potential drops are computed, even if said blocks loot table ++ * does not define any drops at the point the event is constructed. + * + * If the block break is cancelled, this event won't be called. + * +- * If isDropItems in BlockBreakEvent is set to false, this event won't be ++ * If isDropItems in {@link org.bukkit.event.block.BlockBreakEvent} is set to false, this event won't be + * called. + * ++ * If a block is broken and isDropItems is set to true, this event will be called even if the block does ++ * not drop any items, for example glass broken by hand. In this case, #getItems() will be empty. ++ * + * This event will also be called if the player breaks a multi block structure, +- * for example a torch on top of a stone. Both items will have an event call. ++ * for example a torch on top of a stone. Both items will be included in the #getItems() list. + * + * The Block is already broken as this event is called, so #getBlock() will be + * AIR in most cases. Use #getBlockState() for more Information about the broken +diff --git a/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java b/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java +index 1df172c0bb48de3b143179a3f0c63d6ecc30649e..254d549f956053af4264ca3a52d34a97ede4273d 100644 +--- a/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java +@@ -14,6 +14,9 @@ import org.jetbrains.annotations.NotNull; + * Note that due to the nature of explosions, {@link #getBlock()} will always be + * an air block. {@link #getExplodedBlockState()} should be used to get + * information about the block state that exploded. ++ *

      ++ * The event isn't called if the {@link org.bukkit.GameRule#MOB_GRIEFING} ++ * is disabled as no block interaction will occur. + */ + public class BlockExplodeEvent extends BlockEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +diff --git a/src/main/java/org/bukkit/event/block/BlockPistonRetractEvent.java b/src/main/java/org/bukkit/event/block/BlockPistonRetractEvent.java +index 0392cc3a00f77a11608bf78cc157a411c7bcd976..23b3f44ab009bd49dac60a4045f12858f12cb2ba 100644 +--- a/src/main/java/org/bukkit/event/block/BlockPistonRetractEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockPistonRetractEvent.java +@@ -34,7 +34,7 @@ public class BlockPistonRetractEvent extends BlockPistonEvent { + + /** + * Get an immutable list of the blocks which will be moved by the +- * extending. ++ * retracting. + * + * @return Immutable list of the moved blocks. + */ +diff --git a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java +index 77215c1dd2419104607138c45666ce0d84866670..3bfd0f6edc44d6503988f3c3c7a267f1be2986e3 100644 +--- a/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java +@@ -114,7 +114,7 @@ public class BlockPlaceEvent extends BlockEvent implements Cancellable { + + /** + * Gets the value whether the player would be allowed to build here. +- * Defaults to spawn if the server was going to stop them (such as, the ++ * Defaults to false if the server was going to stop them (such as, the + * player is in Spawn). Note that this is an entirely different check + * than BLOCK_CANBUILD, as this refers to a player, not universe-physics + * rule like cactus on dirt. +diff --git a/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java b/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java +index a722e090e788f5497569e69137923682e2abcbac..4c8f388897ff9ddd077695172622c5550651858b 100644 +--- a/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java ++++ b/src/main/java/org/bukkit/event/enchantment/PrepareItemEnchantEvent.java +@@ -81,7 +81,7 @@ public class PrepareItemEnchantEvent extends InventoryEvent implements Cancellab + /** + * Get a list of available {@link EnchantmentOffer} for the player. You can + * modify the values to change the available offers for the player. An offer +- * may be null, if there isn't a enchantment offer at a specific slot. There ++ * may be null, if there isn't an enchantment offer at a specific slot. There + * are 3 slots in the enchantment table available to modify. + * + * @return list of available enchantment offers +diff --git a/src/main/java/org/bukkit/event/entity/AreaEffectCloudApplyEvent.java b/src/main/java/org/bukkit/event/entity/AreaEffectCloudApplyEvent.java +index a37febd0d4dd5b733e9ee72628fdf9395fec4367..9cee218b9ee14688356f16b1f58512186286e7e9 100644 +--- a/src/main/java/org/bukkit/event/entity/AreaEffectCloudApplyEvent.java ++++ b/src/main/java/org/bukkit/event/entity/AreaEffectCloudApplyEvent.java +@@ -8,7 +8,7 @@ import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; + + /** +- * Called when a lingering potion applies it's effects. Happens ++ * Called when a lingering potion applies its effects. Happens + * once every 5 ticks + */ + public class AreaEffectCloudApplyEvent extends EntityEvent implements Cancellable { +diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +index c746c2e73ab9c91376ceaeab43423edb8009fe1a..5d2597378d36ccace672db0768267d3499100cf1 100644 +--- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +@@ -158,11 +158,12 @@ public class CreatureSpawnEvent extends EntitySpawnEvent { + */ + DROWNED, + /** +- * When an cow is spawned by shearing a mushroom cow ++ * When a cow is spawned by shearing a mushroom cow + */ + SHEARED, + /** +- * When eg an effect cloud is spawned as a result of a creeper exploding ++ * When an entity is spawned as a result of an explosion. Like an area effect cloud from ++ * a creeper or a dragon fireball. + */ + EXPLOSION, + /** +diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java +index 0a3699226be1941c0ad1ff1ad8f80bad3aec42aa..971093bd2500543e680db1c92f781bfd5c35dd83 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityDamageByBlockEvent.java +@@ -12,6 +12,10 @@ import org.jetbrains.annotations.Nullable; + + /** + * Called when an entity is damaged by a block ++ *

      ++ * For explosions, the Block returned by {@link #getDamager()} has ++ * already been cleared. See {@link #getDamagerBlockState()} for a snapshot ++ * of the block if it has already been changed. + */ + public class EntityDamageByBlockEvent extends EntityDamageEvent { + private final Block damager; +@@ -51,6 +55,9 @@ public class EntityDamageByBlockEvent extends EntityDamageEvent { + + /** + * Returns the captured BlockState of the block that damaged the player. ++ *

      ++ * This block state is not placed so {@link org.bukkit.block.BlockState#isPlaced} ++ * will be false. + * + * @return the block state + */ +diff --git a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +index fc2158793aec67310bc8d06ac1f0bac39d2a5c3d..50161d313cfcc9e61441589685c3d0e1f057dd86 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +@@ -10,7 +10,9 @@ import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; + + /** +- * Called when an entity explodes ++ * Called when an entity explodes interacting with blocks. The ++ * event isn't called if the {@link org.bukkit.GameRule#MOB_GRIEFING} ++ * is disabled as no block interaction will occur. + */ + public class EntityExplodeEvent extends EntityEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +diff --git a/src/main/java/org/bukkit/event/entity/EntityPickupItemEvent.java b/src/main/java/org/bukkit/event/entity/EntityPickupItemEvent.java +index c866df03d66dd8724e12c7353da4cf144c70b2c8..94ee5a3354722aa5d825da727b7b7071fdc6bacc 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPickupItemEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPickupItemEvent.java +@@ -7,7 +7,7 @@ import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; + + /** +- * Thrown when a entity picks an item up from the ground ++ * Thrown when an entity picks an item up from the ground + */ + public class EntityPickupItemEvent extends EntityEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +diff --git a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java +index 4f116956071148a1a148b94ceb4654d3934e2f7f..a7bd15d51a4ff9142cfb341f65050a88b5f5fa8d 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + /** +- * Triggered when a entity is created in the world by a player "placing" an item ++ * Triggered when an entity is created in the world by a player "placing" an item + * on a block. + *
      + * Note that this event is currently only fired for four specific placements: +diff --git a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java +index 31a5515c08c9454d52a0d946d103a2d526c15e48..d743cc5ee34fd7bc5db92f4b17fed9f3aa5ffbcc 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java +@@ -133,7 +133,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable + public enum Action { + + /** +- * When the potion effect is added because the entity didn't have it's ++ * When the potion effect is added because the entity didn't have its + * type. + */ + ADDED, +@@ -237,7 +237,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable + */ + SPIDER_SPAWN, + /** +- * When the entity gets effects from a totem item saving it's life. ++ * When the entity gets effects from a totem item saving its life. + */ + TOTEM, + /** +diff --git a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java +index d51d2ec1d04d9ea8a25a70d0d856f2355ebfcb4a..7ecff9fcee19fc94be784474fea620e5dd434731 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java +@@ -105,7 +105,7 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable + */ + SATIATED, + /** +- * When a player regains health from eating consumables ++ * When an animal regains health from eating consumables + */ + EATING, + /** +diff --git a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java +index 842cfd3e9829c61250e98d1a45602a81549de176..808142232a722cb6466bac78d00dc55c18ebe109 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityTargetEvent.java +@@ -156,7 +156,7 @@ public class EntityTargetEvent extends EntityEvent implements Cancellable { + FOLLOW_LEADER, + /** + * When another entity tempts this entity by having a desired item such +- * as wheat in it's hand. ++ * as wheat in its hand. + */ + TEMPT, + /** +diff --git a/src/main/java/org/bukkit/event/entity/PiglinBarterEvent.java b/src/main/java/org/bukkit/event/entity/PiglinBarterEvent.java +index c17ff41a688b2cbd877cda25d4ec033ac8ef5524..bd67b7cba78b9bbdd82a5a40048e658a979e3108 100644 +--- a/src/main/java/org/bukkit/event/entity/PiglinBarterEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PiglinBarterEvent.java +@@ -10,8 +10,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Stores all data related to the bartering interaction with a piglin. + * +- * This event can be triggered by a piglin picking up an item that's on its +- * bartering list. ++ * Called when a piglin completes a barter. + */ + public class PiglinBarterEvent extends EntityEvent implements Cancellable { + +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +index bc71bc2d3ace0d19d730c09f05f9e0655bcee8f5..24077da8e6a7937f66eafc6779206055cf82e8d2 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +@@ -8,7 +8,9 @@ import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + + /** +- * Called when an ItemStack is successfully burned as fuel in a furnace. ++ * Called when an ItemStack is successfully burned as fuel in a furnace-like block such as a ++ * {@link org.bukkit.block.Furnace}, {@link org.bukkit.block.Smoker}, or ++ * {@link org.bukkit.block.BlastFurnace}. + */ + public class FurnaceBurnEvent extends BlockEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java +index 65db4991bd4789991868c0d75fea4034fed487a8..5ffd28fd24b4477a07fc9f6a3f669a6f4da9fa26 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceExtractEvent.java +@@ -9,7 +9,9 @@ import org.bukkit.material.MaterialData; + import org.jetbrains.annotations.NotNull; + + /** +- * This event is called when a player takes items out of the furnace ++ * This event is called when a player takes items out of a furnace-like block such as a ++ * {@link org.bukkit.block.Furnace}, {@link org.bukkit.block.Smoker}, or ++ * {@link org.bukkit.block.BlastFurnace}. + */ + public class FurnaceExtractEvent extends BlockExpEvent { + private final Player player; +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java +index 066e7dd9a34d35c8b643a5efcf95d6a5ef47c7ee..f8f9b08a0bd82a2667ae4e0c99dae9103f0db3f0 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java +@@ -6,7 +6,9 @@ import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + + /** +- * Called when an ItemStack is successfully smelted in a furnace. ++ * Called when an ItemStack is successfully smelted in a furnace-like block ++ * such as a {@link org.bukkit.block.Furnace}, {@link org.bukkit.block.Smoker}, ++ * or {@link org.bukkit.block.BlastFurnace}. + */ + public class FurnaceSmeltEvent extends BlockCookEvent { + +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java +index 1440c6115520d692faf75455df35b92aa8734491..0808e7aeffb69160913344de5b5e21d5e857f1d6 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java +@@ -8,7 +8,10 @@ import org.bukkit.inventory.ItemStack; + import org.jetbrains.annotations.NotNull; + + /** +- * Called when a Furnace starts smelting. ++ * Called when any of the furnace-like blocks start smelting. ++ *

      ++ * Furnace-like blocks are {@link org.bukkit.block.Furnace}, ++ * {@link org.bukkit.block.Smoker}, and {@link org.bukkit.block.BlastFurnace}. + */ + public class FurnaceStartSmeltEvent extends InventoryBlockStartEvent { + private static final HandlerList handlers = new HandlerList(); +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +index e1f0ae392c14b940581ed966da42a58ec5cb005d..5832c610e4fad1372e70dc01bd04ba684a89b492 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +@@ -16,12 +16,16 @@ import org.jetbrains.annotations.Nullable; + /** + * This event is called when a player clicks in an inventory. + *

      ++ * In case of a drag action within an inventory, InventoryClickEvent is never called. ++ * Instead, {@link InventoryDragEvent} is called at the end of the drag. ++ *

      + * Because InventoryClickEvent occurs within a modification of the Inventory, + * not all Inventory related methods are safe to use. + *

      +- * The following should never be invoked by an EventHandler for +- * InventoryClickEvent using the HumanEntity or InventoryView associated with +- * this event: ++ * Methods that change the view a player is looking at should never be invoked ++ * by an EventHandler for InventoryClickEvent using the HumanEntity or ++ * InventoryView associated with this event. ++ * Examples of these include: + *

      + */ +- PHYSICAL, ++ // Paper start ++ PHYSICAL; ++ ++ /** ++ * Gets whether this action is a result of a left click. ++ * ++ * @return Whether it's a left click ++ */ ++ public boolean isLeftClick() { ++ return this == LEFT_CLICK_AIR || this == LEFT_CLICK_BLOCK; ++ } ++ ++ /** ++ * Gets whether this action is a result of a right click. ++ * ++ * @return Whether it's a right click ++ */ ++ public boolean isRightClick() { ++ return this == RIGHT_CLICK_AIR || this == RIGHT_CLICK_BLOCK; ++ } ++ // Paper end + } diff --git a/patches/api/0299-Option-to-prevent-data-components-copy-in-smithing-r.patch b/patches/api/0299-Option-to-prevent-data-components-copy-in-smithing-r.patch new file mode 100644 index 000000000000..db16d372fa09 --- /dev/null +++ b/patches/api/0299-Option-to-prevent-data-components-copy-in-smithing-r.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 26 Sep 2021 12:57:35 -0700 +Subject: [PATCH] Option to prevent data components copy in smithing recipes + + +diff --git a/src/main/java/org/bukkit/inventory/SmithingRecipe.java b/src/main/java/org/bukkit/inventory/SmithingRecipe.java +index 6ad1f37372cd77c0f0534deae53125ad148caa7f..eb1c83455e198ff9d6334499be1a865db8e03a2c 100644 +--- a/src/main/java/org/bukkit/inventory/SmithingRecipe.java ++++ b/src/main/java/org/bukkit/inventory/SmithingRecipe.java +@@ -14,6 +14,7 @@ public class SmithingRecipe implements Recipe, Keyed { + private final ItemStack result; + private final RecipeChoice base; + private final RecipeChoice addition; ++ private final boolean copyDataComponents; // Paper + + /** + * Create a smithing recipe to produce the specified result ItemStack. +@@ -29,6 +30,23 @@ public class SmithingRecipe implements Recipe, Keyed { + */ + @Deprecated(since = "1.20.1") + public SmithingRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @Nullable RecipeChoice base, @Nullable RecipeChoice addition) { ++ // Paper start ++ this(key, result, base, addition, true); ++ } ++ /** ++ * Create a smithing recipe to produce the specified result ItemStack. ++ * ++ * @param key The unique recipe key ++ * @param result The item you want the recipe to create. ++ * @param base The base ingredient ++ * @param addition The addition ingredient ++ * @param copyDataComponents whether to copy the data components from the input base item to the output ++ * @deprecated use {@link SmithingTrimRecipe} or {@link SmithingTransformRecipe} ++ */ ++ @Deprecated ++ public SmithingRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @Nullable RecipeChoice base, @Nullable RecipeChoice addition, boolean copyDataComponents) { ++ this.copyDataComponents = copyDataComponents; ++ // Paper end + this.key = key; + this.result = result; + this.base = base; +@@ -66,4 +84,26 @@ public class SmithingRecipe implements Recipe, Keyed { + public NamespacedKey getKey() { + return this.key; + } ++ ++ // Paper start ++ /** ++ * Whether to copy the NBT of the input base item to the output. ++ * ++ * @return true to copy the NBT (default for vanilla smithing recipes) ++ * @apiNote use {@link #willCopyDataComponents()} ++ */ ++ @org.jetbrains.annotations.ApiStatus.Obsolete(since = "1.20.5") ++ public boolean willCopyNbt() { ++ return this.willCopyDataComponents(); ++ } ++ ++ /** ++ * Whether to copy the data components of the input base item to the output. ++ * ++ * @return true to copy the data components (default for vanilla smithing recipes) ++ */ ++ public boolean willCopyDataComponents() { ++ return this.copyDataComponents; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/SmithingTransformRecipe.java b/src/main/java/org/bukkit/inventory/SmithingTransformRecipe.java +index 7a9d77a0cd1c287a3f940f94d4398f84720488aa..e5726da0507ee70cb9dd76c57da6a8442e771307 100644 +--- a/src/main/java/org/bukkit/inventory/SmithingTransformRecipe.java ++++ b/src/main/java/org/bukkit/inventory/SmithingTransformRecipe.java +@@ -24,6 +24,22 @@ public class SmithingTransformRecipe extends SmithingRecipe { + super(key, result, base, addition); + this.template = template; + } ++ // Paper start ++ /** ++ * Create a smithing recipe to produce the specified result ItemStack. ++ * ++ * @param key The unique recipe key ++ * @param result The item you want the recipe to create. ++ * @param template The template item. ++ * @param base The base ingredient ++ * @param addition The addition ingredient ++ * @param copyDataComponents whether to copy the data components from the input base item to the output ++ */ ++ public SmithingTransformRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @Nullable RecipeChoice template, @Nullable RecipeChoice base, @Nullable RecipeChoice addition, boolean copyDataComponents) { ++ super(key, result, base, addition, copyDataComponents); ++ this.template = template; ++ } ++ // Paper end + + /** + * Get the template recipe item. +diff --git a/src/main/java/org/bukkit/inventory/SmithingTrimRecipe.java b/src/main/java/org/bukkit/inventory/SmithingTrimRecipe.java +index 4271c54cfbb0fabd241794d8aea31374d7efe45a..232aa8aeef9e34146e413e56b3681919c8850687 100644 +--- a/src/main/java/org/bukkit/inventory/SmithingTrimRecipe.java ++++ b/src/main/java/org/bukkit/inventory/SmithingTrimRecipe.java +@@ -24,6 +24,21 @@ public class SmithingTrimRecipe extends SmithingRecipe implements ComplexRecipe + super(key, new ItemStack(Material.AIR), base, addition); + this.template = template; + } ++ // Paper start ++ /** ++ * Create a smithing recipe to produce the specified result ItemStack. ++ * ++ * @param key The unique recipe key ++ * @param template The template item. ++ * @param base The base ingredient ++ * @param addition The addition ingredient ++ * @param copyDataComponents whether to copy the data components from the input base item to the output ++ */ ++ public SmithingTrimRecipe(@NotNull NamespacedKey key, @NotNull RecipeChoice template, @NotNull RecipeChoice base, @NotNull RecipeChoice addition, boolean copyDataComponents) { ++ super(key, new ItemStack(Material.AIR), base, addition, copyDataComponents); ++ this.template = template; ++ } ++ // Paper end + + /** + * Get the template recipe item. diff --git a/patches/api/0300-More-CommandBlock-API.patch b/patches/api/0300-More-CommandBlock-API.patch new file mode 100644 index 000000000000..077206eca6e0 --- /dev/null +++ b/patches/api/0300-More-CommandBlock-API.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 28 May 2021 21:47:39 -0700 +Subject: [PATCH] More CommandBlock API + + +diff --git a/src/main/java/io/papermc/paper/command/CommandBlockHolder.java b/src/main/java/io/papermc/paper/command/CommandBlockHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8dc061e38a1728ec4d9dddcb3564ed1b1da746c8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/CommandBlockHolder.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.command; ++ ++import net.kyori.adventure.text.Component; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++@NullMarked ++public interface CommandBlockHolder { ++ ++ /** ++ * Gets the command that this CommandBlock will run when powered. ++ * This will never return null. If the CommandBlock does not have a ++ * command, an empty String will be returned instead. ++ * ++ * @return Command that this CommandBlock will run when activated. ++ */ ++ String getCommand(); ++ ++ /** ++ * Sets the command that this CommandBlock will run when powered. ++ * Setting the command to null is the same as setting it to an empty ++ * String. ++ * ++ * @param command Command that this CommandBlock will run when activated. ++ */ ++ void setCommand(@Nullable String command); ++ ++ /** ++ * Gets the last output from this command block. ++ * ++ * @return the last output ++ */ ++ Component lastOutput(); ++ ++ /** ++ * Sets the last output from this command block. ++ * ++ * @param lastOutput the last output ++ */ ++ void lastOutput(@Nullable Component lastOutput); ++ ++ /** ++ * Gets the success count from this command block. ++ * @see Command_Block#Success_count ++ * ++ * @return the success count ++ */ ++ int getSuccessCount(); ++ ++ /** ++ * Sets the success count from this command block. ++ * @see Command_Block#Success_count ++ * ++ * @param successCount the success count ++ */ ++ void setSuccessCount(int successCount); ++} +diff --git a/src/main/java/org/bukkit/block/CommandBlock.java b/src/main/java/org/bukkit/block/CommandBlock.java +index 9c88be68b4f403d0500cb607394b3a1646675ef7..02bf0f8c12052dd5c17422153228083f56bea75b 100644 +--- a/src/main/java/org/bukkit/block/CommandBlock.java ++++ b/src/main/java/org/bukkit/block/CommandBlock.java +@@ -6,7 +6,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a command block. + */ +-public interface CommandBlock extends TileState { ++public interface CommandBlock extends TileState, io.papermc.paper.command.CommandBlockHolder { // Paper + + /** + * Gets the command that this CommandBlock will run when powered. +diff --git a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +index 91cab8b13d5bba34007f124838b32a1df58c5ac7..6a6021ad3a0e6aaf51f5144fa126e81bada9cfcf 100644 +--- a/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/CommandMinecart.java +@@ -4,7 +4,7 @@ import org.bukkit.entity.Minecart; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-public interface CommandMinecart extends Minecart { ++public interface CommandMinecart extends Minecart, io.papermc.paper.command.CommandBlockHolder { // Paper + + /** + * Gets the command that this CommandMinecart will run when activated. diff --git a/patches/api/0301-Add-missing-team-sidebar-display-slots.patch b/patches/api/0301-Add-missing-team-sidebar-display-slots.patch new file mode 100644 index 000000000000..cdecbd1764fe --- /dev/null +++ b/patches/api/0301-Add-missing-team-sidebar-display-slots.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 1 Oct 2021 08:04:43 -0700 +Subject: [PATCH] Add missing team sidebar display slots + + +diff --git a/src/main/java/org/bukkit/scoreboard/DisplaySlot.java b/src/main/java/org/bukkit/scoreboard/DisplaySlot.java +index 4959bec21d152a17fe4ca9d3f448aef482a05b5e..21cd2ba659504c3a1eb95226539a5701d0c324db 100644 +--- a/src/main/java/org/bukkit/scoreboard/DisplaySlot.java ++++ b/src/main/java/org/bukkit/scoreboard/DisplaySlot.java +@@ -1,26 +1,55 @@ + package org.bukkit.scoreboard; + ++import net.kyori.adventure.text.format.NamedTextColor; // Paper + /** + * Locations for displaying objectives to the player + */ + public enum DisplaySlot { +- BELOW_NAME, +- PLAYER_LIST, +- SIDEBAR, +- SIDEBAR_BLACK, +- SIDEBAR_DARK_BLUE, +- SIDEBAR_DARK_GREEN, +- SIDEBAR_DARK_AQUA, +- SIDEBAR_DARK_RED, +- SIDEBAR_DARK_PURPLE, +- SIDEBAR_GOLD, +- SIDEBAR_GRAY, +- SIDEBAR_DARK_GRAY, +- SIDEBAR_BLUE, +- SIDEBAR_GREEN, +- SIDEBAR_AQUA, +- SIDEBAR_RED, +- SIDEBAR_LIGHT_PURPLE, +- SIDEBAR_YELLOW, +- SIDEBAR_WHITE; ++ // Paper start ++ BELOW_NAME("below_name"), ++ PLAYER_LIST("list"), ++ SIDEBAR("sidebar"), ++ SIDEBAR_TEAM_BLACK(NamedTextColor.BLACK), ++ SIDEBAR_TEAM_DARK_BLUE(NamedTextColor.DARK_BLUE), ++ SIDEBAR_TEAM_DARK_GREEN(NamedTextColor.DARK_GREEN), ++ SIDEBAR_TEAM_DARK_AQUA(NamedTextColor.DARK_AQUA), ++ SIDEBAR_TEAM_DARK_RED(NamedTextColor.DARK_RED), ++ SIDEBAR_TEAM_DARK_PURPLE(NamedTextColor.DARK_PURPLE), ++ SIDEBAR_TEAM_GOLD(NamedTextColor.GOLD), ++ SIDEBAR_TEAM_GRAY(NamedTextColor.GRAY), ++ SIDEBAR_TEAM_DARK_GRAY(NamedTextColor.DARK_GRAY), ++ SIDEBAR_TEAM_BLUE(NamedTextColor.BLUE), ++ SIDEBAR_TEAM_GREEN(NamedTextColor.GREEN), ++ SIDEBAR_TEAM_AQUA(NamedTextColor.AQUA), ++ SIDEBAR_TEAM_RED(NamedTextColor.RED), ++ SIDEBAR_TEAM_LIGHT_PURPLE(NamedTextColor.LIGHT_PURPLE), ++ SIDEBAR_TEAM_YELLOW(NamedTextColor.YELLOW), ++ SIDEBAR_TEAM_WHITE(NamedTextColor.WHITE); ++ ++ public static final net.kyori.adventure.util.Index NAMES = net.kyori.adventure.util.Index.create(DisplaySlot.class, DisplaySlot::getId); ++ ++ private final String id; ++ ++ DisplaySlot(@org.jetbrains.annotations.NotNull String id) { ++ this.id = id; ++ } ++ ++ DisplaySlot(@org.jetbrains.annotations.NotNull NamedTextColor color) { ++ this.id = "sidebar.team." + color; ++ } ++ ++ /** ++ * Get the string id of this display slot. ++ * ++ * @return the string id ++ */ ++ public @org.jetbrains.annotations.NotNull String getId() { ++ return id; ++ } ++ ++ @Override ++ public String toString() { ++ return this.id; ++ } ++ // Paper end + } diff --git a/patches/api/0302-add-back-EntityPortalExitEvent.patch b/patches/api/0302-add-back-EntityPortalExitEvent.patch new file mode 100644 index 000000000000..5a153e234526 --- /dev/null +++ b/patches/api/0302-add-back-EntityPortalExitEvent.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 May 2021 02:49:28 -0700 +Subject: [PATCH] add back EntityPortalExitEvent + +Was removed here: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/a2d787f6ebeb72fa7d5750788221fb9a0d838ac4 + +diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalExitEvent.java b/src/main/java/org/bukkit/event/entity/EntityPortalExitEvent.java +index 869ad3b12ebd8275d04b0c21b5ecc0389da01490..0a87e2934901eb1bcaec72ed8141cd4828a4efce 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPortalExitEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPortalExitEvent.java +@@ -11,6 +11,9 @@ import org.jetbrains.annotations.NotNull; + *

      + * This event allows you to modify the velocity of the entity after they have + * successfully exited the portal. ++ *

      ++ * Cancelling this event does not prevent the teleport, but it does prevent ++ * any changes to velocity and location from taking place. + */ + public class EntityPortalExitEvent extends EntityTeleportEvent { + private static final HandlerList handlers = new HandlerList(); diff --git a/patches/api/0303-Add-methods-to-find-targets-for-lightning-strikes.patch b/patches/api/0303-Add-methods-to-find-targets-for-lightning-strikes.patch new file mode 100644 index 000000000000..ffb2f027aacb --- /dev/null +++ b/patches/api/0303-Add-methods-to-find-targets-for-lightning-strikes.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jakub Zacek +Date: Mon, 4 Oct 2021 08:29:36 +0200 +Subject: [PATCH] Add methods to find targets for lightning strikes + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 8084bb2d8f3983e10de9123b74627ed04d8b5255..a8939bb5815fbc2926907bb3e8921f86255abd93 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -692,6 +692,37 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @NotNull + public LightningStrike strikeLightningEffect(@NotNull Location loc); + ++ // Paper start ++ /** ++ * Finds the location of the nearest unobstructed Lightning Rod in a 128-block ++ * radius around the given location. Returns {@code null} if no Lightning Rod is found. ++ * ++ *

      Note: To activate a Lightning Rod, the position one block above it must be struck by lightning.

      ++ * ++ * @param location {@link Location} to search for Lightning Rod around ++ * @return {@link Location} of Lightning Rod or {@code null} ++ */ ++ @Nullable ++ public Location findLightningRod(@NotNull Location location); ++ ++ /** ++ * Finds a target {@link Location} for lightning to strike. ++ *

      It selects from (in the following order):

      ++ *
        ++ *
      1. the block above the nearest Lightning Rod, found using {@link World#findLightningRod(Location)}
      2. ++ *
      3. a random {@link LivingEntity} that can see the sky in a 6x6 cuboid ++ * around input X/Z coordinates. Y ranges from the highest motion-blocking ++ * block at the input X/Z - 3 to the height limit + 3
      4. ++ *
      ++ *

      Returns {@code null} if no target is found.

      ++ * ++ * @param location {@link Location} to search for target around ++ * @return lightning target or {@code null} ++ */ ++ @Nullable ++ public Location findLightningTarget(@NotNull Location location); ++ // Paper end ++ + /** + * Get a list of all entities in this World + * diff --git a/patches/api/0304-Get-entity-default-attributes.patch b/patches/api/0304-Get-entity-default-attributes.patch new file mode 100644 index 000000000000..92815605ef87 --- /dev/null +++ b/patches/api/0304-Get-entity-default-attributes.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 20 Aug 2021 13:03:55 -0700 +Subject: [PATCH] Get entity default attributes + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 218adc63a0c0037f764942af184b30ebabff697d..4cd43815c317cfa1dd0ac15fb469d601aee42e60 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -197,5 +197,22 @@ public interface UnsafeValues { + * @return true if valid repair, false if not + */ + public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); ++ ++ /** ++ * Checks if the entity represented by the namespaced key has default attributes. ++ * ++ * @param entityKey the entity's key ++ * @return true if it has default attributes ++ */ ++ boolean hasDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); ++ ++ /** ++ * Gets the default attributes for the entity represented by the namespaced key. ++ * ++ * @param entityKey the entity's key ++ * @return an unmodifiable instance of Attributable for reading default attributes. ++ * @throws IllegalArgumentException if the entity does not exist of have default attributes (use {@link #hasDefaultEntityAttributes(NamespacedKey)} first) ++ */ ++ @org.jetbrains.annotations.NotNull org.bukkit.attribute.Attributable getDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/EntityType.java b/src/main/java/org/bukkit/entity/EntityType.java +index fd5d1ad0334b574fca951555ce647436257d9b19..6bc514af551374a9c6f2f2a8dbcb35a0a543a23f 100644 +--- a/src/main/java/org/bukkit/entity/EntityType.java ++++ b/src/main/java/org/bukkit/entity/EntityType.java +@@ -477,6 +477,25 @@ public enum EntityType implements Keyed, Translatable, net.kyori.adventure.trans + Preconditions.checkArgument(this != UNKNOWN, "UNKNOWN entities do not have translation keys"); + return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); + } ++ ++ /** ++ * Checks if the entity has default attributes. ++ * ++ * @return true if it has default attributes ++ */ ++ public boolean hasDefaultAttributes() { ++ return org.bukkit.Bukkit.getUnsafe().hasDefaultEntityAttributes(this.key); ++ } ++ ++ /** ++ * Gets the default attributes for the entity. ++ * ++ * @return an unmodifiable instance of Attributable for reading default attributes. ++ * @throws IllegalArgumentException if the entity does not exist of have default attributes (use {@link #hasDefaultAttributes()} first) ++ */ ++ public @NotNull org.bukkit.attribute.Attributable getDefaultAttributes() { ++ return org.bukkit.Bukkit.getUnsafe().getDefaultEntityAttributes(this.key); ++ } + // Paper end + + /** diff --git a/patches/api/0305-Left-handed-API.patch b/patches/api/0305-Left-handed-API.patch new file mode 100644 index 000000000000..ea746f73d47b --- /dev/null +++ b/patches/api/0305-Left-handed-API.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 14 Oct 2021 12:36:46 -0500 +Subject: [PATCH] Left handed API + + +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index 91d31e5418a5ab7cefd7c02a41bbec8464fe7ab1..d55250d820b02f3a23b99a59e68d3361698baddf 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -204,4 +204,20 @@ public interface Mob extends LivingEntity, Lootable { + */ + void setAggressive(boolean aggressive); + // Paper end - Missing Entity API ++ ++ // Paper start - left-handed API ++ /** ++ * Check if Mob is left-handed ++ * ++ * @return True if left-handed ++ */ ++ public boolean isLeftHanded(); ++ ++ /** ++ * Set if Mob is left-handed ++ * ++ * @param leftHanded True if left-handed ++ */ ++ public void setLeftHanded(boolean leftHanded); ++ // Paper end - left-handed API + } diff --git a/patches/api/0306-Add-critical-damage-API.patch b/patches/api/0306-Add-critical-damage-API.patch new file mode 100644 index 000000000000..419d0d892f0c --- /dev/null +++ b/patches/api/0306-Add-critical-damage-API.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dodison +Date: Mon, 26 Jul 2021 17:35:20 +0200 +Subject: [PATCH] Add critical damage API + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java +index ca6f0fa51f7f0133dabb912508b6f4d2eeea0927..341f99550d077c60306e8a246a254b768ebbeb48 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java +@@ -5,6 +5,7 @@ import java.util.Map; + import org.bukkit.damage.DamageSource; + import org.bukkit.damage.DamageType; + import org.bukkit.entity.Entity; ++import org.jetbrains.annotations.ApiStatus; + import org.jetbrains.annotations.NotNull; + + /** +@@ -12,15 +13,18 @@ import org.jetbrains.annotations.NotNull; + */ + public class EntityDamageByEntityEvent extends EntityDamageEvent { + private final Entity damager; ++ private final boolean critical; // Paper + + @Deprecated(since = "1.20.4", forRemoval = true) + public EntityDamageByEntityEvent(@NotNull final Entity damager, @NotNull final Entity damagee, @NotNull final DamageCause cause, final double damage) { + this(damager, damagee, cause, DamageSource.builder(DamageType.GENERIC).withCausingEntity(damager).withDirectEntity(damager).build(), damage); + } + ++ @Deprecated + public EntityDamageByEntityEvent(@NotNull final Entity damager, @NotNull final Entity damagee, @NotNull final DamageCause cause, @NotNull final DamageSource damageSource, final double damage) { + super(damagee, cause, damageSource, damage); + this.damager = damager; ++ this.critical = false; // Paper - add critical damage API + } + + @Deprecated(since = "1.20.4", forRemoval = true) +@@ -28,11 +32,34 @@ public class EntityDamageByEntityEvent extends EntityDamageEvent { + this(damager, damagee, cause, DamageSource.builder(DamageType.GENERIC).withCausingEntity(damager).withDirectEntity(damager).build(), modifiers, modifierFunctions); + } + ++ @Deprecated + public EntityDamageByEntityEvent(@NotNull final Entity damager, @NotNull final Entity damagee, @NotNull final DamageCause cause, @NotNull final DamageSource damageSource, @NotNull final Map modifiers, @NotNull final Map> modifierFunctions) { + super(damagee, cause, damageSource, modifiers, modifierFunctions); + this.damager = damager; ++ // Paper start ++ this.critical = false; + } + ++ @ApiStatus.Internal ++ public EntityDamageByEntityEvent(@NotNull final Entity damager, @NotNull final Entity damagee, @NotNull final DamageCause cause, @NotNull final DamageSource damageSource, @NotNull final Map modifiers, @NotNull final Map> modifierFunctions, boolean critical) { ++ super(damagee, cause, damageSource, modifiers, modifierFunctions); ++ this.damager = damager; ++ this.critical = critical; ++ } ++ ++ /** ++ * Shows this damage instance was critical. ++ * The damage instance can be critical if the attacking player met the respective conditions. ++ * Furthermore, arrows may also cause a critical damage event if the arrow {@link org.bukkit.entity.AbstractArrow#isCritical()}. ++ * ++ * @return if the hit was critical. ++ * @see https://minecraft.wiki/wiki/Damage#Critical_hit ++ */ ++ public boolean isCritical() { ++ return this.critical; ++ } ++ // Paper end ++ + /** + * Returns the entity that damaged the defender. + * diff --git a/patches/api/0307-Add-more-advancement-API.patch b/patches/api/0307-Add-more-advancement-API.patch new file mode 100644 index 000000000000..1f051ac4c445 --- /dev/null +++ b/patches/api/0307-Add-more-advancement-API.patch @@ -0,0 +1,264 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: syldium +Date: Fri, 9 Jul 2021 18:49:40 +0200 +Subject: [PATCH] Add more advancement API + +Co-authored-by: Jake Potrebic + +diff --git a/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java b/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java +new file mode 100644 +index 0000000000000000000000000000000000000000..59228f2e66e982feca77d9f962004ceacb648783 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java +@@ -0,0 +1,160 @@ ++package io.papermc.paper.advancement; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.translation.Translatable; ++import net.kyori.adventure.util.Index; ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.ItemStack; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Describes the display of an advancement. ++ *

      ++ * The display is used in the chat, in the toast messages and the advancements ++ * screen. ++ */ ++@NullMarked ++public interface AdvancementDisplay { ++ ++ /** ++ * Gets the {@link Frame}. ++ *

      ++ * This defines the appearance of the tile in the advancements screen and ++ * the text when it's completed. ++ * ++ * @return the frame type ++ */ ++ Frame frame(); ++ ++ /** ++ * Gets the advancement title. ++ * ++ * @return the title ++ */ ++ Component title(); ++ ++ /** ++ * Gets the description. ++ * ++ * @return the description ++ */ ++ Component description(); ++ ++ /** ++ * Gets the icon shown in the frame in the advancements screen. ++ * ++ * @return a copy of the icon ++ */ ++ ItemStack icon(); ++ ++ /** ++ * Gets whether a toast should be displayed. ++ *

      ++ * A toast is a notification that will be displayed in the top right corner ++ * of the screen. ++ * ++ * @return {@code true} if a toast should be shown ++ */ ++ boolean doesShowToast(); ++ ++ /** ++ * Gets whether a message should be sent in the chat. ++ * ++ * @return {@code true} if a message should be sent ++ * @see org.bukkit.event.player.PlayerAdvancementDoneEvent#message() to edit ++ * the message ++ */ ++ boolean doesAnnounceToChat(); ++ ++ /** ++ * Gets whether this advancement is hidden. ++ *

      ++ * Hidden advancements cannot be viewed by the player until they have been ++ * unlocked. ++ * ++ * @return {@code true} if hidden ++ */ ++ boolean isHidden(); ++ ++ /** ++ * Gets the texture displayed behind the advancement tree when selected. ++ *

      ++ * This only affects root advancements without any parent. If the background ++ * is not specified or doesn't exist, the tab background will be the missing ++ * texture. ++ * ++ * @return the background texture path ++ */ ++ @Nullable NamespacedKey backgroundPath(); ++ ++ /** ++ * Gets the formatted display name for this display. This ++ * is a part of the component that would be shown in chat when a player ++ * completes the advancement. ++ * ++ * @return the display name ++ * @see org.bukkit.advancement.Advancement#displayName() ++ */ ++ Component displayName(); ++ ++ /** ++ * Defines how the {@link #icon()} appears in the advancements screen and ++ * the color used with the {@link #title() advancement name}. ++ */ ++ enum Frame implements Translatable { ++ ++ /** ++ * "Challenge complete" advancement. ++ *

      ++ * The client will play the {@code ui.toast.challenge_complete} sound ++ * when the challenge is completed and the toast is shown. ++ */ ++ CHALLENGE("challenge", NamedTextColor.DARK_PURPLE), ++ ++ /** ++ * "Goal reached" advancement. ++ */ ++ GOAL("goal", NamedTextColor.GREEN), ++ ++ /** ++ * "Advancement made" advancement. ++ */ ++ TASK("task", NamedTextColor.GREEN); ++ ++ /** ++ * The name map. ++ */ ++ public static final Index NAMES = Index.create(Frame.class, frame -> frame.name); ++ private final String name; ++ private final TextColor color; ++ ++ Frame(final String name, final TextColor color) { ++ this.name = name; ++ this.color = color; ++ } ++ ++ /** ++ * Gets the {@link TextColor} used for the advancement name. ++ * ++ * @return the text color ++ */ ++ public TextColor color() { ++ return this.color; ++ } ++ ++ /** ++ * Gets the translation key used when an advancement is completed. ++ *

      ++ * This is the first line of the toast displayed by the client. ++ * ++ * @return the toast message key ++ */ ++ @Override ++ public String translationKey() { ++ return "advancements.toast." + this.name; ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/advancement/Advancement.java b/src/main/java/org/bukkit/advancement/Advancement.java +index e683af5eb1d08179acd69c521f8f387dc8051e32..5d7ab518dc6be39965cc8925e5df6792456c6658 100644 +--- a/src/main/java/org/bukkit/advancement/Advancement.java ++++ b/src/main/java/org/bukkit/advancement/Advancement.java +@@ -27,13 +27,53 @@ public interface Advancement extends Keyed { + @NotNull + AdvancementRequirements getRequirements(); + ++ // Paper start + /** +- * Returns the display information for this advancement. ++ * Get the display info of this advancement. ++ *

      ++ * Will be {@code null} when totally hidden, for example with crafting ++ * recipes. + * +- * This includes it's name, description and other visible tags. ++ * @return the display info ++ */ ++ @Nullable ++ io.papermc.paper.advancement.AdvancementDisplay getDisplay(); ++ ++ /** ++ * Gets the formatted display name for this display. This ++ * is part of the component that would be shown in chat when a player ++ * completes the advancement. Will return the same as ++ * {@link io.papermc.paper.advancement.AdvancementDisplay#displayName()} when an ++ * {@link io.papermc.paper.advancement.AdvancementDisplay} is present. + * +- * @return a AdvancementDisplay object, or null if not set. ++ * @return the display name ++ * @see io.papermc.paper.advancement.AdvancementDisplay#displayName() ++ */ ++ @NotNull net.kyori.adventure.text.Component displayName(); ++ ++ /** ++ * Gets the parent advancement, if any. ++ * ++ * @return the parent advancement + */ + @Nullable +- AdvancementDisplay getDisplay(); ++ Advancement getParent(); ++ ++ /** ++ * Gets all the direct children advancements. ++ * ++ * @return the children advancements ++ */ ++ @NotNull ++ @org.jetbrains.annotations.Unmodifiable ++ Collection getChildren(); ++ ++ /** ++ * Gets the root advancement of the tree this is located in. ++ * ++ * @return the root advancement ++ */ ++ @NotNull ++ Advancement getRoot(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/advancement/AdvancementDisplay.java b/src/main/java/org/bukkit/advancement/AdvancementDisplay.java +index 0ff86a39025a94ca128364a45bf171728cb81027..aec6be7e121da3eb8a464b6934da29ab6b473885 100644 +--- a/src/main/java/org/bukkit/advancement/AdvancementDisplay.java ++++ b/src/main/java/org/bukkit/advancement/AdvancementDisplay.java +@@ -5,7 +5,10 @@ import org.jetbrains.annotations.NotNull; + + /** + * Holds information about how the advancement is displayed by the game. ++ * ++ * @deprecated use {@link io.papermc.paper.advancement.AdvancementDisplay} + */ ++@Deprecated(forRemoval = true) // Paper + public interface AdvancementDisplay { + + /** +diff --git a/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java b/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java +index de767efb9f55448df061e166c66a2cf3439d57ec..06d8b72dd54becc13f40bd6e505115405462cd73 100644 +--- a/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java ++++ b/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java +@@ -8,7 +8,9 @@ import org.jetbrains.annotations.NotNull; + * + * This enum contains information about these types and how they are + * represented. ++ * @deprecated use {@link io.papermc.paper.advancement.AdvancementDisplay.Frame} + */ ++@Deprecated(forRemoval = true) + public enum AdvancementDisplayType { + + /** diff --git a/patches/api/0308-Fix-issues-with-mob-conversion.patch b/patches/api/0308-Fix-issues-with-mob-conversion.patch new file mode 100644 index 000000000000..75899f33463a --- /dev/null +++ b/patches/api/0308-Fix-issues-with-mob-conversion.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 24 Oct 2021 20:29:27 -0700 +Subject: [PATCH] Fix issues with mob conversion + + +diff --git a/src/main/java/org/bukkit/entity/Hoglin.java b/src/main/java/org/bukkit/entity/Hoglin.java +index 83a9e06fe91bdfe74e771b170966c70e4c47893c..452a8e73fa084f29f3b96793d642bd8ec0bc8aac 100644 +--- a/src/main/java/org/bukkit/entity/Hoglin.java ++++ b/src/main/java/org/bukkit/entity/Hoglin.java +@@ -44,13 +44,17 @@ public interface Hoglin extends Animals, Enemy { + public int getConversionTime(); + + /** +- * Sets the amount of ticks until this entity will be converted to a Zoglin. ++ * Sets the conversion counter value. The counter is incremented ++ * every tick the method {@link #isConverting()} returns true. Setting ++ * this value will not start the conversion if the {@link Hoglin} is ++ * not in a valid environment ({@link org.bukkit.World#isPiglinSafe}) ++ * to convert, is immune to zombification ({@link #isImmuneToZombification()}) ++ * or has no AI ({@link #hasAI}). + * +- * When this reaches 0, the entity will be converted. A value of less than 0 +- * will stop the current conversion process without converting the current +- * entity. ++ * When this reaches 300, the entity will be converted. To stop the ++ * conversion use {@link #setImmuneToZombification(boolean)}. + * +- * @param time new conversion time ++ * @param time new conversion counter + */ + public void setConversionTime(int time); + +diff --git a/src/main/java/org/bukkit/entity/PiglinAbstract.java b/src/main/java/org/bukkit/entity/PiglinAbstract.java +index 9c4c1a4ab37403303c395db2764134abb10206d5..41aeb01f75380f5f40a8c0eb3f52ec3d9cade04d 100644 +--- a/src/main/java/org/bukkit/entity/PiglinAbstract.java ++++ b/src/main/java/org/bukkit/entity/PiglinAbstract.java +@@ -31,14 +31,17 @@ public interface PiglinAbstract extends Monster, Ageable { + public int getConversionTime(); + + /** +- * Sets the amount of ticks until this entity will be converted to a +- * Zombified Piglin. ++ * Sets the conversion counter value. The counter is incremented ++ * every tick the method {@link #isConverting()} returns true. Setting ++ * this value will not start the conversion if the {@link PiglinAbstract} is ++ * not in a valid environment ({@link org.bukkit.World#isPiglinSafe}) ++ * to convert, is immune to zombification ({@link #isImmuneToZombification()}) ++ * or has no AI ({@link #hasAI}). + * +- * When this reaches 0, the entity will be converted. A value of less than 0 +- * will stop the current conversion process without converting the current +- * entity. ++ * When this reaches 300, the entity will be converted. To stop the ++ * conversion use {@link #setImmuneToZombification(boolean)}. + * +- * @param time new conversion time ++ * @param time new conversion counter + */ + public void setConversionTime(int time); + diff --git a/patches/api/0309-Add-hasCollision-methods-to-various-places.patch b/patches/api/0309-Add-hasCollision-methods-to-various-places.patch new file mode 100644 index 000000000000..09f465abcc2b --- /dev/null +++ b/patches/api/0309-Add-hasCollision-methods-to-various-places.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 4 Nov 2021 11:50:35 -0700 +Subject: [PATCH] Add hasCollision methods to various places + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index e8985981deb7d23ec624781725c4a05cc9cc94e7..b28ab97ff80c9e7af85d8830f26fd0f252082541 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -4877,6 +4877,21 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla + } + // Paper end - item default attributes API + ++ // Paper start - isCollidable API ++ /** ++ * Checks if this material is collidable. ++ * ++ * @return true if collidable ++ * @throws IllegalArgumentException if {@link #isBlock()} is false ++ */ ++ public boolean isCollidable() { ++ if (this.isBlock()) { ++ return this.asBlockType().hasCollision(); ++ } ++ throw new IllegalArgumentException(this + " isn't a block type"); ++ } ++ // Paper end - isCollidable API ++ + /** + * Do not use for any reason. + * +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index bd50ec2a93800af9ce663fd10ecf74ae011a6715..7f9acd155c1b275145ba53a41b7513dc8cc00531 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -486,6 +486,13 @@ public interface Block extends Metadatable, Translatable, net.kyori.adventure.tr + * @return true if block is solid + */ + boolean isSolid(); ++ ++ /** ++ * Checks if this block is collidable. ++ * ++ * @return true if collidable ++ */ ++ boolean isCollidable(); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/block/BlockState.java b/src/main/java/org/bukkit/block/BlockState.java +index 555d0492c2fcf85c1e2f95f145b974cb75bc5ecc..ee4cbbc584ec1a10c62464a7abb3ea5da656ffc0 100644 +--- a/src/main/java/org/bukkit/block/BlockState.java ++++ b/src/main/java/org/bukkit/block/BlockState.java +@@ -245,4 +245,13 @@ public interface BlockState extends Metadatable { + * or 'virtual' (e.g. on an itemstack) + */ + boolean isPlaced(); ++ ++ // Paper start ++ /** ++ * Checks if this block state is collidable. ++ * ++ * @return true if collidable ++ */ ++ boolean isCollidable(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/block/BlockType.java b/src/main/java/org/bukkit/block/BlockType.java +index f0c3343e2006f244bb1f99c269bcbaa357feb25f..a2376f08c836d727995987a640a47f8f3a7b0c11 100644 +--- a/src/main/java/org/bukkit/block/BlockType.java ++++ b/src/main/java/org/bukkit/block/BlockType.java +@@ -3625,4 +3625,13 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran + @Override + @NotNull String getTranslationKey(); + // Paper end - add Translatable ++ ++ // Paper start - hasCollision API ++ /** ++ * Checks if this block type has collision. ++ *

      ++ * @return false if this block never has collision, true if it might have collision ++ */ ++ boolean hasCollision(); ++ // Paper end - hasCollision API + } diff --git a/patches/api/0310-Goat-ram-API.patch b/patches/api/0310-Goat-ram-API.patch new file mode 100644 index 000000000000..06d426a7866e --- /dev/null +++ b/patches/api/0310-Goat-ram-API.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seggan +Date: Thu, 5 Aug 2021 13:10:31 -0400 +Subject: [PATCH] Goat ram API + + +diff --git a/src/main/java/org/bukkit/entity/Goat.java b/src/main/java/org/bukkit/entity/Goat.java +index 3a24f8cc7a6dee3da30a73f1294cccf03680bdd5..18e48bbb04076f1535b6a4c10e139908e82da44e 100644 +--- a/src/main/java/org/bukkit/entity/Goat.java ++++ b/src/main/java/org/bukkit/entity/Goat.java +@@ -52,4 +52,12 @@ public interface Goat extends Animals { + * @param screaming screaming status + */ + void setScreaming(boolean screaming); ++ ++ // Paper start - Goat ram API ++ /** ++ * Makes the goat ram at the specified entity ++ * @param entity the entity to ram at ++ */ ++ void ram(@org.jetbrains.annotations.NotNull LivingEntity entity); ++ // Paper end + } diff --git a/patches/api/0311-Add-API-for-resetting-a-single-score.patch b/patches/api/0311-Add-API-for-resetting-a-single-score.patch new file mode 100644 index 000000000000..a071aa88f79f --- /dev/null +++ b/patches/api/0311-Add-API-for-resetting-a-single-score.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: booky10 +Date: Fri, 5 Nov 2021 21:01:36 +0100 +Subject: [PATCH] Add API for resetting a single score + +It was only possible to reset all scores for a specific entry, instead of resetting only specific scores. + +diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java +index 787bb91b48e3ed798e85ba57c8b218c0082bc85c..48a1654a2dd8da82cb91bcfa4b3a523f88323568 100644 +--- a/src/main/java/org/bukkit/scoreboard/Score.java ++++ b/src/main/java/org/bukkit/scoreboard/Score.java +@@ -73,4 +73,14 @@ public interface Score { + */ + @Nullable + Scoreboard getScoreboard(); ++ ++ // Paper start ++ /** ++ * Resets this score, if a value has been set. ++ * ++ * @throws IllegalStateException if the associated objective has been ++ * unregistered ++ */ ++ void resetScore() throws IllegalStateException; ++ // Paper end + } diff --git a/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch b/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch new file mode 100644 index 000000000000..381f5dd0d5f8 --- /dev/null +++ b/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mariell Hoversholm +Date: Sun, 24 Oct 2021 16:19:26 -0400 +Subject: [PATCH] Add Raw Byte Entity Serialization + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 4cd43815c317cfa1dd0ac15fb469d601aee42e60..5be89089da4e8230dc7aa078712428189f38d9f9 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -169,6 +169,14 @@ public interface UnsafeValues { + + ItemStack deserializeItem(byte[] data); + ++ byte[] serializeEntity(org.bukkit.entity.Entity entity); ++ ++ default org.bukkit.entity.Entity deserializeEntity(byte[] data, World world) { ++ return deserializeEntity(data, world, false); ++ } ++ ++ org.bukkit.entity.Entity deserializeEntity(byte[] data, World world, boolean preserveUUID); ++ + /** + * Creates and returns the next EntityId available. + *

      +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 3b40c63a380e519ecae2e272754a53aff5aebd9a..464668496f5a611ae78bd5f6392915ec384862ac 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -946,5 +946,32 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + @Deprecated + @NotNull Set getTrackedPlayers(); ++ ++ /** ++ * Spawns the entity in the world at the given {@link Location} with the default spawn reason. ++ *

      ++ * This will not spawn the entity if the entity is already spawned or has previously been despawned. ++ *

      ++ * Also, this method will fire the same events as a normal entity spawn. ++ * ++ * @param location The location to spawn the entity at. ++ * @return Whether the entity was successfully spawned. ++ */ ++ public default boolean spawnAt(@NotNull Location location) { ++ return spawnAt(location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ /** ++ * Spawns the entity in the world at the given {@link Location} with the reason given. ++ *

      ++ * This will not spawn the entity if the entity is already spawned or has previously been despawned. ++ *

      ++ * Also, this method will fire the same events as a normal entity spawn. ++ * ++ * @param location The location to spawn the entity at. ++ * @param reason The reason for the entity being spawned. ++ * @return Whether the entity was successfully spawned. ++ */ ++ public boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason); + // Paper end + } diff --git a/patches/api/0313-Add-PlayerItemFrameChangeEvent.patch b/patches/api/0313-Add-PlayerItemFrameChangeEvent.patch new file mode 100644 index 000000000000..2231459fbb60 --- /dev/null +++ b/patches/api/0313-Add-PlayerItemFrameChangeEvent.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SamB440 +Date: Mon, 15 Nov 2021 18:09:46 +0000 +Subject: [PATCH] Add PlayerItemFrameChangeEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerItemFrameChangeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerItemFrameChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f387477da45a44cc7788ed5342104f535cf3cb98 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerItemFrameChangeEvent.java +@@ -0,0 +1,99 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.ItemFrame; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Called when an {@link ItemFrame} is having an item rotated, added, or removed from it. ++ */ ++@NullMarked ++public class PlayerItemFrameChangeEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final ItemFrame itemFrame; ++ private final ItemFrameChangeAction action; ++ private ItemStack itemStack; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PlayerItemFrameChangeEvent(final Player player, final ItemFrame itemFrame, final ItemStack itemStack, final ItemFrameChangeAction action) { ++ super(player); ++ this.itemFrame = itemFrame; ++ this.itemStack = itemStack; ++ this.action = action; ++ } ++ ++ /** ++ * Gets the {@link ItemFrame} involved in this event. ++ * ++ * @return the {@link ItemFrame} ++ */ ++ public ItemFrame getItemFrame() { ++ return this.itemFrame; ++ } ++ ++ /** ++ * Gets the {@link ItemStack} involved in this event. ++ * This is the item being added, rotated, or removed from the {@link ItemFrame}. ++ *

      ++ * If this method returns air, then the resulting item in the ItemFrame will be empty. ++ * ++ * @return the {@link ItemStack} being added, rotated, or removed ++ */ ++ public ItemStack getItemStack() { ++ return this.itemStack; ++ } ++ ++ /** ++ * Sets the {@link ItemStack} that this {@link ItemFrame} holds. ++ * If {@code null} is provided, the ItemStack will become air and the result in the ItemFrame will be empty. ++ * ++ * @param itemStack {@link ItemFrame} item ++ */ ++ public void setItemStack(final @Nullable ItemStack itemStack) { ++ this.itemStack = itemStack == null ? ItemStack.empty() : itemStack; ++ } ++ ++ /** ++ * Gets the action that was performed on this {@link ItemFrame}. ++ * ++ * @return action performed on the item frame in this event ++ */ ++ public ItemFrameChangeAction getAction() { ++ return this.action; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public enum ItemFrameChangeAction { ++ PLACE, ++ REMOVE, ++ ROTATE ++ } ++} diff --git a/patches/api/0314-Add-more-Campfire-API.patch b/patches/api/0314-Add-more-Campfire-API.patch new file mode 100644 index 000000000000..80cdc0bb3905 --- /dev/null +++ b/patches/api/0314-Add-more-Campfire-API.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Fri, 16 Jul 2021 00:38:52 +0900 +Subject: [PATCH] Add more Campfire API + + +diff --git a/src/main/java/org/bukkit/block/Campfire.java b/src/main/java/org/bukkit/block/Campfire.java +index f8a344cabb7b5a6d1c5409798a0a98b023bcd756..9c3952459ed216f727b3654b2ed536f17f320402 100644 +--- a/src/main/java/org/bukkit/block/Campfire.java ++++ b/src/main/java/org/bukkit/block/Campfire.java +@@ -69,4 +69,40 @@ public interface Campfire extends TileState { + * @param cookTimeTotal Cook time total + */ + void setCookTimeTotal(int index, int cookTimeTotal); ++ ++ // Paper start ++ /** ++ * Disable cooking in all slots. ++ */ ++ void stopCooking(); ++ ++ /** ++ * Re-enable cooking in all slots. ++ */ ++ void startCooking(); ++ ++ /** ++ * Disable cooking in the specified slot index. ++ * ++ * @param index item slot index ++ * @return whether the slot had cooking enabled before this call ++ */ ++ boolean stopCooking(int index); ++ ++ /** ++ * Re-enable cooking in the specified slot index. ++ * ++ * @param index item slot index ++ * @return whether the slot couldn't cook before this call ++ */ ++ boolean startCooking(int index); ++ ++ /** ++ * State of slot index. ++ * ++ * @param index item slot index ++ * @return {@code true} if the specified slot index cannot cook ++ */ ++ boolean isCookingDisabled(int index); ++ // Paper end + } diff --git a/patches/api/0315-Extend-VehicleCollisionEvent-move-HandlerList-up.patch b/patches/api/0315-Extend-VehicleCollisionEvent-move-HandlerList-up.patch new file mode 100644 index 000000000000..5f5a4f414001 --- /dev/null +++ b/patches/api/0315-Extend-VehicleCollisionEvent-move-HandlerList-up.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 13 Dec 2021 14:35:27 -0800 +Subject: [PATCH] Extend VehicleCollisionEvent, move HandlerList up + +Co-authored-by: SoSeDiK + +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java +index 316f625aa595d2ada16529b16d09f013fc4daeac..d0a437bd8aeec18f800893f51ece06deb0c8972c 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java +@@ -9,13 +9,31 @@ import org.jetbrains.annotations.NotNull; + * Raised when a vehicle collides with a block. + */ + public class VehicleBlockCollisionEvent extends VehicleCollisionEvent { +- private static final HandlerList handlers = new HandlerList(); + private final Block block; ++ private final org.bukkit.util.Vector velocity; // Paper + ++ // Paper start - Add pre-collision velocity ++ @Deprecated + public VehicleBlockCollisionEvent(@NotNull final Vehicle vehicle, @NotNull final Block block) { ++ this(vehicle, block, vehicle.getVelocity()); ++ } ++ ++ public VehicleBlockCollisionEvent(@NotNull final Vehicle vehicle, @NotNull final Block block, @NotNull final org.bukkit.util.Vector velocity) { // Paper - Added velocity + super(vehicle); + this.block = block; ++ this.velocity = velocity; ++ } ++ ++ /** ++ * Gets velocity at which the vehicle collided with the block ++ * ++ * @return pre-collision moving velocity ++ */ ++ @NotNull ++ public org.bukkit.util.Vector getVelocity() { ++ return velocity; + } ++ // Paper end + + /** + * Gets the block the vehicle collided with +@@ -26,15 +44,4 @@ public class VehicleBlockCollisionEvent extends VehicleCollisionEvent { + public Block getBlock() { + return block; + } +- +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } + } +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleCollisionEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleCollisionEvent.java +index 9d493c155ad5c26430c1e404fcf0db5f734679e4..aa1d74eade479195bde8095aafcc91a83635102d 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleCollisionEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleCollisionEvent.java +@@ -7,7 +7,18 @@ import org.jetbrains.annotations.NotNull; + * Raised when a vehicle collides. + */ + public abstract class VehicleCollisionEvent extends VehicleEvent { ++ private static final org.bukkit.event.HandlerList HANDLER_LIST = new org.bukkit.event.HandlerList(); // Paper + public VehicleCollisionEvent(@NotNull final Vehicle vehicle) { + super(vehicle); + } ++ // Paper start ++ @Override ++ public org.bukkit.event.@org.jetbrains.annotations.NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static org.bukkit.event.@NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleEntityCollisionEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleEntityCollisionEvent.java +index 50c762d777ac90a05772501a28cacff8fd3f5126..77fb04bdf5b1a6d94693a7374a750e020131dc3d 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleEntityCollisionEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleEntityCollisionEvent.java +@@ -10,7 +10,6 @@ import org.jetbrains.annotations.NotNull; + * Raised when a vehicle collides with an entity. + */ + public class VehicleEntityCollisionEvent extends VehicleCollisionEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); + private final Entity entity; + private boolean cancelled = false; + private boolean cancelledPickup = false; +@@ -55,15 +54,4 @@ public class VehicleEntityCollisionEvent extends VehicleCollisionEvent implement + public void setCollisionCancelled(boolean cancel) { + cancelledCollision = cancel; + } +- +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } + } diff --git a/patches/api/0316-Improve-scoreboard-entries.patch b/patches/api/0316-Improve-scoreboard-entries.patch new file mode 100644 index 000000000000..26f03310e988 --- /dev/null +++ b/patches/api/0316-Improve-scoreboard-entries.patch @@ -0,0 +1,191 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 4 Nov 2021 12:31:45 -0700 +Subject: [PATCH] Improve scoreboard entries + + +diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java +index 35755c9165c1b48eaacfff86a50a7973476fe04b..d6d52bc9185e8a1581ccfa57df3550bc12d9872a 100644 +--- a/src/main/java/org/bukkit/scoreboard/Objective.java ++++ b/src/main/java/org/bukkit/scoreboard/Objective.java +@@ -148,9 +148,8 @@ public interface Objective { + * @return Score tracking the Objective and player specified + * @throws IllegalStateException if this objective has been unregistered + * @see #getScore(String) +- * @deprecated Scoreboards can contain entries that aren't players + */ +- @Deprecated(since = "1.7.8") ++ // @Deprecated(since = "1.7.8") // Paper + @NotNull + Score getScore(@NotNull OfflinePlayer player); + +@@ -164,4 +163,16 @@ public interface Objective { + */ + @NotNull + Score getScore(@NotNull String entry); ++ ++ // Paper start - improve scoreboard entries ++ /** ++ * Gets an entity's Score for an Objective on this Scoreboard. ++ * ++ * @param entity Entity for the Score ++ * @return Score tracking the Objective and entity specified ++ * @throws IllegalArgumentException if entity is null ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ @NotNull Score getScoreFor(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException, IllegalStateException; ++ // Paper end - improve scoreboard entries + } +diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +index 1cba9a96cc7efce2a4394add33e4c0369f94be31..81ca0c62ce32204681fcb8fd751d12b4fb0aeb97 100644 +--- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java ++++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java +@@ -215,9 +215,8 @@ public interface Scoreboard { + * @param player the player whose scores are being retrieved + * @return immutable set of all scores tracked for the player + * @see #getScores(String) +- * @deprecated Scoreboards can contain entries that aren't players + */ +- @Deprecated(since = "1.7.8") ++ // @Deprecated(since = "1.7.8") // Paper + @NotNull + Set getScores(@NotNull OfflinePlayer player); + +@@ -235,9 +234,8 @@ public interface Scoreboard { + * + * @param player the player to drop all current scores for + * @see #resetScores(String) +- * @deprecated Scoreboards can contain entries that aren't players + */ +- @Deprecated(since = "1.7.8") ++ // @Deprecated(since = "1.7.8") // Paper + void resetScores(@NotNull OfflinePlayer player); + + /** +@@ -253,9 +251,8 @@ public interface Scoreboard { + * @param player the player to search for + * @return the player's Team or null if the player is not on a team + * @see #getEntryTeam(String) +- * @deprecated Scoreboards can contain entries that aren't players + */ +- @Deprecated(since = "1.8.6") ++ // @Deprecated(since = "1.8.6") // Paper + @Nullable + Team getPlayerTeam(@NotNull OfflinePlayer player); + +@@ -320,4 +317,35 @@ public interface Scoreboard { + * @param slot the slot to remove objectives + */ + void clearSlot(@NotNull DisplaySlot slot); ++ ++ // Paper start - improve scoreboard entries ++ /** ++ * Gets all scores for an entity on this Scoreboard ++ * ++ * @param entity the entity whose scores are being retrieved ++ * @return immutable set of all scores tracked for the entity ++ * @throws IllegalArgumentException if entity is null ++ * @see #getScores(String) ++ */ ++ @NotNull Set getScoresFor(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException; ++ ++ /** ++ * Removes all scores for an entity on this Scoreboard ++ * ++ * @param entity the entity to drop all current scores for ++ * @throws IllegalArgumentException if entity is null ++ * @see #resetScores(String) ++ */ ++ void resetScoresFor(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException; ++ ++ /** ++ * Gets an entity's Team on this Scoreboard ++ * ++ * @param entity the entity to search for ++ * @return the entity's Team or null if the entity is not on a team ++ * @throws IllegalArgumentException if entity is null ++ * @see #getEntryTeam(String) ++ */ ++ @Nullable Team getEntityTeam(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException; ++ // Paper end - improve scoreboard entries + } +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index 38deee00cfe2f6803070e98cd9ded95d859bf8e1..c500de6ed19bdf732f7bedbedb19a4b37ca343f8 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -295,9 +295,8 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + * @param player the player to add + * @throws IllegalStateException if this team has been unregistered + * @see #addEntry(String) +- * @deprecated Teams can contain entries that aren't players + */ +- @Deprecated(since = "1.8.6") ++ // @Deprecated(since = "1.8.6") // Paper + void addPlayer(@NotNull OfflinePlayer player); + + /** +@@ -317,9 +316,8 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + * @return if the player was on this team + * @throws IllegalStateException if this team has been unregistered + * @see #removeEntry(String) +- * @deprecated Teams can contain entries that aren't players + */ +- @Deprecated(since = "1.8.6") ++ // @Deprecated(since = "1.8.6") // Paper + boolean removePlayer(@NotNull OfflinePlayer player); + + /** +@@ -345,9 +343,8 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + * @return true if the player is a member of this team + * @throws IllegalStateException if this team has been unregistered + * @see #hasEntry(String) +- * @deprecated Teams can contain entries that aren't players + */ +- @Deprecated(since = "1.8.6") ++ // @Deprecated(since = "1.8.6") // Paper + boolean hasPlayer(@NotNull OfflinePlayer player); + /** + * Checks to see if the specified entry is a member of this team. +@@ -377,6 +374,42 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + */ + void setOption(@NotNull Option option, @NotNull OptionStatus status); + ++ // Paper start - improve scoreboard entries ++ /** ++ * This puts the specified entity onto this team for the scoreboard. ++ *

      ++ * This will remove the entity from any other team on the scoreboard. ++ * ++ * @param entity the entity to add ++ * @throws IllegalArgumentException if entity is null ++ * @throws IllegalStateException if this team has been unregistered ++ * @see #addEntry(String) ++ */ ++ void addEntity(@NotNull org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Removes the entity from this team. ++ * ++ * @param entity the entity to remove ++ * @return if the entity was on this team ++ * @throws IllegalArgumentException if entity is null ++ * @throws IllegalStateException if this team has been unregistered ++ * @see #removeEntry(String) ++ */ ++ boolean removeEntity(@NotNull org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Checks to see if the specified entity is a member of this team. ++ * ++ * @param entity the entity to search for ++ * @return true if the entity is a member of this team ++ * @throws IllegalArgumentException if entity is null ++ * @throws IllegalStateException if this team has been unregistered ++ * @see #hasEntry(String) ++ */ ++ boolean hasEntity(@NotNull org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException; ++ // Paper end - improve scoreboard entries ++ + /** + * Represents an option which may be applied to this team. + */ diff --git a/patches/api/0317-Entity-powdered-snow-API.patch b/patches/api/0317-Entity-powdered-snow-API.patch new file mode 100644 index 000000000000..ca7af1d0e573 --- /dev/null +++ b/patches/api/0317-Entity-powdered-snow-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 24 Oct 2021 20:58:52 -0700 +Subject: [PATCH] Entity powdered snow API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 464668496f5a611ae78bd5f6392915ec384862ac..97b8ac9ae8ebe0f074f5f1f806d9415b8122400c 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -973,5 +973,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * @return Whether the entity was successfully spawned. + */ + public boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason); ++ ++ /** ++ * Check if entity is inside powdered snow. ++ * ++ * @return true if in powdered snow. ++ */ ++ boolean isInPowderedSnow(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/bukkit/entity/Skeleton.java +index 0944d920301d8cd5ec3960454129f7d1c15ee6d4..ce04c03ba5f67e02faf10ed8aaef4d51fbf2b190 100644 +--- a/src/main/java/org/bukkit/entity/Skeleton.java ++++ b/src/main/java/org/bukkit/entity/Skeleton.java +@@ -41,6 +41,16 @@ public interface Skeleton extends AbstractSkeleton { + */ + void setConversionTime(int time); + ++ // Paper start ++ /** ++ * Gets the time the skeleton ++ * has been inside powdered snow. ++ * ++ * @return time in ticks ++ */ ++ int inPowderedSnowTime(); ++ // Paper end ++ + /** + * A legacy enum that defines the different variances of skeleton-like + * entities on the server. diff --git a/patches/api/0318-Add-API-for-item-entity-health.patch b/patches/api/0318-Add-API-for-item-entity-health.patch new file mode 100644 index 000000000000..572034e55714 --- /dev/null +++ b/patches/api/0318-Add-API-for-item-entity-health.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 28 Aug 2021 09:00:35 -0700 +Subject: [PATCH] Add API for item entity health + + +diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java +index 6239aec4f6c625a814fa4fd610cdc5ab1a9f6e0f..ced419f8655bff72f0257b639d5f7d73afe3c2e2 100644 +--- a/src/main/java/org/bukkit/entity/Item.java ++++ b/src/main/java/org/bukkit/entity/Item.java +@@ -133,5 +133,24 @@ public interface Item extends Entity { + * @param willAge True if the item should age + */ + public void setWillAge(boolean willAge); ++ ++ /** ++ * Gets the health of item stack. ++ *

      ++ * Currently the default max health is 5. ++ * ++ * @return the health ++ */ ++ public int getHealth(); ++ ++ /** ++ * Sets the health of the item stack. If the value is non-positive ++ * the itemstack's normal "on destroy" functionality will be run. ++ *

      ++ * Currently, the default max health is 5. ++ * ++ * @param health the health, a non-positive value will destroy the entity ++ */ ++ public void setHealth(int health); + // Paper end + } diff --git a/patches/api/0319-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch b/patches/api/0319-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch new file mode 100644 index 000000000000..f094cdc2551e --- /dev/null +++ b/patches/api/0319-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Thu, 23 Dec 2021 15:32:40 -0600 +Subject: [PATCH] Expose isFuel and canSmelt methods to FurnaceInventory + + +diff --git a/src/main/java/org/bukkit/inventory/FurnaceInventory.java b/src/main/java/org/bukkit/inventory/FurnaceInventory.java +index 3f46259c1e0f82941ffc3038d1b51be199114abd..b9d4f05980d924a4831b1d213d4963199f5b9a5d 100644 +--- a/src/main/java/org/bukkit/inventory/FurnaceInventory.java ++++ b/src/main/java/org/bukkit/inventory/FurnaceInventory.java +@@ -53,6 +53,24 @@ public interface FurnaceInventory extends Inventory { + */ + void setSmelting(@Nullable ItemStack stack); + ++ // Paper start ++ /** ++ * Check if an item can be used as a fuel source in this furnace container ++ * ++ * @param item Item to check ++ * @return True if a valid fuel source ++ */ ++ public boolean isFuel(@Nullable ItemStack item); ++ ++ /** ++ * Check if an item can be smelted in this furnace container ++ * ++ * @param item Item to check ++ * @return True if can be smelt ++ */ ++ public boolean canSmelt(@Nullable ItemStack item); ++ // Paper end ++ + @Override + @Nullable + Furnace getHolder(); diff --git a/patches/api/0320-Bucketable-API.patch b/patches/api/0320-Bucketable-API.patch new file mode 100644 index 000000000000..b954c4c6983a --- /dev/null +++ b/patches/api/0320-Bucketable-API.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 26 Dec 2021 14:03:11 -0500 +Subject: [PATCH] Bucketable API + + +diff --git a/src/main/java/io/papermc/paper/entity/Bucketable.java b/src/main/java/io/papermc/paper/entity/Bucketable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a63c3d0fe50f5808215ed169b81269112f76ec1b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/Bucketable.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.entity; ++ ++import org.bukkit.Sound; ++import org.bukkit.entity.Entity; ++import org.bukkit.inventory.ItemStack; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents an entity that can be bucketed. ++ */ ++@NullMarked ++public interface Bucketable extends Entity { ++ ++ /** ++ * Gets if this entity originated from a bucket. ++ * ++ * @return originated from bucket ++ */ ++ boolean isFromBucket(); ++ ++ /** ++ * Sets if this entity originated from a bucket. ++ * ++ * @param fromBucket is from a bucket ++ */ ++ void setFromBucket(boolean fromBucket); ++ ++ /** ++ * Gets the base itemstack of this entity in a bucket form. ++ * ++ * @return bucket form ++ */ ++ ItemStack getBaseBucketItem(); ++ ++ /** ++ * Gets the sound that is played when this entity ++ * is picked up in a bucket. ++ * @return bucket pickup sound ++ */ ++ Sound getPickupSound(); ++} +diff --git a/src/main/java/org/bukkit/entity/Axolotl.java b/src/main/java/org/bukkit/entity/Axolotl.java +index 9763f3b9ac8f32c082a476f4b50a32622b2720a0..c8c738b1b72e9ad89d97b7a1f5450d58045a72ca 100644 +--- a/src/main/java/org/bukkit/entity/Axolotl.java ++++ b/src/main/java/org/bukkit/entity/Axolotl.java +@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; + /** + * An Axolotl. + */ +-public interface Axolotl extends Animals { ++public interface Axolotl extends Animals, io.papermc.paper.entity.Bucketable { // Paper - Bucketable API + + /** + * Gets if this axolotl is playing dead. +diff --git a/src/main/java/org/bukkit/entity/Fish.java b/src/main/java/org/bukkit/entity/Fish.java +index 82e390b2152e7c881006ca30f2527d160c01f8a1..86da8dc401ed7db19a39bc682721055cd341ccde 100644 +--- a/src/main/java/org/bukkit/entity/Fish.java ++++ b/src/main/java/org/bukkit/entity/Fish.java +@@ -3,4 +3,4 @@ package org.bukkit.entity; + /** + * Represents a fish entity. + */ +-public interface Fish extends WaterMob { } ++public interface Fish extends WaterMob, io.papermc.paper.entity.Bucketable { } // Paper - Bucketable API diff --git a/patches/api/0321-System-prop-for-default-config-comment-parsing.patch b/patches/api/0321-System-prop-for-default-config-comment-parsing.patch new file mode 100644 index 000000000000..9b8176aef854 --- /dev/null +++ b/patches/api/0321-System-prop-for-default-config-comment-parsing.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 30 Dec 2021 16:35:56 -0800 +Subject: [PATCH] System prop for default config comment parsing + +Allows for certain legacy plugins to continue to work without changing +by setting `Paper.parseYamlCommentsByDefault` to false + +diff --git a/src/main/java/org/bukkit/configuration/file/FileConfigurationOptions.java b/src/main/java/org/bukkit/configuration/file/FileConfigurationOptions.java +index 4bff5d18d9ae62c6c55869c66efc2bc481a0cc18..800a34710c2b85dc2a58f2e15ba910c7ee717c08 100644 +--- a/src/main/java/org/bukkit/configuration/file/FileConfigurationOptions.java ++++ b/src/main/java/org/bukkit/configuration/file/FileConfigurationOptions.java +@@ -15,7 +15,10 @@ import org.jetbrains.annotations.Nullable; + public class FileConfigurationOptions extends MemoryConfigurationOptions { + private List header = Collections.emptyList(); + private List footer = Collections.emptyList(); +- private boolean parseComments = true; ++ // Paper start - add system prop for comment parsing ++ private static final boolean PAPER_PARSE_COMMENTS_BY_DEFAULT = Boolean.parseBoolean(System.getProperty("Paper.parseYamlCommentsByDefault", "true")); ++ private boolean parseComments = PAPER_PARSE_COMMENTS_BY_DEFAULT; ++ // Paper end + + protected FileConfigurationOptions(@NotNull MemoryConfiguration configuration) { + super(configuration); diff --git a/patches/api/0322-Expose-vanilla-BiomeProvider-from-WorldInfo.patch b/patches/api/0322-Expose-vanilla-BiomeProvider-from-WorldInfo.patch new file mode 100644 index 000000000000..9b189fc91849 --- /dev/null +++ b/patches/api/0322-Expose-vanilla-BiomeProvider-from-WorldInfo.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Thu, 6 Jan 2022 15:56:16 -0800 +Subject: [PATCH] Expose vanilla BiomeProvider from WorldInfo + + +diff --git a/src/main/java/org/bukkit/generator/WorldInfo.java b/src/main/java/org/bukkit/generator/WorldInfo.java +index 5bf00f46e8f3a80fec2a8a738e4d0d92461cfc92..5067f1371433cccd3287af7f03e152f2c3c1ece3 100644 +--- a/src/main/java/org/bukkit/generator/WorldInfo.java ++++ b/src/main/java/org/bukkit/generator/WorldInfo.java +@@ -57,4 +57,13 @@ public interface WorldInfo { + * @return Maximum height of the world + */ + int getMaxHeight(); ++ ++ // Paper start ++ /** ++ * Get the vanilla {@link BiomeProvider} for this world. ++ * ++ * @return vanilla biome provider ++ */ ++ @NotNull BiomeProvider vanillaBiomeProvider(); ++ // Paper end + } diff --git a/patches/api/0323-Multiple-Entries-with-Scoreboards.patch b/patches/api/0323-Multiple-Entries-with-Scoreboards.patch new file mode 100644 index 000000000000..a1e9b23e68e2 --- /dev/null +++ b/patches/api/0323-Multiple-Entries-with-Scoreboards.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Tue, 21 Sep 2021 18:17:34 -0500 +Subject: [PATCH] Multiple Entries with Scoreboards + + +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index c500de6ed19bdf732f7bedbedb19a4b37ca343f8..c34d9ab72928d5f58339025d717ec840a4d8cf2c 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -309,6 +309,60 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + */ + void addEntry(@NotNull String entry); + ++ // Paper start ++ /** ++ * This puts a collection of entities onto this team for the scoreboard which results in one ++ * packet for the updates rather than a packet-per-entity. ++ *

      ++ * Entities on other teams will be removed from their respective teams. ++ * ++ * @param entities the entities to add ++ * @throws IllegalArgumentException if entities are null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ default void addEntities(@NotNull org.bukkit.entity.Entity @NotNull ...entities) { ++ this.addEntities(java.util.List.of(entities)); ++ } ++ ++ /** ++ * This puts a collection of entities onto this team for the scoreboard which results in one ++ * packet for the updates rather than a packet-per-entity. ++ *

      ++ * Entities on other teams will be removed from their respective teams. ++ * ++ * @param entities the entities to add ++ * @throws IllegalArgumentException if entities are null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void addEntities(@NotNull java.util.Collection entities) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * This puts a collection of entries onto this team for the scoreboard which results in one ++ * packet for the updates rather than a packet-per-entry. ++ *

      ++ * Entries on other teams will be removed from their respective teams. ++ * ++ * @param entries the entries to add ++ * @throws IllegalArgumentException if entries are null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ default void addEntries(@NotNull String... entries) throws IllegalStateException, IllegalArgumentException { ++ this.addEntries(java.util.List.of(entries)); ++ } ++ ++ /** ++ * This puts a collection of entries onto this team for the scoreboard which results in one ++ * packet for the updates rather than a packet-per-entry. ++ *

      ++ * Entries on other teams will be removed from their respective teams. ++ * ++ * @param entries the entries to add ++ * @throws IllegalArgumentException if entries are null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void addEntries(@NotNull java.util.Collection entries) throws IllegalStateException, IllegalArgumentException; ++ // Paper end ++ + /** + * Removes the player from this team. + * +@@ -329,6 +383,56 @@ public interface Team extends net.kyori.adventure.audience.ForwardingAudience { + */ + boolean removeEntry(@NotNull String entry); + ++ // Paper start ++ /** ++ * Removes a collection of entities from this team which results in one ++ * packet for the updates rather than a packet-per-entity. ++ * ++ * @param entities the entries to remove ++ * @return if any of the entities were a part of this team ++ * @throws IllegalArgumentException if entities is null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ default boolean removeEntities(@NotNull org.bukkit.entity.Entity @NotNull ... entities) throws IllegalStateException, IllegalArgumentException { ++ return this.removeEntities(java.util.List.of(entities)); ++ } ++ ++ /** ++ * Removes a collection of entities from this team which results in one ++ * packet for the updates rather than a packet-per-entity. ++ * ++ * @param entities the entries to remove ++ * @return if any of the entities were a part of this team ++ * @throws IllegalArgumentException if entities is null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ boolean removeEntities(@NotNull java.util.Collection entities) throws IllegalStateException, IllegalArgumentException; ++ ++ /** ++ * Removes a collection of entries from this team which results in one ++ * packet for the updates rather than a packet-per-entry. ++ * ++ * @param entries the entries to remove ++ * @return if any of the entries were a part of this team ++ * @throws IllegalArgumentException if entries is null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ default boolean removeEntries(@NotNull String... entries) throws IllegalStateException, IllegalArgumentException { ++ return this.removeEntries(java.util.List.of(entries)); ++ } ++ ++ /** ++ * Removes a collection of entries from this team which results in one ++ * packet for the updates rather than a packet-per-entry. ++ * ++ * @param entries the entries to remove ++ * @return if any of the entries were a part of this team ++ * @throws IllegalArgumentException if entries is null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ boolean removeEntries(@NotNull java.util.Collection entries) throws IllegalStateException, IllegalArgumentException; ++ // Paper end ++ + /** + * Unregisters this team from the Scoreboard + * diff --git a/patches/api/0324-Warn-on-strange-EventHandler-return-types.patch b/patches/api/0324-Warn-on-strange-EventHandler-return-types.patch new file mode 100644 index 000000000000..c7807b823b91 --- /dev/null +++ b/patches/api/0324-Warn-on-strange-EventHandler-return-types.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Tue, 18 Jan 2022 11:07:54 -0700 +Subject: [PATCH] Warn on strange @EventHandler return types + + +diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java +index 9026e108ccd3a88aee1267ee275137befa646455..5fa52419f21d8e8b3d8f9aafd248b05774a28348 100644 +--- a/src/main/java/org/bukkit/plugin/EventExecutor.java ++++ b/src/main/java/org/bukkit/plugin/EventExecutor.java +@@ -51,6 +51,12 @@ public interface EventExecutor { + Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); + Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); + ClassDefiner definer = ClassDefiner.getInstance(); ++ if (m.getReturnType() != Void.TYPE) { ++ final org.bukkit.plugin.java.JavaPlugin plugin = org.bukkit.plugin.java.JavaPlugin.getProvidingPlugin(m.getDeclaringClass()); ++ org.bukkit.Bukkit.getLogger().warning("@EventHandler method " + m.getDeclaringClass().getName() + (Modifier.isStatic(m.getModifiers()) ? '.' : '#') + m.getName() ++ + " returns non-void type " + m.getReturnType().getName() + ". This is unsupported behavior and will no longer work in a future version of Paper." ++ + " This should be reported to the developers of " + plugin.getPluginMeta().getDisplayName() + " (" + String.join(",", plugin.getPluginMeta().getAuthors()) + ')'); ++ } + if (Modifier.isStatic(m.getModifiers())) { + return new StaticMethodHandleEventExecutor(eventClass, m); + } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { diff --git a/patches/api/0325-Multi-Block-Change-API.patch b/patches/api/0325-Multi-Block-Change-API.patch new file mode 100644 index 000000000000..5b0180c266bf --- /dev/null +++ b/patches/api/0325-Multi-Block-Change-API.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brody Beckwith +Date: Fri, 14 Jan 2022 00:40:42 -0500 +Subject: [PATCH] Multi Block Change API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 68c470b9504a8b731606a1d297de223235b55cb9..db3a1e9170aeada5fe738975124861d79e82e2d1 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -977,6 +977,29 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendBlockDamage(@NotNull Location loc, float progress); + ++ // Paper start ++ /** ++ * Send multiple block changes. This fakes a multi block change packet for each ++ * chunk section that a block change occurs. This will not actually change the world in any way. ++ * ++ * @param blockChanges A map of the positions you want to change to their new block data ++ */ ++ void sendMultiBlockChange(@NotNull Map blockChanges); ++ ++ /** ++ * Send multiple block changes. This fakes a multi block change packet for each ++ * chunk section that a block change occurs. This will not actually change the world in any way. ++ * ++ * @param blockChanges A map of the positions you want to change to their new block data ++ * @param suppressLightUpdates Whether to suppress light updates or not ++ * @deprecated suppressLightUpdates is no longer available in 1.20+, use {@link #sendMultiBlockChange(Map)} ++ */ ++ @Deprecated ++ default void sendMultiBlockChange(@NotNull Map blockChanges, boolean suppressLightUpdates) { ++ this.sendMultiBlockChange(blockChanges); ++ } ++ // Paper end ++ + /** + * Send block damage. This fakes block break progress at a certain location + * sourced by the provided entity. This will not actually change the block's diff --git a/patches/api/0326-Fix-NotePlayEvent.patch b/patches/api/0326-Fix-NotePlayEvent.patch new file mode 100644 index 000000000000..0159992c04af --- /dev/null +++ b/patches/api/0326-Fix-NotePlayEvent.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kieran Wallbanks +Date: Mon, 21 Jun 2021 12:33:45 +0100 +Subject: [PATCH] Fix NotePlayEvent + + +diff --git a/src/main/java/org/bukkit/event/block/NotePlayEvent.java b/src/main/java/org/bukkit/event/block/NotePlayEvent.java +index c9ecbebbc27f27734d35f496783706f702dccb29..ea7cb75ba3ecbe40e0390fd5568db77de56c4f16 100644 +--- a/src/main/java/org/bukkit/event/block/NotePlayEvent.java ++++ b/src/main/java/org/bukkit/event/block/NotePlayEvent.java +@@ -56,11 +56,13 @@ public class NotePlayEvent extends BlockEvent implements Cancellable { + + /** + * Overrides the {@link Instrument} to be used. ++ *

      ++ * Only works when the note block isn't under a player head. ++ * For this specific case the 'note_block_sound' property of the ++ * player head state takes the priority. + * + * @param instrument the Instrument. Has no effect if null. +- * @deprecated no effect on newer Minecraft versions + */ +- @Deprecated(since = "1.13") + public void setInstrument(@NotNull Instrument instrument) { + if (instrument != null) { + this.instrument = instrument; +@@ -71,9 +73,7 @@ public class NotePlayEvent extends BlockEvent implements Cancellable { + * Overrides the {@link Note} to be played. + * + * @param note the Note. Has no effect if null. +- * @deprecated no effect on newer Minecraft versions + */ +- @Deprecated(since = "1.13") + public void setNote(@NotNull Note note) { + if (note != null) { + this.note = note; diff --git a/patches/api/0327-Freeze-Tick-Lock-API.patch b/patches/api/0327-Freeze-Tick-Lock-API.patch new file mode 100644 index 000000000000..7e573b5966b2 --- /dev/null +++ b/patches/api/0327-Freeze-Tick-Lock-API.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 26 Dec 2021 20:27:49 -0500 +Subject: [PATCH] Freeze Tick Lock API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 97b8ac9ae8ebe0f074f5f1f806d9415b8122400c..fe3f59390ee45a289ae6dbb398ce7954fab717d5 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -327,6 +327,26 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + boolean hasNoPhysics(); + // Paper end - missing entity api + ++ // Paper start - Freeze Tick Lock API ++ /** ++ * Gets if the entity currently has its freeze ticks locked ++ * to a set amount. ++ *

      ++ * This is only set by plugins ++ * ++ * @return locked or not ++ */ ++ boolean isFreezeTickingLocked(); ++ ++ /** ++ * Sets if the entity currently has its freeze ticks locked, ++ * preventing default vanilla freeze tick modification. ++ * ++ * @param locked prevent vanilla modification or not ++ */ ++ void lockFreezeTicks(boolean locked); ++ // Paper end - Freeze Tick Lock API ++ + /** + * Mark the entity's removal. + * diff --git a/patches/api/0328-Dolphin-API.patch b/patches/api/0328-Dolphin-API.patch new file mode 100644 index 000000000000..8c3706b8706c --- /dev/null +++ b/patches/api/0328-Dolphin-API.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Tue, 7 Dec 2021 19:34:11 -0500 +Subject: [PATCH] Dolphin API + + +diff --git a/src/main/java/org/bukkit/entity/Dolphin.java b/src/main/java/org/bukkit/entity/Dolphin.java +index fcf09afd38277180aa299703000e46dd2482c372..d3d3f8b20769eec65a81d9a59195625cb2be8579 100644 +--- a/src/main/java/org/bukkit/entity/Dolphin.java ++++ b/src/main/java/org/bukkit/entity/Dolphin.java +@@ -1,3 +1,52 @@ + package org.bukkit.entity; + +-public interface Dolphin extends Ageable, WaterMob { } ++import org.bukkit.Location; ++ ++public interface Dolphin extends Ageable, WaterMob { // Paper start - Dolphin API ++ ++ /** ++ * Gets the moistness level of this dolphin ++ */ ++ int getMoistness(); ++ ++ /** ++ * Sets the moistness of this dolphin, once this is less than 0 the dolphin will start to take damage. ++ * ++ * @param moistness moistness level ++ */ ++ void setMoistness(int moistness); ++ ++ /** ++ * Sets if this dolphin was fed a fish. ++ * ++ * @param hasFish has a fish ++ */ ++ void setHasFish(boolean hasFish); ++ ++ /** ++ * Gets if this dolphin has a fish. ++ * ++ * @return has a fish ++ */ ++ boolean hasFish(); ++ ++ /** ++ * Gets the treasure location this dolphin tries to guide players to. ++ *

      ++ * This value is calculated if the player has fed the dolphin a fish, and it tries to start the {@link com.destroystokyo.paper.entity.ai.VanillaGoal#DOLPHIN_SWIM_TO_TREASURE} goal. ++ * ++ * @return calculated closest treasure location ++ */ ++ @org.jetbrains.annotations.NotNull ++ Location getTreasureLocation(); ++ ++ /** ++ * Sets the treasure location that this dolphin will try to lead the player to. ++ * This only has an effect if the dolphin is currently leading a player, as this value is recalculated next time it leads a player. ++ *

      ++ * The world of the location does not matter, as the dolphin will always use the world it is currently in. ++ * ++ * @param location location to guide to ++ */ ++ void setTreasureLocation(@org.jetbrains.annotations.NotNull Location location); ++} // Paper end - Dolphin API diff --git a/patches/api/0329-More-PotionEffectType-API.patch b/patches/api/0329-More-PotionEffectType-API.patch new file mode 100644 index 000000000000..736dc6f9a86c --- /dev/null +++ b/patches/api/0329-More-PotionEffectType-API.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 27 May 2021 21:58:33 -0700 +Subject: [PATCH] More PotionEffectType API + + +diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java +index d03bdf6617ce66950e335f0afb52c19b2e2a14e2..b2bd12736d08fe72128142af4ca2022da8309f6d 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -367,6 +367,15 @@ public interface Registry extends Iterable { + * @see GameEvent + */ + Registry GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper ++ ++ // Paper start - potion effect type registry ++ /** ++ * Potion effect types. ++ * ++ * @see org.bukkit.potion.PotionEffectType ++ */ ++ Registry POTION_EFFECT_TYPE = EFFECT; ++ // Paper end - potion effect type registry + /** + * Get the object by its key. + * +diff --git a/src/main/java/org/bukkit/potion/PotionEffectType.java b/src/main/java/org/bukkit/potion/PotionEffectType.java +index 6375eed0ef4f8e897a00b4f77fb45b354888e74e..5f32728fad44c3c5f3f5382b0ad6fd9b1ef5e0fd 100644 +--- a/src/main/java/org/bukkit/potion/PotionEffectType.java ++++ b/src/main/java/org/bukkit/potion/PotionEffectType.java +@@ -17,7 +17,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a type of potion and its effect on an entity. + */ +-public abstract class PotionEffectType implements Keyed, Translatable { ++public abstract class PotionEffectType implements Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - implement Translatable + private static final BiMap ID_MAP = HashBiMap.create(); + + /** +@@ -360,4 +360,57 @@ public abstract class PotionEffectType implements Keyed, Translatable { + public static PotionEffectType[] values() { + return Lists.newArrayList(Registry.EFFECT).toArray(new PotionEffectType[0]); + } ++ ++ // Paper start ++ /** ++ * Gets the effect attributes in an immutable map. ++ * ++ * @return the attribute map ++ */ ++ public abstract @NotNull java.util.Map getEffectAttributes(); ++ ++ /** ++ * Gets the true modifier amount based on the effect amplifier. ++ * ++ * @param attribute the attribute ++ * @param effectAmplifier the effect amplifier (0 indexed) ++ * @return the modifier amount ++ * @throws IllegalArgumentException if the supplied attribute is not present in the map from {@link #getEffectAttributes()} ++ */ ++ public abstract double getAttributeModifierAmount(@NotNull org.bukkit.attribute.Attribute attribute, int effectAmplifier); ++ ++ /** ++ * Gets the category of this effect ++ * ++ * @return the category ++ */ ++ public abstract @NotNull PotionEffectType.Category getEffectCategory(); ++ ++ /** ++ * Category of {@link PotionEffectType}s ++ */ ++ public enum Category { ++ ++ BENEFICIAL(net.kyori.adventure.text.format.NamedTextColor.BLUE), ++ HARMFUL(net.kyori.adventure.text.format.NamedTextColor.RED), ++ NEUTRAL(net.kyori.adventure.text.format.NamedTextColor.BLUE); ++ ++ private final net.kyori.adventure.text.format.TextColor color; ++ ++ Category(net.kyori.adventure.text.format.TextColor color) { ++ this.color = color; ++ } ++ ++ /** ++ * Gets the text color used when displaying potions ++ * of this category. ++ * ++ * @return the text color ++ */ ++ @NotNull ++ public net.kyori.adventure.text.format.TextColor getColor() { ++ return color; ++ } ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/potion/PotionEffectTypeWrapper.java b/src/main/java/org/bukkit/potion/PotionEffectTypeWrapper.java +index 6861d1cfcedb6d72c2c425bad205342aac8e33a1..7acdeb9054e128c452ea8610d8b39a35627c56bf 100644 +--- a/src/main/java/org/bukkit/potion/PotionEffectTypeWrapper.java ++++ b/src/main/java/org/bukkit/potion/PotionEffectTypeWrapper.java +@@ -19,4 +19,41 @@ public abstract class PotionEffectTypeWrapper extends PotionEffectType { + public PotionEffectType getType() { + return this; + } ++ ++ @Override ++ public boolean isInstant() { ++ return getType().isInstant(); ++ } ++ ++ @NotNull ++ @Override ++ public org.bukkit.Color getColor() { ++ return getType().getColor(); ++ } ++ // Paper start ++ @Override ++ public @NotNull org.bukkit.NamespacedKey getKey() { ++ return this.getType().getKey(); ++ } ++ ++ @Override ++ public @NotNull java.util.Map getEffectAttributes() { ++ return this.getType().getEffectAttributes(); ++ } ++ ++ @Override ++ public double getAttributeModifierAmount(@NotNull org.bukkit.attribute.Attribute attribute, int effectAmplifier) { ++ return this.getType().getAttributeModifierAmount(attribute, effectAmplifier); ++ } ++ ++ @Override ++ public @NotNull PotionEffectType.Category getEffectCategory() { ++ return this.getType().getEffectCategory(); ++ } ++ ++ @Override ++ public @NotNull String translationKey() { ++ return this.getType().translationKey(); ++ } ++ // Paper end + } diff --git a/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch b/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch new file mode 100644 index 000000000000..5c606e2d0b44 --- /dev/null +++ b/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Tue, 1 Feb 2022 15:51:44 -0700 +Subject: [PATCH] API for creating command sender which forwards feedback + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 46b678da746fb8ff65e77811499ee341093a65e8..a9d1a9a5223148ea134ed146d059ec9edb922f03 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1595,6 +1595,20 @@ public final class Bukkit { + return server.getConsoleSender(); + } + ++ // Paper start ++ /** ++ * Creates a special {@link CommandSender} which redirects command feedback (in the form of chat messages) to the ++ * specified listener. The returned sender will have the same effective permissions as {@link #getConsoleSender()}. ++ * ++ * @param feedback feedback listener ++ * @return a command sender ++ */ ++ @NotNull ++ public static CommandSender createCommandSender(final @NotNull java.util.function.Consumer feedback) { ++ return server.createCommandSender(feedback); ++ } ++ // Paper end ++ + /** + * Gets the folder that contains all of the various {@link World}s. + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 5ca4543587043f964175435654b9e00c9dadffd5..06cc09298abcefaacd7a6987c32e5bd86653e719 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1349,6 +1349,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public ConsoleCommandSender getConsoleSender(); + ++ // Paper start ++ /** ++ * Creates a special {@link CommandSender} which redirects command feedback (in the form of chat messages) to the ++ * specified listener. The returned sender will have the same effective permissions as {@link #getConsoleSender()}. ++ * ++ * @param feedback feedback listener ++ * @return a command sender ++ */ ++ @NotNull ++ public CommandSender createCommandSender(final @NotNull java.util.function.Consumer feedback); ++ // Paper end ++ + /** + * Gets the folder that contains all of the various {@link World}s. + * diff --git a/patches/api/0331-Implement-regenerateChunk.patch b/patches/api/0331-Implement-regenerateChunk.patch new file mode 100644 index 000000000000..ba17a9e629d4 --- /dev/null +++ b/patches/api/0331-Implement-regenerateChunk.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Sat, 5 Feb 2022 20:25:28 +0100 +Subject: [PATCH] Implement regenerateChunk + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index a8939bb5815fbc2926907bb3e8921f86255abd93..0f01e87c1f09f2291d12eaac7f12b32ca543c82f 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -405,8 +405,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + * @return Whether the chunk was actually regenerated + * + * @deprecated regenerating a single chunk is not likely to produce the same +- * chunk as before as terrain decoration may be spread across chunks. Use of +- * this method should be avoided as it is known to produce buggy results. ++ * chunk as before as terrain decoration may be spread across chunks. It may ++ * or may not change blocks in the adjacent chunks as well. + */ + @Deprecated(since = "1.13") + public boolean regenerateChunk(int x, int z); diff --git a/patches/api/0332-Add-GameEvent-tags.patch b/patches/api/0332-Add-GameEvent-tags.patch new file mode 100644 index 000000000000..961174f6e825 --- /dev/null +++ b/patches/api/0332-Add-GameEvent-tags.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 18 Dec 2021 10:34:21 -0800 +Subject: [PATCH] Add GameEvent tags + + +diff --git a/src/main/java/org/bukkit/Tag.java b/src/main/java/org/bukkit/Tag.java +index 8420fb1c6059ea9f782a47d18c465ba515765085..961a36e03df968898590c95573cee04083988e32 100644 +--- a/src/main/java/org/bukkit/Tag.java ++++ b/src/main/java/org/bukkit/Tag.java +@@ -1427,6 +1427,25 @@ public interface Tag extends Keyed { + */ + Tag ENTITY_TYPES_REDIRECTABLE_PROJECTILE = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("redirectable_projectile"), EntityType.class); + ++ // Paper start ++ String REGISTRY_GAME_EVENTS = "game_events"; ++ ++ /** ++ * Tag for game events that trigger sculk sensors ++ */ ++ Tag GAME_EVENT_VIBRATIONS = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("vibrations"), GameEvent.class); ++ ++ /** ++ * Tag for game events that are ignored if the entity is sneaking ++ */ ++ Tag GAME_EVENT_IGNORE_VIBRATIONS_SNEAKING = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("ignore_vibrations_sneaking"), GameEvent.class); ++ ++ /** ++ * Tag for game events that an allay can listen to ++ */ ++ Tag GAME_EVENT_ALLAY_CAN_LISTEN = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("allay_can_listen"), GameEvent.class); ++ // Paper end ++ + /** + * Returns whether or not this tag has an entry for the specified item. + * diff --git a/patches/api/0333-Furnace-RecipesUsed-API.patch b/patches/api/0333-Furnace-RecipesUsed-API.patch new file mode 100644 index 000000000000..7fed82db2115 --- /dev/null +++ b/patches/api/0333-Furnace-RecipesUsed-API.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 13 Jan 2022 15:21:08 -0800 +Subject: [PATCH] Furnace RecipesUsed API + + +diff --git a/src/main/java/org/bukkit/block/Furnace.java b/src/main/java/org/bukkit/block/Furnace.java +index dbdf3dbe9517b09a7965cf9d65cae1edd87af67d..8745e5aeaa81cd42d6625f415c623daa28776647 100644 +--- a/src/main/java/org/bukkit/block/Furnace.java ++++ b/src/main/java/org/bukkit/block/Furnace.java +@@ -92,6 +92,40 @@ public interface Furnace extends Container { + * @throws IllegalArgumentException if value is more than 200 + */ + public void setCookSpeedMultiplier(double multiplier); ++ ++ /** ++ * Gets the number of times a recipe has been used since the ++ * last player removed items from the result slot. This is used ++ * to calculate experience rewards when withdrawing items from furnaces. ++ * ++ * @param furnaceRecipe the recipe to query the count for ++ * @return the count or 0 if none found ++ */ ++ int getRecipeUsedCount(@NotNull org.bukkit.NamespacedKey furnaceRecipe); ++ ++ /** ++ * Checks if the recipe has a used count present on this furnace. ++ * ++ * @param furnaceRecipe the recipe to check if a count exists for ++ * @return true if there is a positive count, else false ++ */ ++ boolean hasRecipeUsedCount(@NotNull org.bukkit.NamespacedKey furnaceRecipe); ++ ++ /** ++ * Sets the number of times a recipe has been used. This is used ++ * to calculate experience rewards when withdrawing items from furnaces. ++ * ++ * @param furnaceRecipe the recipe to set the count for ++ * @param count the count, a non-positive number will remove the recipe ++ */ ++ void setRecipeUsedCount(@NotNull org.bukkit.inventory.CookingRecipe furnaceRecipe, int count); ++ ++ /** ++ * Sets all recipes used by this furnace. ++ * ++ * @param recipesUsed the recipes used ++ */ ++ void setRecipesUsed(@NotNull Map, Integer> recipesUsed); + // Paper end + + @NotNull diff --git a/patches/api/0334-Configurable-sculk-sensor-listener-range.patch b/patches/api/0334-Configurable-sculk-sensor-listener-range.patch new file mode 100644 index 000000000000..b1ad0cdb5b15 --- /dev/null +++ b/patches/api/0334-Configurable-sculk-sensor-listener-range.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 19 Aug 2021 18:43:16 -0700 +Subject: [PATCH] Configurable sculk sensor listener range + + +diff --git a/src/main/java/org/bukkit/block/SculkSensor.java b/src/main/java/org/bukkit/block/SculkSensor.java +index 18966117823eda97e37627fe72b3dbc2c67cab7c..95a822613093479821c22c9aeea32b27d3ec2e21 100644 +--- a/src/main/java/org/bukkit/block/SculkSensor.java ++++ b/src/main/java/org/bukkit/block/SculkSensor.java +@@ -24,4 +24,19 @@ public interface SculkSensor extends TileState { + * @param lastVibrationFrequency frequency between 0-15. + */ + void setLastVibrationFrequency(int lastVibrationFrequency); ++ // Paper start ++ /** ++ * Gets the range this sensor listens to events at. ++ * ++ * @return the range (defaults to 8) ++ */ ++ int getListenerRange(); ++ ++ /** ++ * Sets the range this sensor will listen to events from. ++ * ++ * @param range the range (must be greater than 0) ++ */ ++ void setListenerRange(int range); ++ // Paper end + } diff --git a/patches/api/0335-Add-missing-block-data-API.patch b/patches/api/0335-Add-missing-block-data-API.patch new file mode 100644 index 000000000000..1675944429f0 --- /dev/null +++ b/patches/api/0335-Add-missing-block-data-API.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 16 Oct 2021 22:57:10 -0700 +Subject: [PATCH] Add missing block data API + +General purpose patch adding missing getters/setters to BlockData and +its child types. + +Co-authored-by: SoSeDiK +Co-authored-by: Fabrizio La Rosa + +diff --git a/src/main/java/org/bukkit/block/data/Levelled.java b/src/main/java/org/bukkit/block/data/Levelled.java +index 5255538fecae6da413546be3adacd2a99f6c74e9..860f072dee391b300cb1629058a3f9c23dfd95e2 100644 +--- a/src/main/java/org/bukkit/block/data/Levelled.java ++++ b/src/main/java/org/bukkit/block/data/Levelled.java +@@ -36,4 +36,13 @@ public interface Levelled extends BlockData { + * @return the maximum 'level' value + */ + int getMaximumLevel(); ++ ++ // Paper start ++ /** ++ * Gets the minimum allowed value of the 'level' property. ++ * ++ * @return the minimum 'level' value ++ */ ++ int getMinimumLevel(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/block/data/type/Bed.java b/src/main/java/org/bukkit/block/data/type/Bed.java +index ed519bfebe5b921f60867a3900edfce9859058b6..6e7a456dc5e9bfc28a19029a3381e53fa6453d30 100644 +--- a/src/main/java/org/bukkit/block/data/type/Bed.java ++++ b/src/main/java/org/bukkit/block/data/type/Bed.java +@@ -35,6 +35,15 @@ public interface Bed extends Directional { + */ + boolean isOccupied(); + ++ // Paper start ++ /** ++ * Sets the value of the 'occupied' property. ++ * ++ * @param occupied the new 'occupied' value ++ */ ++ void setOccupied(boolean occupied); ++ // Paper end ++ + /** + * Horizontal half of a bed. + */ +diff --git a/src/main/java/org/bukkit/block/data/type/Candle.java b/src/main/java/org/bukkit/block/data/type/Candle.java +index d4d08bd424f84523200d1a2012f4d37c07cc3497..7baccce27f2db2242f628ea92a9d040267caef75 100644 +--- a/src/main/java/org/bukkit/block/data/type/Candle.java ++++ b/src/main/java/org/bukkit/block/data/type/Candle.java +@@ -28,4 +28,13 @@ public interface Candle extends Lightable, Waterlogged { + * @return the maximum 'candles' value + */ + int getMaximumCandles(); ++ ++ // Paper start ++ /** ++ * Gets the minimum allowed value of the 'candles' property. ++ * ++ * @return the minimum 'candles' value ++ */ ++ int getMinimumCandles(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/block/data/type/DecoratedPot.java b/src/main/java/org/bukkit/block/data/type/DecoratedPot.java +index eb0ffa977450ef0c79caa78302cfe75ee35b34b7..b3d290dbfdcbadcbadcb54e6b414e423eba80cc6 100644 +--- a/src/main/java/org/bukkit/block/data/type/DecoratedPot.java ++++ b/src/main/java/org/bukkit/block/data/type/DecoratedPot.java +@@ -4,4 +4,17 @@ import org.bukkit.block.data.Directional; + import org.bukkit.block.data.Waterlogged; + + public interface DecoratedPot extends Directional, Waterlogged { ++ // Paper start - add missing block data api ++ /** ++ * @return whether the pot is cracked ++ */ ++ public boolean isCracked(); ++ ++ /** ++ * Set whether the pot is cracked. ++ * ++ * @param cracked whether the pot is cracked ++ */ ++ public void setCracked(boolean cracked); ++ // Paper end - add missing block data api + } +diff --git a/src/main/java/org/bukkit/block/data/type/Leaves.java b/src/main/java/org/bukkit/block/data/type/Leaves.java +index 3ea21dfad26222ee70fbc627595f54de1a28aa96..cd013a7c42648d819d1e91c7cf9f97a8190c1fad 100644 +--- a/src/main/java/org/bukkit/block/data/type/Leaves.java ++++ b/src/main/java/org/bukkit/block/data/type/Leaves.java +@@ -39,4 +39,20 @@ public interface Leaves extends Waterlogged { + * @param distance the new 'distance' value + */ + void setDistance(int distance); ++ ++ // Paper start ++ /** ++ * Gets the maximum allowed value of the 'distance' property. ++ * ++ * @return the maximum 'distance' value ++ */ ++ int getMaximumDistance(); ++ ++ /** ++ * Gets the minimum allowed value of the 'distance' property. ++ * ++ * @return the minimum 'distance' value ++ */ ++ int getMinimumDistance(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/block/data/type/PinkPetals.java b/src/main/java/org/bukkit/block/data/type/PinkPetals.java +index a84b36f7587eb2ed9e9177973b3166dc94cdf3df..eae9c9cdd0f47a7480ee23ac7b655692f5ee9c1e 100644 +--- a/src/main/java/org/bukkit/block/data/type/PinkPetals.java ++++ b/src/main/java/org/bukkit/block/data/type/PinkPetals.java +@@ -21,6 +21,15 @@ public interface PinkPetals extends Directional { + */ + void setFlowerAmount(int flower_amount); + ++ // Paper start ++ /** ++ * Gets the minimum allowed value of the 'flower_amount' property. ++ * ++ * @return the minimum 'flower_amount' value ++ */ ++ int getMinimumFlowerAmount(); ++ // Paper end ++ + /** + * Gets the maximum allowed value of the 'flower_amount' property. + * diff --git a/patches/api/0336-Custom-Potion-Mixes.patch b/patches/api/0336-Custom-Potion-Mixes.patch new file mode 100644 index 000000000000..5e26417fe9a4 --- /dev/null +++ b/patches/api/0336-Custom-Potion-Mixes.patch @@ -0,0 +1,268 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 7 Oct 2021 14:34:59 -0700 +Subject: [PATCH] Custom Potion Mixes + + +diff --git a/src/main/java/io/papermc/paper/potion/PotionMix.java b/src/main/java/io/papermc/paper/potion/PotionMix.java +new file mode 100644 +index 0000000000000000000000000000000000000000..01b2a7c7a6bf328b3f7c30db3be0bfb8156ebc89 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/potion/PotionMix.java +@@ -0,0 +1,103 @@ ++package io.papermc.paper.potion; ++ ++import java.util.Objects; ++import java.util.function.Predicate; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.inventory.RecipeChoice; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents a potion mix made in a Brewing Stand. ++ */ ++@NullMarked ++public final class PotionMix implements Keyed { ++ ++ private final NamespacedKey key; ++ private final ItemStack result; ++ private final RecipeChoice input; ++ private final RecipeChoice ingredient; ++ ++ /** ++ * Creates a new potion mix. Add it to the server with {@link org.bukkit.potion.PotionBrewer#addPotionMix(PotionMix)}. ++ * ++ * @param key a unique key for the mix ++ * @param result the resulting itemstack that will appear in the 3 bottom slots ++ * @param input the input placed into the bottom 3 slots ++ * @param ingredient the ingredient placed into the top slot ++ */ ++ public PotionMix(final NamespacedKey key, final ItemStack result, final RecipeChoice input, final RecipeChoice ingredient) { ++ this.key = key; ++ this.result = result; ++ this.input = input; ++ this.ingredient = ingredient; ++ } ++ ++ /** ++ * Create a {@link RecipeChoice} based on a Predicate. These RecipeChoices are only ++ * valid for {@link PotionMix}, not anywhere else RecipeChoices may be used. ++ * ++ * @param stackPredicate a predicate for an itemstack. ++ * @return a new RecipeChoice ++ */ ++ @Contract(value = "_ -> new", pure = true) ++ public static RecipeChoice createPredicateChoice(final Predicate stackPredicate) { ++ return new PredicateRecipeChoice(stackPredicate); ++ } ++ ++ @Override ++ public NamespacedKey getKey() { ++ return this.key; ++ } ++ ++ /** ++ * Gets the resulting itemstack after the brew has finished. ++ * ++ * @return the result itemstack ++ */ ++ public ItemStack getResult() { ++ return this.result; ++ } ++ ++ /** ++ * Gets the input for the bottom 3 slots in the brewing stand. ++ * ++ * @return the bottom 3 slot ingredients ++ */ ++ public RecipeChoice getInput() { ++ return this.input; ++ } ++ ++ /** ++ * Gets the ingredient in the top slot of the brewing stand. ++ * ++ * @return the top slot input ++ */ ++ public RecipeChoice getIngredient() { ++ return this.ingredient; ++ } ++ ++ @Override ++ public String toString() { ++ return "PotionMix{" + ++ "result=" + this.result + ++ ", base=" + this.input + ++ ", addition=" + this.ingredient + ++ '}'; ++ } ++ ++ @Override ++ public boolean equals(final Object o) { ++ if (this == o) return true; ++ if (o == null || this.getClass() != o.getClass()) return false; ++ final PotionMix potionMix = (PotionMix) o; ++ return this.key.equals(potionMix.key) && this.result.equals(potionMix.result) && this.input.equals(potionMix.input) && this.ingredient.equals(potionMix.ingredient); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(this.key, this.result, this.input, this.ingredient); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/potion/PredicateRecipeChoice.java b/src/main/java/io/papermc/paper/potion/PredicateRecipeChoice.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c252b432a9df5fd7da71a5eecba37a8844820700 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/potion/PredicateRecipeChoice.java +@@ -0,0 +1,32 @@ ++package io.papermc.paper.potion; ++ ++import java.util.function.Predicate; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.inventory.RecipeChoice; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++record PredicateRecipeChoice(Predicate itemStackPredicate) implements RecipeChoice, Cloneable { ++ ++ @Override ++ @Deprecated ++ public ItemStack getItemStack() { ++ throw new UnsupportedOperationException("PredicateRecipeChoice does not support this"); ++ } ++ ++ @Override ++ public RecipeChoice clone() { ++ try { ++ return (PredicateRecipeChoice) super.clone(); ++ } catch (final CloneNotSupportedException ex) { ++ throw new AssertionError(ex); ++ } ++ } ++ ++ @Override ++ public boolean test(final ItemStack itemStack) { ++ return this.itemStackPredicate.test(itemStack); ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index a9d1a9a5223148ea134ed146d059ec9edb922f03..9be54f481a14bc917b465fdef3c2695d8ee64880 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2665,6 +2665,15 @@ public final class Bukkit { + public static io.papermc.paper.datapack.DatapackManager getDatapackManager() { + return server.getDatapackManager(); + } ++ ++ /** ++ * Gets the potion brewer. ++ * ++ * @return the potion brewer ++ */ ++ public static @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer() { ++ return server.getPotionBrewer(); ++ } + // Paper end + + @NotNull +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 06cc09298abcefaacd7a6987c32e5bd86653e719..0da9cee02e2a77e16e3bfaec2197bfc567f5580a 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2322,5 +2322,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + @NotNull + io.papermc.paper.datapack.DatapackManager getDatapackManager(); ++ ++ /** ++ * Gets the potion brewer. ++ * ++ * @return the potion brewer ++ */ ++ @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer(); + // Paper end + } +diff --git a/src/main/java/org/bukkit/potion/PotionBrewer.java b/src/main/java/org/bukkit/potion/PotionBrewer.java +index a90a97901475060e6a4c3ab4e864d30b03974c44..72e159698762f816c06378090a9847d211bfc451 100644 +--- a/src/main/java/org/bukkit/potion/PotionBrewer.java ++++ b/src/main/java/org/bukkit/potion/PotionBrewer.java +@@ -4,10 +4,31 @@ import java.util.Collection; + import org.jetbrains.annotations.NotNull; + + /** +- * Represents a brewer that can create {@link PotionEffect}s. ++ * Used to manage custom {@link io.papermc.paper.potion.PotionMix}s. + */ + public interface PotionBrewer { + ++ // Paper start ++ /** ++ * Adds a new potion mix recipe. ++ * ++ * @param potionMix the potion mix to add ++ */ ++ void addPotionMix(@NotNull io.papermc.paper.potion.PotionMix potionMix); ++ ++ /** ++ * Removes a potion mix recipe. ++ * ++ * @param key the key of the mix to remove ++ */ ++ void removePotionMix(@NotNull org.bukkit.NamespacedKey key); ++ ++ /** ++ * Resets potion mixes to their default, removing all custom ones. ++ */ ++ void resetPotionMixes(); ++ // Paper end ++ + /** + * Creates a {@link PotionEffect} from the given {@link PotionEffectType}, + * applying duration modifiers and checks. +@@ -16,9 +37,15 @@ public interface PotionBrewer { + * @param duration The duration in ticks + * @param amplifier The amplifier of the effect + * @return The resulting potion effect ++ * @deprecated use {@link PotionEffectType#createEffect(int, int)} instead. + */ ++ @Deprecated(forRemoval = true, since = "1.20.5") // Paper + @NotNull +- public PotionEffect createEffect(@NotNull PotionEffectType potion, int duration, int amplifier); ++ // Paper start - make default ++ default PotionEffect createEffect(@NotNull PotionEffectType potion, int duration, int amplifier) { ++ return potion.createEffect(duration, amplifier); ++ } ++ // Paper end + + /** + * Returns a collection of {@link PotionEffect} that would be applied from +@@ -28,9 +55,13 @@ public interface PotionBrewer { + * @return The list of effects + * @deprecated Non-Functional + */ +- @Deprecated(since = "1.6.2") ++ @Deprecated(since = "1.6.2", forRemoval = true) // Paper + @NotNull +- public Collection getEffectsFromDamage(int damage); ++ // Paper start - make default ++ default Collection getEffectsFromDamage(final int damage) { ++ return new java.util.ArrayList<>(); ++ } ++ // Paper end + + /** + * Returns a collection of {@link PotionEffect} that would be applied from +@@ -43,6 +74,6 @@ public interface PotionBrewer { + * @deprecated Upgraded / extended potions are now their own {@link PotionType} use {@link PotionType#getPotionEffects()} instead + */ + @NotNull +- @Deprecated(since = "1.20.2") ++ @Deprecated(since = "1.20.2", forRemoval = true) // Paper + public Collection getEffects(@NotNull PotionType type, boolean upgraded, boolean extended); + } diff --git a/patches/api/0337-Expose-furnace-minecart-push-values.patch b/patches/api/0337-Expose-furnace-minecart-push-values.patch new file mode 100644 index 000000000000..3d8c2336e7e7 --- /dev/null +++ b/patches/api/0337-Expose-furnace-minecart-push-values.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: EpicKnarvik97 +Date: Sat, 5 Mar 2022 20:58:47 +0100 +Subject: [PATCH] Expose furnace minecart push values + +Adds methods for getting and setting a furnace minecart's push values + +diff --git a/src/main/java/org/bukkit/entity/minecart/PoweredMinecart.java b/src/main/java/org/bukkit/entity/minecart/PoweredMinecart.java +index 2076af6c029027d3243ebfa518f4d69b716de7fe..b95df59f780da9291d1d2db77a8eb7a9cd460777 100644 +--- a/src/main/java/org/bukkit/entity/minecart/PoweredMinecart.java ++++ b/src/main/java/org/bukkit/entity/minecart/PoweredMinecart.java +@@ -21,4 +21,34 @@ public interface PoweredMinecart extends Minecart { + * @param fuel Number of ticks until the minecart runs out of fuel + */ + public void setFuel(int fuel); ++ ++ // Paper start ++ /** ++ * Get the x push of the minecart. ++ * ++ * @return The x push of the minecart ++ */ ++ public double getPushX(); ++ ++ /** ++ * Get the z push of the minecart. ++ * ++ * @return The z push of the minecart ++ */ ++ public double getPushZ(); ++ ++ /** ++ * Set the x push of the minecart. ++ * ++ * @param xPush The new x push of the minecart ++ */ ++ public void setPushX(double xPush); ++ ++ /** ++ * Set the z push of the minecart. ++ * ++ * @param zPush The new z push of the minecart ++ */ ++ public void setPushZ(double zPush); ++ // Paper end + } diff --git a/patches/api/0338-More-Projectile-API.patch b/patches/api/0338-More-Projectile-API.patch new file mode 100644 index 000000000000..9c3f7dd61631 --- /dev/null +++ b/patches/api/0338-More-Projectile-API.patch @@ -0,0 +1,520 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 26 May 2021 19:34:43 -0400 +Subject: [PATCH] More Projectile API + +Co-authored-by: Nassim Jahnke +Co-authored-by: SoSeDiK +Co-authored-by: MelnCat + +diff --git a/src/main/java/org/bukkit/entity/AbstractArrow.java b/src/main/java/org/bukkit/entity/AbstractArrow.java +index ebb6976aba314f592459cdfa49f6c15079207fd2..88b8f2e81cdd22e5e879832c9223a770df7e9f42 100644 +--- a/src/main/java/org/bukkit/entity/AbstractArrow.java ++++ b/src/main/java/org/bukkit/entity/AbstractArrow.java +@@ -139,17 +139,21 @@ public interface AbstractArrow extends Projectile { + * Gets the ItemStack which will be picked up from this arrow. + * + * @return The picked up ItemStack ++ * @deprecated use {@link #getItemStack()} + */ + @NotNull + @ApiStatus.Experimental ++ @Deprecated(forRemoval = true, since = "1.20.4") // Paper + public ItemStack getItem(); + + /** + * Sets the ItemStack which will be picked up from this arrow. + * + * @param item ItemStack set to be picked up ++ * @deprecated use {@link #getItemStack()} + */ + @ApiStatus.Experimental ++ @Deprecated(forRemoval = true, since = "1.20.4") // Paper + public void setItem(@NotNull ItemStack item); + + /** +@@ -220,4 +224,52 @@ public interface AbstractArrow extends Projectile { + CREATIVE_ONLY; + } + // Paper end ++ ++ // Paper start - more projectile API ++ /** ++ * Gets the {@link ItemStack} for this arrow. This stack is used ++ * for both visuals on the arrow and the stack that could be picked up. ++ * ++ * @return The ItemStack, as if a player picked up the arrow ++ */ ++ @NotNull ItemStack getItemStack(); ++ ++ /** ++ * Sets the {@link ItemStack} for this arrow. This stack is used for both ++ * visuals on the arrow and the stack that could be picked up. ++ * ++ * @param stack the arrow stack ++ */ ++ void setItemStack(@NotNull ItemStack stack); ++ ++ /** ++ * Sets the amount of ticks this arrow has been alive in the world ++ * This is used to determine when the arrow should be automatically despawned. ++ * ++ * @param ticks lifetime ticks ++ */ ++ void setLifetimeTicks(int ticks); ++ ++ /** ++ * Gets how many ticks this arrow has been in the world for. ++ * ++ * @return ticks this arrow has been in the world ++ */ ++ int getLifetimeTicks(); ++ ++ /** ++ * Gets the sound that is played when this arrow hits an entity. ++ * ++ * @return sound that plays ++ */ ++ @NotNull ++ org.bukkit.Sound getHitSound(); ++ ++ /** ++ * Sets the sound that is played when this arrow hits an entity. ++ * ++ * @param sound sound that is played ++ */ ++ void setHitSound(@NotNull org.bukkit.Sound sound); ++ // Paper end - more projectile API + } +diff --git a/src/main/java/org/bukkit/entity/Firework.java b/src/main/java/org/bukkit/entity/Firework.java +index 0d31aa0b22cf1e849572294e2cfe38b48c9210af..217d348ad0bbef720b25d3b507a55ca8105b7731 100644 +--- a/src/main/java/org/bukkit/entity/Firework.java ++++ b/src/main/java/org/bukkit/entity/Firework.java +@@ -16,6 +16,8 @@ public interface Firework extends Projectile { + + /** + * Apply the provided meta to the fireworks ++ *

      ++ * Adjusts detonation ticks automatically. + * + * @param meta The FireworkMeta to apply + */ +@@ -54,31 +56,39 @@ public interface Firework extends Projectile { + * {@link #getMaxLife()}, the firework will detonate. + * + * @param ticks the ticks to set. Must be greater than or equal to 0 ++ * @deprecated use {@link #setTicksFlown(int)} + * @return true if the life was set, false if this firework has already detonated + */ ++ @Deprecated(forRemoval = true) // Paper + boolean setLife(int ticks); + + /** + * Get the ticks that this firework has been alive. When this value reaches + * {@link #getMaxLife()}, the firework will detonate. + * ++ * @deprecated use {@link #getTicksFlown()} + * @return the life ticks + */ ++ @Deprecated(forRemoval = true) // Paper + int getLife(); + + /** + * Set the time in ticks this firework will exist until it is detonated. + * + * @param ticks the ticks to set. Must be greater than 0 ++ * @deprecated use {@link #setTicksToDetonate(int)} + * @return true if the time was set, false if this firework has already detonated + */ ++ @Deprecated(forRemoval = true) // Paper + boolean setMaxLife(int ticks); + + /** + * Get the time in ticks this firework will exist until it is detonated. + * ++ * @deprecated use {@link #getTicksToDetonate()} + * @return the maximum life in ticks + */ ++ @Deprecated(forRemoval = true) // Paper + int getMaxLife(); + + /** +@@ -127,4 +137,52 @@ public interface Firework extends Projectile { + return getAttachedTo(); + } + // Paper end ++ ++ // Paper start - Firework API ++ /** ++ * Gets the item used in the firework. ++ * ++ * @return firework item ++ */ ++ @NotNull ++ public org.bukkit.inventory.ItemStack getItem(); ++ ++ /** ++ * Sets the item used in the firework. ++ *

      ++ * Firework explosion effects are used from this item. ++ * ++ * @param itemStack item to set ++ */ ++ void setItem(@org.jetbrains.annotations.Nullable org.bukkit.inventory.ItemStack itemStack); ++ ++ /** ++ * Gets the number of ticks the firework has flown. ++ * ++ * @return ticks flown ++ */ ++ int getTicksFlown(); ++ ++ /** ++ * Sets the number of ticks the firework has flown. ++ * Setting this greater than detonation ticks will cause the firework to explode. ++ * ++ * @param ticks ticks flown ++ */ ++ void setTicksFlown(int ticks); ++ ++ /** ++ * Gets the number of ticks the firework will detonate on. ++ * ++ * @return the tick to detonate on ++ */ ++ int getTicksToDetonate(); ++ ++ /** ++ * Set the amount of ticks the firework will detonate on. ++ * ++ * @param ticks ticks to detonate on ++ */ ++ void setTicksToDetonate(int ticks); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/FishHook.java b/src/main/java/org/bukkit/entity/FishHook.java +index e17851255506f23b33e3e010d2eeb74e83c6e682..c28e78aa259bbd80343cd6d788436833098f0aea 100644 +--- a/src/main/java/org/bukkit/entity/FishHook.java ++++ b/src/main/java/org/bukkit/entity/FishHook.java +@@ -322,4 +322,50 @@ public interface FishHook extends Projectile { + */ + BOBBING; + } ++ ++ // Paper start - More FishHook API ++ /** ++ * Get the number of ticks the hook needs to wait for a fish to bite. ++ * ++ * @return Number of ticks ++ */ ++ int getWaitTime(); ++ ++ /** ++ * Sets the number of ticks the hook needs to wait for a fish to bite. ++ * ++ * @param ticks Number of ticks ++ */ ++ void setWaitTime(int ticks); ++ ++ /** ++ * Get the number of ticks the fish has to swim until biting the hook. ++ * The {@link #getWaitTime()} has to be zero or below for the fish to start the time until bite timer. ++ * ++ * @return number of ticks. ++ * A value of one indicates that the fish bites the very next time the fish hook is ticked ++ * while a value of zero represents a fish that has already bitten the hook. ++ * @see #getWaitTime() ++ */ ++ @org.jetbrains.annotations.Range(from = 0, to = Integer.MAX_VALUE) ++ int getTimeUntilBite(); ++ ++ /** ++ * Sets the number of ticks the fish has to swim until biting the hook. ++ * ++ * @param ticks number of ticks. ++ * One is the minimum that can be passed to this method and instructs the fish to bite the very next tick. ++ * @throws IllegalArgumentException if the passed tick value is less than one. ++ */ ++ void setTimeUntilBite(@org.jetbrains.annotations.Range(from = 1, to = Integer.MAX_VALUE) int ticks) throws IllegalArgumentException; ++ ++ /** ++ * Completely resets this fishing hook's fishing state, re-randomizing the time needed until a fish is lured and ++ * bites the hook. ++ *

      ++ * This method takes all properties of the fishing hook into account when resetting said values, such as a lure ++ * enchantment. ++ */ ++ void resetFishingState(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Projectile.java b/src/main/java/org/bukkit/entity/Projectile.java +index fe64f4e87a0f600b5f1522f788f78ccfc5d7c7ea..f4c7317fd2da03181d836a3d1d24ae910710f0bc 100644 +--- a/src/main/java/org/bukkit/entity/Projectile.java ++++ b/src/main/java/org/bukkit/entity/Projectile.java +@@ -12,6 +12,7 @@ public interface Projectile extends Entity { + * Retrieve the shooter of this projectile. + * + * @return the {@link ProjectileSource} that shot this projectile ++ * @see #getOwnerUniqueId() + */ + @Nullable + public ProjectileSource getShooter(); +@@ -41,4 +42,89 @@ public interface Projectile extends Entity { + */ + @Deprecated(since = "1.20.2", forRemoval = true) + public void setBounce(boolean doesBounce); ++ // Paper start ++ ++ /** ++ * Gets whether the projectile has left the ++ * hitbox of their shooter and can now hit entities. ++ * ++ * @return has left shooter's hitbox ++ */ ++ boolean hasLeftShooter(); ++ ++ /** ++ * Sets whether the projectile has left the ++ * hitbox of their shooter and can now hit entities. ++ * ++ * This is recalculated each tick if the projectile has a shooter. ++ * ++ * @param leftShooter has left shooter's hitbox ++ */ ++ void setHasLeftShooter(boolean leftShooter); ++ ++ /** ++ * Gets whether the projectile has been ++ * shot into the world and has sent a projectile ++ * shot game event. ++ * ++ * @return has been shot into the world ++ */ ++ boolean hasBeenShot(); ++ ++ /** ++ * Sets whether the projectile has been ++ * shot into the world and has sent a projectile ++ * shot game event in the next tick. ++ * ++ * Setting this to false will cause a game event ++ * to fire and the value to be set back to true. ++ * ++ * @param beenShot has been in shot into the world ++ */ ++ void setHasBeenShot(boolean beenShot); ++ ++ /** ++ * Gets whether this projectile can hit an entity. ++ *

      ++ * This method returns true under the following conditions: ++ *

      ++ * - The shooter can see the entity ({@link Player#canSee(Entity)})

      ++ * - The entity is alive and not a spectator

      ++ * - The projectile has left the hitbox of the shooter ({@link #hasLeftShooter()})

      ++ * - If this is an arrow with piercing, it has not pierced the entity already ++ * ++ * @param entity the entity to check if this projectile can hit ++ * @return true if this projectile can damage the entity, false otherwise ++ */ ++ boolean canHitEntity(@org.jetbrains.annotations.NotNull Entity entity); ++ ++ /** ++ * Makes this projectile hit a specific entity. ++ * This uses the current position of the projectile for the hit point. ++ * Using this method will result in {@link org.bukkit.event.entity.ProjectileHitEvent} being called. ++ * @param entity the entity to hit ++ * @see #hitEntity(Entity, org.bukkit.util.Vector) ++ * @see #canHitEntity(Entity) ++ */ ++ void hitEntity(@org.jetbrains.annotations.NotNull Entity entity); ++ ++ /** ++ * Makes this projectile hit a specific entity from a specific point. ++ * Using this method will result in {@link org.bukkit.event.entity.ProjectileHitEvent} being called. ++ * @param entity the entity to hit ++ * @param vector the direction to hit from ++ * @see #hitEntity(Entity) ++ * @see #canHitEntity(Entity) ++ */ ++ void hitEntity(@org.jetbrains.annotations.NotNull Entity entity, @org.jetbrains.annotations.NotNull org.bukkit.util.Vector vector); ++ ++ /** ++ * Gets the owner's UUID ++ * ++ * @return the owner's UUID, or null if not owned ++ * @see #getShooter() ++ */ ++ @Nullable ++ java.util.UUID getOwnerUniqueId(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/ShulkerBullet.java b/src/main/java/org/bukkit/entity/ShulkerBullet.java +index 4623e0d767b343cbdc6fcf20b3b2ff7ff14863cf..dd69a68d1f005c25329bb0366d161ae9b061e108 100644 +--- a/src/main/java/org/bukkit/entity/ShulkerBullet.java ++++ b/src/main/java/org/bukkit/entity/ShulkerBullet.java +@@ -18,4 +18,61 @@ public interface ShulkerBullet extends Projectile { + * @param target the entity to target + */ + void setTarget(@Nullable Entity target); ++ // Paper start ++ /** ++ * Gets the relative offset that this shulker bullet should move towards, ++ * note that this will change each tick as the skulker bullet approaches the target. ++ * ++ * @return target delta offset ++ */ ++ @org.jetbrains.annotations.NotNull ++ org.bukkit.util.Vector getTargetDelta(); ++ ++ ++ /** ++ * Sets the relative offset that this shulker bullet should move towards, ++ * note that this will change each tick as the skulker bullet approaches the target. ++ * This is usually relative towards their target. ++ * ++ * @param vector target ++ */ ++ void setTargetDelta(@org.jetbrains.annotations.NotNull org.bukkit.util.Vector vector); ++ ++ /** ++ * Gets the current movement direction. ++ * This is used to determine the next movement direction to ensure ++ * that the bullet does not move in the same direction. ++ * ++ * @return null or their current direction ++ */ ++ @Nullable ++ org.bukkit.block.BlockFace getCurrentMovementDirection(); ++ ++ /** ++ * Set the current movement direction. ++ * This is used to determine the next movement direction to ensure ++ * that the bullet does not move in the same direction. ++ * ++ * Set to null to simply pick a random direction. ++ * ++ * @param movementDirection null or a direction ++ */ ++ void setCurrentMovementDirection(@Nullable org.bukkit.block.BlockFace movementDirection); ++ ++ /** ++ * Gets how many ticks this shulker bullet ++ * will attempt to move in its current direction. ++ * ++ * @return number of steps ++ */ ++ int getFlightSteps(); ++ ++ /** ++ * Sets how many ticks this shulker bullet ++ * will attempt to move in its current direction. ++ * ++ * @param steps number of steps ++ */ ++ void setFlightSteps(int steps); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/ThrownPotion.java b/src/main/java/org/bukkit/entity/ThrownPotion.java +index 7051e07b4e456aae0ec9e37808b59e5fa62a4027..225ac312613b9e8f3cf680819f2ebe350d1bf48a 100644 +--- a/src/main/java/org/bukkit/entity/ThrownPotion.java ++++ b/src/main/java/org/bukkit/entity/ThrownPotion.java +@@ -32,12 +32,34 @@ public interface ThrownPotion extends ThrowableProjectile { + + /** + * Set the ItemStack for this thrown potion. +- *

      +- * The ItemStack must be of type {@link org.bukkit.Material#SPLASH_POTION} +- * or {@link org.bukkit.Material#LINGERING_POTION}, otherwise an exception +- * is thrown. + * + * @param item New ItemStack + */ + public void setItem(@NotNull ItemStack item); ++ ++ // Paper start - Projectile API ++ /** ++ * Gets a copy of the PotionMeta for this thrown potion. ++ * This includes what effects will be applied by this potion. ++ * ++ * @return potion meta ++ */ ++ @NotNull ++ org.bukkit.inventory.meta.PotionMeta getPotionMeta(); ++ ++ /** ++ * Sets the PotionMeta of this thrown potion. ++ * This will modify the effects applied by this potion. ++ *

      ++ * Note that the type of {@link #getItem()} is irrelevant ++ * ++ * @param meta potion meta ++ */ ++ void setPotionMeta(@NotNull org.bukkit.inventory.meta.PotionMeta meta); ++ ++ /** ++ * Splashes the potion at its current location. ++ */ ++ void splash(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Trident.java b/src/main/java/org/bukkit/entity/Trident.java +index c8015ff610e3c1222cb368ea1d8a0c2f3785d9c7..02584eced96944a551140f8150c65a7c0f4bb55e 100644 +--- a/src/main/java/org/bukkit/entity/Trident.java ++++ b/src/main/java/org/bukkit/entity/Trident.java +@@ -38,5 +38,24 @@ public interface Trident extends AbstractArrow, ThrowableProjectile { + * @throws IllegalArgumentException if the loyalty level is lower than 0 or greater than 127 + */ + void setLoyaltyLevel(int loyaltyLevel); ++ ++ /** ++ * Gets if this trident has dealt damage to an ++ * entity yet or has hit the floor. ++ * ++ * If neither of these events have occurred yet, this will ++ * return false. ++ * ++ * @return has dealt damage ++ */ ++ boolean hasDealtDamage(); ++ ++ /** ++ * Sets if this trident has dealt damage to an entity ++ * yet or has hit the floor. ++ * ++ * @param hasDealtDamage has dealt damage or hit the floor ++ */ ++ void setHasDealtDamage(boolean hasDealtDamage); + } + // Paper end +diff --git a/src/main/java/org/bukkit/projectiles/ProjectileSource.java b/src/main/java/org/bukkit/projectiles/ProjectileSource.java +index 8557bfefaf02538dec95adb29734ae2cf50f3f8c..03faf9a142f494e255258099a6b8831a0d4a879b 100644 +--- a/src/main/java/org/bukkit/projectiles/ProjectileSource.java ++++ b/src/main/java/org/bukkit/projectiles/ProjectileSource.java +@@ -39,4 +39,26 @@ public interface ProjectileSource { + */ + @NotNull + public T launchProjectile(@NotNull Class projectile, @Nullable Vector velocity); ++ ++ // Paper start - add consumer to launchProjectile ++ /** ++ * Launches a {@link Projectile} from the ProjectileSource with an ++ * initial velocity, with the supplied function run before the ++ * entity is added to the world. ++ *
      ++ * Note that when the function is run, the entity will not be actually in ++ * the world. Any operation involving such as teleporting the entity is undefined ++ * until after this function returns. ++ *

      ++ * The family of launchProjectile methods only promise the ability to launch projectile types ++ * that the {@link ProjectileSource} is capable of firing in vanilla. ++ * Any other types of projectiles *may* be implemented but are not part of the method contract. ++ * @param a projectile subclass ++ * @param projectile class of the projectile to launch ++ * @param velocity the velocity with which to launch ++ * @param function the function to be run before the entity is spawned ++ * @return the launched projectile ++ */ ++ @NotNull T launchProjectile(@NotNull Class projectile, @Nullable Vector velocity, java.util.function.@Nullable Consumer function); ++ // Paper end - add consumer to launchProjectile + } diff --git a/patches/api/0339-Add-getComputedBiome-API.patch b/patches/api/0339-Add-getComputedBiome-API.patch new file mode 100644 index 000000000000..fefb8c693eef --- /dev/null +++ b/patches/api/0339-Add-getComputedBiome-API.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Mon, 14 Mar 2022 22:45:32 -0700 +Subject: [PATCH] Add getComputedBiome API + + +diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bukkit/RegionAccessor.java +index b68367f123f029c3ff47eab6bfabd7a894a99da4..44ee56a5956cc17194c767a0c1071a2abffe818a 100644 +--- a/src/main/java/org/bukkit/RegionAccessor.java ++++ b/src/main/java/org/bukkit/RegionAccessor.java +@@ -25,6 +25,7 @@ public interface RegionAccessor extends Keyed { // Paper + * + * @param location the location of the biome + * @return Biome at the given location ++ * @see #getComputedBiome(int, int, int) + */ + @NotNull + Biome getBiome(@NotNull Location location); +@@ -36,10 +37,33 @@ public interface RegionAccessor extends Keyed { // Paper + * @param y Y-coordinate of the block + * @param z Z-coordinate of the block + * @return Biome at the given coordinates ++ * @see #getComputedBiome(int, int, int) + */ + @NotNull + Biome getBiome(int x, int y, int z); + ++ // Paper start ++ /** ++ * Gets the computed {@link Biome} at the given coordinates. ++ * ++ *

      The computed Biome is the Biome as seen by clients for rendering ++ * purposes and in the "F3" debug menu. This is computed by looking at the noise biome ++ * at this and surrounding quarts and applying complex math operations.

      ++ * ++ *

      Most other Biome-related methods named getBiome, setBiome, and similar ++ * operate on the "noise biome", which is stored per-quart, or in other words, ++ * 1 Biome per 4x4x4 block region. This is how Biomes are currently generated and ++ * stored on disk.

      ++ * ++ * @param x X-coordinate of the block ++ * @param y Y-coordinate of the block ++ * @param z Z-coordinate of the block ++ * @return Biome at the given coordinates ++ */ ++ @NotNull ++ Biome getComputedBiome(int x, int y, int z); ++ // Paper end ++ + /** + * Sets the {@link Biome} at the given {@link Location}. + * +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 7f9acd155c1b275145ba53a41b7513dc8cc00531..b47804da74e143b8d3665c3ec7dd9d858eee6a6b 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -375,10 +375,22 @@ public interface Block extends Metadatable, Translatable, net.kyori.adventure.tr + * Returns the biome that this block resides in + * + * @return Biome type containing this block ++ * @see #getComputedBiome() + */ + @NotNull + Biome getBiome(); + ++ // Paper start ++ /** ++ * Gets the computed biome at the location of this Block. ++ * ++ * @return computed biome at the location of this Block. ++ * @see org.bukkit.RegionAccessor#getComputedBiome(int, int, int) ++ */ ++ @NotNull ++ Biome getComputedBiome(); ++ // Paper end ++ + /** + * Sets the biome that this block resides in + * diff --git a/patches/api/0340-Add-enchantWithLevels-API.patch b/patches/api/0340-Add-enchantWithLevels-API.patch new file mode 100644 index 000000000000..5b88a184cd3e --- /dev/null +++ b/patches/api/0340-Add-enchantWithLevels-API.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Wed, 16 Mar 2022 20:35:13 -0700 +Subject: [PATCH] Add enchantWithLevels API + +Deprecate upstream's newer and poorly implemented similar +API. + +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 579a9037b656bef9fb65c6da03611e981492074a..e1986aea72bb1f1ba2ea76f3ba53f274b6aac899 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -170,8 +170,11 @@ public interface ItemFactory { + * @param level the level to use, which is the level in the enchantment table + * @param allowTreasures allows treasure enchants, e.g. mending, if true. + * @return a new ItemStack containing the result of the Enchantment ++ * @deprecated use {@link #enchantWithLevels(ItemStack, int, boolean, java.util.Random)}. This method's implementation is poorly ++ * designed and was originally broken. + */ + @NotNull ++ @Deprecated(since = "1.19.3") // Paper + ItemStack enchantItem(@NotNull final Entity entity, @NotNull final ItemStack item, final int level, final boolean allowTreasures); + + /** +@@ -184,8 +187,11 @@ public interface ItemFactory { + * @param level the level to use, which is the level in the enchantment table + * @param allowTreasures allow the treasure enchants, e.g. mending, if true. + * @return a new ItemStack containing the result of the Enchantment ++ * @deprecated use {@link #enchantWithLevels(ItemStack, int, boolean, java.util.Random)}. This method's implementation is poorly ++ * designed and was originally broken. + */ + @NotNull ++ @Deprecated(since = "1.19.3") // Paper + ItemStack enchantItem(@NotNull final World world, @NotNull final ItemStack item, final int level, final boolean allowTreasures); + + /** +@@ -197,8 +203,11 @@ public interface ItemFactory { + * @param level the level to use, which is the level in the enchantment table + * @param allowTreasures allow treasure enchantments, e.g. mending, if true. + * @return a new ItemStack containing the result of the Enchantment ++ * @deprecated use {@link #enchantWithLevels(ItemStack, int, boolean, java.util.Random)}. This method's implementation is poorly ++ * designed and was originally broken. + */ + @NotNull ++ @Deprecated(since = "1.19.3") // Paper + ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures); + + // Paper start - Adventure +@@ -311,4 +320,22 @@ public interface ItemFactory { + @Deprecated + net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName); + // Paper end - bungee hover events ++ ++ // Paper start - enchantWithLevels API ++ /** ++ * Randomly enchants a copy of the provided {@link ItemStack} using the given experience levels. ++ * ++ *

      If the provided ItemStack is already enchanted, the existing enchants will be removed before enchanting.

      ++ * ++ *

      Levels must be in range {@code [1, 30]}.

      ++ * ++ * @param itemStack ItemStack to enchant ++ * @param levels levels to use for enchanting ++ * @param allowTreasure whether to allow enchantments where {@link org.bukkit.enchantments.Enchantment#isTreasure()} returns true ++ * @param random {@link java.util.Random} instance to use for enchanting ++ * @return enchanted copy of the provided ItemStack ++ * @throws IllegalArgumentException on bad arguments ++ */ ++ @NotNull ItemStack enchantWithLevels(@NotNull ItemStack itemStack, @org.jetbrains.annotations.Range(from = 1, to = 30) int levels, boolean allowTreasure, @NotNull java.util.Random random); ++ // Paper end - enchantWithLevels API + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 86404d3b8b4862cd1f140617cae93aa69df122ca..e9b88bb759af1a5c926d3d4c30a333e7720519cd 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -678,6 +678,24 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + } + + // Paper start ++ /** ++ * Randomly enchants a copy of this {@link ItemStack} using the given experience levels. ++ * ++ *

      If this ItemStack is already enchanted, the existing enchants will be removed before enchanting.

      ++ * ++ *

      Levels must be in range {@code [1, 30]}.

      ++ * ++ * @param levels levels to use for enchanting ++ * @param allowTreasure whether to allow enchantments where {@link org.bukkit.enchantments.Enchantment#isTreasure()} returns true ++ * @param random {@link java.util.Random} instance to use for enchanting ++ * @return enchanted copy of the provided ItemStack ++ * @throws IllegalArgumentException on bad arguments ++ */ ++ @NotNull ++ public ItemStack enchantWithLevels(final @org.jetbrains.annotations.Range(from = 1, to = 30) int levels, final boolean allowTreasure, final @NotNull java.util.Random random) { ++ return Bukkit.getServer().getItemFactory().enchantWithLevels(this, levels, allowTreasure, random); ++ } ++ + @NotNull + @Override + public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { diff --git a/patches/api/0341-Add-TameableDeathMessageEvent.patch b/patches/api/0341-Add-TameableDeathMessageEvent.patch new file mode 100644 index 000000000000..bfab2aa214c2 --- /dev/null +++ b/patches/api/0341-Add-TameableDeathMessageEvent.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Fri, 19 Mar 2021 23:25:38 -0400 +Subject: [PATCH] Add TameableDeathMessageEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/TameableDeathMessageEvent.java b/src/main/java/io/papermc/paper/event/entity/TameableDeathMessageEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b956ef8f95156c225741f53811b4a36963da6616 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/TameableDeathMessageEvent.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.event.entity; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Tameable; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when a {@link Tameable} dies and sends a death message. ++ */ ++@NullMarked ++public class TameableDeathMessageEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private Component deathMessage; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public TameableDeathMessageEvent(final Tameable tameable, final Component deathMessage) { ++ super(tameable); ++ this.deathMessage = deathMessage; ++ } ++ ++ /** ++ * Set the death message that appears to the owner of the tameable. ++ * ++ * @param deathMessage Death message to appear ++ */ ++ public void deathMessage(final Component deathMessage) { ++ this.deathMessage = deathMessage; ++ } ++ ++ /** ++ * Get the death message that appears to the owner of the tameable. ++ * ++ * @return Death message to appear ++ */ ++ public Component deathMessage() { ++ return this.deathMessage; ++ } ++ ++ @Override ++ public Tameable getEntity() { ++ return (Tameable) super.getEntity(); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0342-Allow-to-change-the-podium-of-the-EnderDragon.patch b/patches/api/0342-Allow-to-change-the-podium-of-the-EnderDragon.patch new file mode 100644 index 000000000000..08ffa1fdde63 --- /dev/null +++ b/patches/api/0342-Allow-to-change-the-podium-of-the-EnderDragon.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Doc +Date: Sat, 2 Apr 2022 23:03:32 -0300 +Subject: [PATCH] Allow to change the podium of the EnderDragon + + +diff --git a/src/main/java/org/bukkit/entity/EnderDragon.java b/src/main/java/org/bukkit/entity/EnderDragon.java +index 92cd35c87bad578c2b714761c93a5b72ebf4bc9e..68f58c40a56791df177967de5661cca976a7e98c 100644 +--- a/src/main/java/org/bukkit/entity/EnderDragon.java ++++ b/src/main/java/org/bukkit/entity/EnderDragon.java +@@ -108,4 +108,22 @@ public interface EnderDragon extends ComplexLivingEntity, Boss, Mob, Enemy { + * @return this dragon's death animation ticks + */ + int getDeathAnimationTicks(); ++ ++ // Paper start ++ ++ /** ++ * Get the podium location used by the ender dragon. ++ * ++ * @return the podium location of the dragon ++ */ ++ @NotNull ++ org.bukkit.Location getPodium(); ++ ++ /** ++ * Sets the location of the podium for the ender dragon. ++ * ++ * @param location the location of the podium or null to use the default podium location (exit portal of the end) ++ */ ++ void setPodium(@Nullable org.bukkit.Location location); ++ // Paper end + } diff --git a/patches/api/0343-Fix-incorrect-new-blockstate-in-EntityBreakDoorEvent.patch b/patches/api/0343-Fix-incorrect-new-blockstate-in-EntityBreakDoorEvent.patch new file mode 100644 index 000000000000..21b3f85c0bfc --- /dev/null +++ b/patches/api/0343-Fix-incorrect-new-blockstate-in-EntityBreakDoorEvent.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 2 Jul 2023 22:14:09 -0700 +Subject: [PATCH] Fix incorrect new blockstate in EntityBreakDoorEvent + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityBreakDoorEvent.java b/src/main/java/org/bukkit/event/entity/EntityBreakDoorEvent.java +index 30b9bdca89a8d4b226824b3de8b9ac5bc8243c7d..b7889e3b6cc5d3ed4d7fc2380d0acb060cb0905a 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityBreakDoorEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityBreakDoorEvent.java +@@ -12,8 +12,8 @@ import org.jetbrains.annotations.NotNull; + * Cancelling the event will cause the event to be delayed + */ + public class EntityBreakDoorEvent extends EntityChangeBlockEvent { +- public EntityBreakDoorEvent(@NotNull final LivingEntity entity, @NotNull final Block targetBlock) { +- super(entity, targetBlock, Material.AIR.createBlockData()); ++ public EntityBreakDoorEvent(@NotNull final LivingEntity entity, @NotNull final Block targetBlock, @NotNull final org.bukkit.block.data.BlockData to) { // Paper ++ super(entity, targetBlock, to); // Paper + } + + @NotNull diff --git a/patches/api/0344-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch b/patches/api/0344-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch new file mode 100644 index 000000000000..5775b6f33cca --- /dev/null +++ b/patches/api/0344-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: HexedHero <6012891+HexedHero@users.noreply.github.com> +Date: Sun, 10 Apr 2022 06:21:19 +0100 +Subject: [PATCH] Add pre-unbreaking amount to PlayerItemDamageEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java +index 2d049633998b3965ce0f4a6a4cea3169da0d5658..a2993c7434c9775483a1b4628f2f66454b0d666d 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java +@@ -15,12 +15,21 @@ public class PlayerItemDamageEvent extends PlayerEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private final ItemStack item; + private int damage; ++ private int originalDamage; // Paper - Add pre-reduction damage + private boolean cancelled = false; + ++ @Deprecated // Paper - Add pre-reduction damage + public PlayerItemDamageEvent(@NotNull Player player, @NotNull ItemStack what, int damage) { ++ // Paper start - Add pre-reduction damage ++ this(player, what, damage, damage); ++ } ++ ++ public PlayerItemDamageEvent(@NotNull Player player, @NotNull ItemStack what, int damage, int originalDamage) { + super(player); + this.item = what; + this.damage = damage; ++ this.originalDamage = originalDamage; ++ // Paper end + } + + /** +@@ -42,6 +51,19 @@ public class PlayerItemDamageEvent extends PlayerEvent implements Cancellable { + return damage; + } + ++ // Paper start - Add pre-reduction damage ++ /** ++ * Gets the amount of durability damage this item would have taken before ++ * the Unbreaking reduction. If the item has no Unbreaking level then ++ * this value will be the same as the {@link #getDamage()} value. ++ * ++ * @return pre-reduction damage amount ++ */ ++ public int getOriginalDamage() { ++ return originalDamage; ++ } ++ // Paper end ++ + public void setDamage(int damage) { + this.damage = damage; + } diff --git a/patches/api/0345-WorldCreator-keepSpawnLoaded.patch b/patches/api/0345-WorldCreator-keepSpawnLoaded.patch new file mode 100644 index 000000000000..287c313c5887 --- /dev/null +++ b/patches/api/0345-WorldCreator-keepSpawnLoaded.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Sat, 3 Jul 2021 21:18:41 +0100 +Subject: [PATCH] WorldCreator#keepSpawnLoaded + + +diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java +index afc0ce2eaa7cf48d1255fec7377103b1f7a99734..58e3e3e0e772640b3944b4acb5a92d96431728a7 100644 +--- a/src/main/java/org/bukkit/WorldCreator.java ++++ b/src/main/java/org/bukkit/WorldCreator.java +@@ -23,7 +23,7 @@ public class WorldCreator { + private boolean generateStructures = true; + private String generatorSettings = ""; + private boolean hardcore = false; +- private boolean keepSpawnInMemory = true; ++ private net.kyori.adventure.util.TriState keepSpawnLoaded = net.kyori.adventure.util.TriState.NOT_SET; // Paper + + /** + * Creates an empty WorldCreationOptions for the given world name +@@ -123,7 +123,7 @@ public class WorldCreator { + type = world.getWorldType(); + generateStructures = world.canGenerateStructures(); + hardcore = world.isHardcore(); +- keepSpawnInMemory = world.getKeepSpawnInMemory(); ++ this.keepSpawnLoaded = net.kyori.adventure.util.TriState.byBoolean(world.getKeepSpawnInMemory()); // Paper + + return this; + } +@@ -146,7 +146,7 @@ public class WorldCreator { + generateStructures = creator.generateStructures(); + generatorSettings = creator.generatorSettings(); + hardcore = creator.hardcore(); +- keepSpawnInMemory = creator.keepSpawnInMemory(); ++ keepSpawnLoaded = creator.keepSpawnLoaded(); // Paper + + return this; + } +@@ -470,21 +470,23 @@ public class WorldCreator { + * + * @param keepSpawnInMemory Whether the spawn chunks will be kept loaded + * @return This object, for chaining ++ * @deprecated use {@link #keepSpawnLoaded(net.kyori.adventure.util.TriState)} + */ + @NotNull ++ @Deprecated(forRemoval = true) // Paper + public WorldCreator keepSpawnInMemory(boolean keepSpawnInMemory) { +- this.keepSpawnInMemory = keepSpawnInMemory; +- +- return this; ++ return this.keepSpawnLoaded(net.kyori.adventure.util.TriState.byBoolean(keepSpawnInMemory)); // Paper + } + + /** + * Gets whether or not the spawn chunks will be kept loaded. + * + * @return True if the spawn chunks will be kept loaded ++ * @deprecated use {@link #keepSpawnLoaded()} + */ ++ @Deprecated(forRemoval = true) // Paper + public boolean keepSpawnInMemory() { +- return keepSpawnInMemory; ++ return this.keepSpawnLoaded() == net.kyori.adventure.util.TriState.TRUE; // Paper + } + + /** +@@ -594,4 +596,31 @@ public class WorldCreator { + + return result; + } ++ ++ // Paper start - keep spawn loaded tristate ++ /** ++ * Returns the current intent to keep the world loaded, @see {@link WorldCreator#keepSpawnLoaded(net.kyori.adventure.util.TriState)} ++ * ++ * @return the current tristate value ++ */ ++ @NotNull ++ public net.kyori.adventure.util.TriState keepSpawnLoaded() { ++ return keepSpawnLoaded; ++ } ++ ++ /** ++ * Controls if a world should be kept loaded or not, default (NOT_SET) will use the servers standard ++ * configuration, otherwise, will act as an override towards this setting ++ * ++ * @param keepSpawnLoaded the new value ++ * @return This object, for chaining ++ */ ++ @NotNull ++ public WorldCreator keepSpawnLoaded(@NotNull net.kyori.adventure.util.TriState keepSpawnLoaded) { ++ Preconditions.checkArgument(keepSpawnLoaded != null, "keepSpawnLoaded"); ++ this.keepSpawnLoaded = keepSpawnLoaded; ++ return this; ++ } ++ ++ // Paper end - keep spawn loaded tristate + } diff --git a/patches/api/0346-Add-EntityDyeEvent-and-CollarColorable-interface.patch b/patches/api/0346-Add-EntityDyeEvent-and-CollarColorable-interface.patch new file mode 100644 index 000000000000..4d61563d3b8a --- /dev/null +++ b/patches/api/0346-Add-EntityDyeEvent-and-CollarColorable-interface.patch @@ -0,0 +1,270 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 18 Mar 2022 21:16:38 -0700 +Subject: [PATCH] Add EntityDyeEvent and CollarColorable interface + + +diff --git a/src/main/java/io/papermc/paper/entity/CollarColorable.java b/src/main/java/io/papermc/paper/entity/CollarColorable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..205b561c76386c02c827694b17ea50175a3c84ff +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/CollarColorable.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.entity; ++ ++import org.bukkit.DyeColor; ++import org.bukkit.entity.LivingEntity; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Entities that can have their collars colored. ++ */ ++@NullMarked ++public interface CollarColorable extends LivingEntity { ++ ++ /** ++ * Get the collar color of this entity ++ * ++ * @return the color of the collar ++ */ ++ DyeColor getCollarColor(); ++ ++ /** ++ * Set the collar color of this entity ++ * ++ * @param color the color to apply ++ */ ++ void setCollarColor(DyeColor color); ++} +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityDyeEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityDyeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..049471bac6c9b830fe7717c129173a723091963f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityDyeEvent.java +@@ -0,0 +1,82 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.DyeColor; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.entity.Sheep; ++import org.bukkit.entity.Wolf; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Called when an entity is dyed. Currently, this is called for {@link Sheep} ++ * being dyed, and {@link Wolf}/{@link Cat} collars being dyed. ++ */ ++@NullMarked ++public class EntityDyeEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final @Nullable Player player; ++ private DyeColor dyeColor; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityDyeEvent(final Entity entity, final DyeColor dyeColor, final @Nullable Player player) { ++ super(entity); ++ this.dyeColor = dyeColor; ++ this.player = player; ++ } ++ ++ /** ++ * Gets the DyeColor the entity is being dyed ++ * ++ * @return the DyeColor the entity is being dyed ++ */ ++ public DyeColor getColor() { ++ return this.dyeColor; ++ } ++ ++ /** ++ * Sets the DyeColor the entity is being dyed ++ * ++ * @param dyeColor the DyeColor the entity will be dyed ++ */ ++ public void setColor(final DyeColor dyeColor) { ++ this.dyeColor = dyeColor; ++ } ++ ++ /** ++ * Returns the player dyeing the entity, if available. ++ * ++ * @return player or {@code null} ++ */ ++ public @Nullable Player getPlayer() { ++ return this.player; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/org/bukkit/entity/Cat.java b/src/main/java/org/bukkit/entity/Cat.java +index 5101553bb71d60fee7ac234f7ef2863781dd7742..de422f00f8fd1975669ee5431c466c9c16d699af 100644 +--- a/src/main/java/org/bukkit/entity/Cat.java ++++ b/src/main/java/org/bukkit/entity/Cat.java +@@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Meow. + */ +-public interface Cat extends Tameable, Sittable { ++public interface Cat extends Tameable, Sittable, io.papermc.paper.entity.CollarColorable { // Paper - CollarColorable + + /** + * Gets the current type of this cat. +@@ -36,6 +36,7 @@ public interface Cat extends Tameable, Sittable { + * @return the color of the collar + */ + @NotNull ++ @Override // Paper + public DyeColor getCollarColor(); + + /** +@@ -43,6 +44,7 @@ public interface Cat extends Tameable, Sittable { + * + * @param color the color to apply + */ ++ @Override // Paper + public void setCollarColor(@NotNull DyeColor color); + + /** +diff --git a/src/main/java/org/bukkit/entity/Wolf.java b/src/main/java/org/bukkit/entity/Wolf.java +index 91e96ee5362fd71d28deef1687ebeb0d8dfa05b9..c73489f4b745bc84501ce94f0227b034d9768eae 100644 +--- a/src/main/java/org/bukkit/entity/Wolf.java ++++ b/src/main/java/org/bukkit/entity/Wolf.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a Wolf + */ +-public interface Wolf extends Tameable, Sittable { ++public interface Wolf extends Tameable, Sittable, io.papermc.paper.entity.CollarColorable { // Paper - CollarColorable + + /** + * Checks if this wolf is angry +@@ -34,6 +34,7 @@ public interface Wolf extends Tameable, Sittable { + * @return the color of the collar + */ + @NotNull ++ @Override // Paper + public DyeColor getCollarColor(); + + /** +@@ -41,6 +42,7 @@ public interface Wolf extends Tameable, Sittable { + * + * @param color the color to apply + */ ++ @Override // Paper + public void setCollarColor(@NotNull DyeColor color); + + /** +diff --git a/src/main/java/org/bukkit/event/entity/SheepDyeWoolEvent.java b/src/main/java/org/bukkit/event/entity/SheepDyeWoolEvent.java +index d93a7efd0f6231dbb02fedc4a9108b7cb1d86838..5d056d6bcb0fec0a4ec0aedc3ce9cb52a33934d3 100644 +--- a/src/main/java/org/bukkit/event/entity/SheepDyeWoolEvent.java ++++ b/src/main/java/org/bukkit/event/entity/SheepDyeWoolEvent.java +@@ -11,11 +11,8 @@ import org.jetbrains.annotations.Nullable; + /** + * Called when a sheep's wool is dyed + */ +-public class SheepDyeWoolEvent extends EntityEvent implements Cancellable { +- private static final HandlerList handlers = new HandlerList(); +- private boolean cancel; +- private DyeColor color; +- private final Player player; ++public class SheepDyeWoolEvent extends io.papermc.paper.event.entity.EntityDyeEvent implements Cancellable { ++ // Paper - move everything to superclass + + @Deprecated(since = "1.17.1") + public SheepDyeWoolEvent(@NotNull final Sheep sheep, @NotNull final DyeColor color) { +@@ -23,20 +20,7 @@ public class SheepDyeWoolEvent extends EntityEvent implements Cancellable { + } + + public SheepDyeWoolEvent(@NotNull final Sheep sheep, @NotNull final DyeColor color, @Nullable Player player) { +- super(sheep); +- this.cancel = false; +- this.color = color; +- this.player = player; +- } +- +- @Override +- public boolean isCancelled() { +- return cancel; +- } +- +- @Override +- public void setCancelled(boolean cancel) { +- this.cancel = cancel; ++ super(sheep, color, player); // Paper + } + + @NotNull +@@ -44,45 +28,4 @@ public class SheepDyeWoolEvent extends EntityEvent implements Cancellable { + public Sheep getEntity() { + return (Sheep) entity; + } +- +- /** +- * Returns the player dyeing the sheep, if available. +- * +- * @return player or null +- */ +- @Nullable +- public Player getPlayer() { +- return player; +- } +- +- /** +- * Gets the DyeColor the sheep is being dyed +- * +- * @return the DyeColor the sheep is being dyed +- */ +- @NotNull +- public DyeColor getColor() { +- return color; +- } +- +- /** +- * Sets the DyeColor the sheep is being dyed +- * +- * @param color the DyeColor the sheep will be dyed +- */ +- public void setColor(@NotNull DyeColor color) { +- this.color = color; +- } +- +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } +- + } diff --git a/patches/api/0347-Add-PlayerStopUsingItemEvent.patch b/patches/api/0347-Add-PlayerStopUsingItemEvent.patch new file mode 100644 index 000000000000..c4f27c29257d --- /dev/null +++ b/patches/api/0347-Add-PlayerStopUsingItemEvent.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: u9g +Date: Tue, 3 May 2022 20:41:30 -0400 +Subject: [PATCH] Add PlayerStopUsingItemEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerStopUsingItemEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerStopUsingItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d79b995292799853a0874d4e113e68b494167242 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerStopUsingItemEvent.java +@@ -0,0 +1,53 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when the server detects a player stopping using an item. ++ * Examples of this are letting go of the interact button when holding a bow, an edible item, or a spyglass. ++ */ ++@NullMarked ++public class PlayerStopUsingItemEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final ItemStack item; ++ private final int ticksHeldFor; ++ ++ public PlayerStopUsingItemEvent(final Player player, final ItemStack item, final int ticksHeldFor) { ++ super(player); ++ this.item = item; ++ this.ticksHeldFor = ticksHeldFor; ++ } ++ ++ /** ++ * Gets the exact item the player is releasing ++ * ++ * @return ItemStack the exact item the player released ++ */ ++ public ItemStack getItem() { ++ return this.item; ++ } ++ ++ /** ++ * Gets the number of ticks the item was held for ++ * ++ * @return int the number of ticks the item was held for ++ */ ++ public int getTicksHeldFor() { ++ return this.ticksHeldFor; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0348-Expand-FallingBlock-API.patch b/patches/api/0348-Expand-FallingBlock-API.patch new file mode 100644 index 000000000000..14bfc4015624 --- /dev/null +++ b/patches/api/0348-Expand-FallingBlock-API.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 5 Dec 2021 14:58:55 -0500 +Subject: [PATCH] Expand FallingBlock API + +- add auto expire setting +- add setter for block data +- add accessors for block state + +Co-authored-by: Lukas Planz + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 0f01e87c1f09f2291d12eaac7f12b32ca543c82f..8bfa8db3d0fdbe0c26e3b327d134c6c0af6be206 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -2281,8 +2281,10 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + * @return The spawned {@link FallingBlock} instance + * @throws IllegalArgumentException if {@link Location} or {@link + * MaterialData} are null or {@link Material} of the {@link MaterialData} is not a block ++ * @deprecated Use {@link #spawn(Location, Class, Consumer)} (or a variation thereof) in combination with {@link FallingBlock#setBlockData(BlockData)} + */ + @NotNull ++ @Deprecated(since = "1.20.2") // Paper + public FallingBlock spawnFallingBlock(@NotNull Location location, @NotNull MaterialData data) throws IllegalArgumentException; + + /** +@@ -2295,8 +2297,10 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + * @return The spawned {@link FallingBlock} instance + * @throws IllegalArgumentException if {@link Location} or {@link + * BlockData} are null ++ * @deprecated Use {@link #spawn(Location, Class, Consumer)} (or a variation thereof) in combination with {@link FallingBlock#setBlockData(BlockData)} + */ + @NotNull ++ @org.jetbrains.annotations.ApiStatus.Obsolete(since = "1.20.2") // Paper + public FallingBlock spawnFallingBlock(@NotNull Location location, @NotNull BlockData data) throws IllegalArgumentException; + + /** +@@ -2313,7 +2317,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + * @return The spawned {@link FallingBlock} instance + * @throws IllegalArgumentException if {@link Location} or {@link + * Material} are null or {@link Material} is not a block +- * @deprecated Magic value ++ * @deprecated Magic value. Use {@link #spawn(Location, Class, Consumer)} (or a variation thereof) in combination with {@link FallingBlock#setBlockData(BlockData)} + */ + @Deprecated(since = "1.7.5") + @NotNull +diff --git a/src/main/java/org/bukkit/entity/FallingBlock.java b/src/main/java/org/bukkit/entity/FallingBlock.java +index 315dcf9da29e077a819f602ebf1c76286164b264..f4ec235b9ccc81e8482f721783561313d160629b 100644 +--- a/src/main/java/org/bukkit/entity/FallingBlock.java ++++ b/src/main/java/org/bukkit/entity/FallingBlock.java +@@ -26,6 +26,33 @@ public interface FallingBlock extends Entity { + */ + @NotNull + BlockData getBlockData(); ++ // Paper start ++ /** ++ * Sets the data for the falling block. ++ *
      ++ * Any potential additional data currently stored in the falling blocks {@link #getBlockState()} will be ++ * purged by calling this setter. ++ * ++ * @param blockData the data to use as the block ++ */ ++ void setBlockData(@NotNull BlockData blockData); ++ ++ /** ++ * Get the data of the falling block represented as a {@link org.bukkit.block.BlockState BlockState} ++ * which includes potential NBT data that gets applied when the block gets placed on landing. ++ * ++ * @return the BlockState representing this block ++ */ ++ @NotNull ++ org.bukkit.block.BlockState getBlockState(); ++ ++ /** ++ * Sets the {@link BlockData} and possibly present tile entity data for the falling block. ++ * ++ * @param blockState the BlockState to use ++ */ ++ void setBlockState(@NotNull org.bukkit.block.BlockState blockState); ++ // Paper end + + /** + * Get if the falling block will break into an item if it cannot be placed. +@@ -137,4 +164,23 @@ public interface FallingBlock extends Entity { + default org.bukkit.Location getSourceLoc() { + return this.getOrigin(); + } ++ // Paper start - Auto expire setting ++ /** ++ * Sets if this falling block should expire after: ++ * - 30 seconds ++ * - 5 seconds and is outside of the world ++ * ++ * @return if this behavior occurs ++ */ ++ boolean doesAutoExpire(); ++ ++ /** ++ * Sets if this falling block should expire after: ++ * - 30 seconds ++ * - 5 seconds and is outside of the world ++ * ++ * @param autoExpires if this behavior should occur ++ */ ++ void shouldAutoExpire(boolean autoExpires); ++ // Paper end - Auto expire setting + } diff --git a/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch b/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch new file mode 100644 index 000000000000..e328c2a07628 --- /dev/null +++ b/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BuildTools <46540330+willkroboth@users.noreply.github.com> +Date: Fri, 19 Aug 2022 16:11:51 -0400 +Subject: [PATCH] Add method isTickingWorlds() to Bukkit. + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 9be54f481a14bc917b465fdef3c2695d8ee64880..629d062b76ff4186cc5c824b1bdcafe3667b50fe 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -809,12 +809,26 @@ public final class Bukkit { + return server.getWorlds(); + } + ++ // Paper start ++ /** ++ * Gets whether the worlds are being ticked right now. ++ * ++ * @return true if the worlds are being ticked, false otherwise. ++ */ ++ public static boolean isTickingWorlds(){ ++ return server.isTickingWorlds(); ++ } ++ // Paper end ++ + /** + * Creates or loads a world with the given name using the specified + * options. + *

      + * If the world is already loaded, it will just return the equivalent of + * getWorld(creator.name()). ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param creator the options to use when creating the world + * @return newly created or loaded world +@@ -826,6 +840,9 @@ public final class Bukkit { + + /** + * Unloads a world with the given name. ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param name Name of the world to unload + * @param save whether to save the chunks before unloading +@@ -837,6 +854,9 @@ public final class Bukkit { + + /** + * Unloads the given world. ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param world the world to unload + * @param save whether to save the chunks before unloading +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 0da9cee02e2a77e16e3bfaec2197bfc567f5580a..3f21dfaaa8a6575c9f9b0d33b60fb9913fec8987 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -679,34 +679,55 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @NotNull + public List getWorlds(); + ++ // Paper start ++ /** ++ * Gets whether the worlds are being ticked right now. ++ * ++ * @return true if the worlds are being ticked, false otherwise. ++ */ ++ public boolean isTickingWorlds(); ++ // Paper end ++ + /** + * Creates or loads a world with the given name using the specified + * options. + *

      + * If the world is already loaded, it will just return the equivalent of + * getWorld(creator.name()). ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param creator the options to use when creating the world + * @return newly created or loaded world ++ * @throws IllegalStateException when {@link #isTickingWorlds() isTickingWorlds} is true + */ + @Nullable + public World createWorld(@NotNull WorldCreator creator); + + /** + * Unloads a world with the given name. ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param name Name of the world to unload + * @param save whether to save the chunks before unloading + * @return true if successful, false otherwise ++ * @throws IllegalStateException when {@link #isTickingWorlds() isTickingWorlds} is true + */ + public boolean unloadWorld(@NotNull String name, boolean save); + + /** + * Unloads the given world. ++ *

      ++ * Do note that un/loading worlds mid-tick may have potential side effects, we strongly recommend ++ * ensuring that you're not un/loading worlds midtick by checking {@link Bukkit#isTickingWorlds()} + * + * @param world the world to unload + * @param save whether to save the chunks before unloading + * @return true if successful, false otherwise ++ * @throws IllegalStateException when {@link #isTickingWorlds() isTickingWorlds} is true + */ + public boolean unloadWorld(@NotNull World world, boolean save); + diff --git a/patches/api/0350-Add-WardenAngerChangeEvent.patch b/patches/api/0350-Add-WardenAngerChangeEvent.patch new file mode 100644 index 000000000000..d37a8bcb838f --- /dev/null +++ b/patches/api/0350-Add-WardenAngerChangeEvent.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nopjar +Date: Sun, 12 Jun 2022 00:56:45 +0200 +Subject: [PATCH] Add WardenAngerChangeEvent + +Adding a event which gets called when a warden is angered by +another entity. + +diff --git a/src/main/java/io/papermc/paper/event/entity/WardenAngerChangeEvent.java b/src/main/java/io/papermc/paper/event/entity/WardenAngerChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7c06de67121f92f6e1e8890f250157721c78e627 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/WardenAngerChangeEvent.java +@@ -0,0 +1,103 @@ ++package io.papermc.paper.event.entity; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Warden; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Range; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when a Warden's anger level has changed due to another entity. ++ *

      ++ * If the event is cancelled, the warden's anger level will not change. ++ */ ++@NullMarked ++public class WardenAngerChangeEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity target; ++ private final int oldAnger; ++ private int newAnger; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public WardenAngerChangeEvent(final Warden warden, final Entity target, final int oldAnger, final int newAnger) { ++ super(warden); ++ this.target = target; ++ this.oldAnger = oldAnger; ++ this.newAnger = newAnger; ++ } ++ ++ /** ++ * Gets the entity which triggered this anger update. ++ * ++ * @return triggering entity ++ */ ++ public Entity getTarget() { ++ return this.target; ++ } ++ ++ /** ++ * Gets the old anger level. ++ * ++ * @return old anger level ++ * @see Warden#getAnger(Entity) ++ */ ++ public @Range(from = 0, to = 150) int getOldAnger() { ++ return this.oldAnger; ++ } ++ ++ /** ++ * Gets the new anger level resulting from this event. ++ * ++ * @return new anger level ++ * @see Warden#getAnger(Entity) ++ */ ++ public @Range(from = 0, to = 150) int getNewAnger() { ++ return this.newAnger; ++ } ++ ++ /** ++ * Sets the new anger level resulting from this event. ++ *

      ++ * The anger of a warden is capped at 150. ++ * ++ * @param newAnger the new anger level, max 150 ++ * @throws IllegalArgumentException if newAnger is greater than 150 ++ * @see Warden#setAnger(Entity, int) ++ */ ++ public void setNewAnger(final @Range(from = 0, to = 150) int newAnger) { ++ Preconditions.checkArgument(newAnger <= 150, "newAnger must not be greater than 150"); ++ this.newAnger = newAnger; ++ } ++ ++ @Override ++ public Warden getEntity() { ++ return (Warden) super.getEntity(); ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0351-Nameable-Banner-API.patch b/patches/api/0351-Nameable-Banner-API.patch new file mode 100644 index 000000000000..eba196daaf10 --- /dev/null +++ b/patches/api/0351-Nameable-Banner-API.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Thu, 7 Apr 2022 17:49:38 -0400 +Subject: [PATCH] Nameable Banner API + +Co-Authored-By: Swedz + +diff --git a/src/main/java/org/bukkit/block/Banner.java b/src/main/java/org/bukkit/block/Banner.java +index e6eb3c04b9fa6cd232f95dd5851d365234972efd..4dfd4bd40cb2f852d01a628994964700b9b20dc9 100644 +--- a/src/main/java/org/bukkit/block/Banner.java ++++ b/src/main/java/org/bukkit/block/Banner.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a captured state of a banner. + */ +-public interface Banner extends TileState { ++public interface Banner extends TileState, org.bukkit.Nameable { // Paper - Nameable API + + /** + * Returns the base color for this banner diff --git a/patches/api/0352-Add-Player-getFishHook.patch b/patches/api/0352-Add-Player-getFishHook.patch new file mode 100644 index 000000000000..fc0e0e4157a3 --- /dev/null +++ b/patches/api/0352-Add-Player-getFishHook.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: u9g +Date: Tue, 14 Jun 2022 19:35:21 -0400 +Subject: [PATCH] Add Player#getFishHook + + +diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java +index 10576d39e019c0ca6bbd07b889a4580b2883d875..188c8e27d724a1593dc586b58c7dcb74a1b3d926 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -425,6 +425,13 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder + @Nullable + public Location getPotentialBedLocation(); + // Paper end ++ // Paper start ++ /** ++ * @return the player's fishing hook if they are fishing ++ */ ++ @Nullable ++ FishHook getFishHook(); ++ // Paper end + + /** + * Attempts to make the entity sleep at the given location. diff --git a/patches/api/0353-More-Teleport-API.patch b/patches/api/0353-More-Teleport-API.patch new file mode 100644 index 000000000000..7a4a14cfda81 --- /dev/null +++ b/patches/api/0353-More-Teleport-API.patch @@ -0,0 +1,309 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 5 Sep 2021 00:36:05 -0400 +Subject: [PATCH] More Teleport API + + +diff --git a/src/main/java/io/papermc/paper/entity/LookAnchor.java b/src/main/java/io/papermc/paper/entity/LookAnchor.java +new file mode 100644 +index 0000000000000000000000000000000000000000..544eec787ea837f7d29df6519255840d6fe087d7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/LookAnchor.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper.entity; ++ ++import io.papermc.paper.math.Position; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.LivingEntity; ++ ++/** ++ * Represents what part of the entity should be used when determining where to face a position/entity. ++ * ++ * @see org.bukkit.entity.Player#lookAt(Position, LookAnchor) ++ * @see org.bukkit.entity.Player#lookAt(Entity, LookAnchor, LookAnchor) ++ */ ++public enum LookAnchor { ++ /** ++ * Represents the entity's feet. ++ * @see LivingEntity#getLocation() ++ */ ++ FEET, ++ /** ++ * Represents the entity's eyes. ++ * @see LivingEntity#getEyeLocation() ++ */ ++ EYES; ++} +diff --git a/src/main/java/io/papermc/paper/entity/TeleportFlag.java b/src/main/java/io/papermc/paper/entity/TeleportFlag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9dbbe1f3cfda3b1862fd9cf1ef9853329eda750c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/TeleportFlag.java +@@ -0,0 +1,113 @@ ++package io.papermc.paper.entity; ++ ++import org.bukkit.Location; ++import org.bukkit.event.player.PlayerTeleportEvent; ++ ++/** ++ * Represents a flag that can be set on teleportation that may ++ * slightly modify the behavior. ++ * ++ * @see EntityState ++ * @see Relative ++ */ ++public sealed interface TeleportFlag permits TeleportFlag.EntityState, TeleportFlag.Relative { ++ ++ /** ++ * Note: These flags only work on {@link org.bukkit.entity.Player} entities. ++ *

      ++ * Relative flags enable a player to not lose their velocity in the flag-specific axis/context when teleporting. ++ * ++ * @apiNote The relative flags exposed in the API do *not* mirror all flags known to vanilla, as relative flags concerning ++ * the position are non-applicable given teleports always expect an absolute location. ++ * @see org.bukkit.entity.Player#teleport(Location, PlayerTeleportEvent.TeleportCause, TeleportFlag...) ++ */ ++ enum Relative implements TeleportFlag { ++ /** ++ * Configures the player to not lose velocity in their x axis during the teleport. ++ */ ++ VELOCITY_X, ++ /** ++ * Configures the player to not lose velocity in their y axis during the teleport. ++ */ ++ VELOCITY_Y, ++ /** ++ * Configures the player to not lose velocity in their z axis during the teleport. ++ */ ++ VELOCITY_Z, ++ /** ++ * Configures the player to not lose velocity in their current rotation during the teleport. ++ */ ++ VELOCITY_ROTATION; ++ /** ++ * Configures the player to not loose velocity in their x axis during the teleport. ++ * @deprecated Since 1.21.3, vanilla split up the relative teleport flags into velocity and position related ++ * ones. As the API does not deal with position relative flags, this name is no longer applicable. ++ * Use {@link #VELOCITY_X} instead. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ public static final Relative X = VELOCITY_X; ++ /** ++ * Configures the player to not loose velocity in their y axis during the teleport. ++ * @deprecated Since 1.21.3, vanilla split up the relative teleport flags into velocity and position related ++ * ones. As the API does not deal with position relative flags, this name is no longer applicable. ++ * Use {@link #VELOCITY_Y} instead. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ public static final Relative Y = VELOCITY_Y; ++ /** ++ * Configures the player to not loose velocity in their z axis during the teleport. ++ * @deprecated Since 1.21.3, vanilla split up the relative teleport flags into velocity and position related ++ * ones. As the API does not deal with position relative flags, this name is no longer applicable. ++ * Use {@link #VELOCITY_Z} instead. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ public static final Relative Z = VELOCITY_Z; ++ /** ++ * Represents the player's yaw ++ * ++ * @deprecated relative velocity flags now allow for the whole rotation to be relative, instead of the yaw and ++ * pitch having individual options. Use {@link #VELOCITY_ROTATION} instead. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ public static final Relative YAW = VELOCITY_ROTATION; ++ /** ++ * Represents the player's pitch ++ * ++ * @deprecated relative velocity flags now allow for the whole rotation to be relative, instead of the yaw and ++ * pitch having individual options. Use {@link #VELOCITY_ROTATION} instead. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ public static final Relative PITCH = VELOCITY_ROTATION; ++ } ++ ++ /** ++ * Represents flags that effect the entity's state on ++ * teleportation. ++ */ ++ enum EntityState implements TeleportFlag { ++ /** ++ * If all passengers should not be required to be removed prior to teleportation. ++ *

      ++ * Note: ++ * Teleporting to a different world with this flag present while the entity has entities riding it ++ * will cause this teleportation to return false and not occur. ++ */ ++ RETAIN_PASSENGERS, ++ /** ++ * If the entity should not be dismounted if they are riding another entity. ++ *

      ++ * Note: ++ * Teleporting to a different world with this flag present while this entity is riding another entity will ++ * cause this teleportation to return false and not occur. ++ */ ++ RETAIN_VEHICLE, ++ /** ++ * Indicates that a player should not have their current open inventory closed when teleporting. ++ *

      ++ * Note: ++ * This option will be ignored when teleported to a different world. ++ */ ++ RETAIN_OPEN_INVENTORY; ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index fe3f59390ee45a289ae6dbb398ce7954fab717d5..b39ade088062c5e636915f09b7094bc27bac1fcf 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -126,10 +126,32 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * + * @param yaw the yaw + * @param pitch the pitch +- * @throws UnsupportedOperationException if used for players + */ + public void setRotation(float yaw, float pitch); + ++ // Paper start - Teleport API ++ /** ++ * Teleports this entity to the given location. ++ * ++ * @param location New location to teleport this entity to ++ * @param teleportFlags Flags to be used in this teleportation ++ * @return true if the teleport was successful ++ */ ++ default boolean teleport(@NotNull Location location, @NotNull io.papermc.paper.entity.TeleportFlag @NotNull... teleportFlags) { ++ return this.teleport(location, TeleportCause.PLUGIN, teleportFlags); ++ } ++ ++ /** ++ * Teleports this entity to the given location. ++ * ++ * @param location New location to teleport this entity to ++ * @param cause The cause of this teleportation ++ * @param teleportFlags Flags to be used in this teleportation ++ * @return true if the teleport was successful ++ */ ++ boolean teleport(@NotNull Location location, @NotNull TeleportCause cause, @NotNull io.papermc.paper.entity.TeleportFlag @NotNull... teleportFlags); ++ // Paper end - Teleport API ++ + /** + * Teleports this entity to the given location. If this entity is riding a + * vehicle, it will be dismounted prior to teleportation. +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index db3a1e9170aeada5fe738975124861d79e82e2d1..7d39bf96ac7dd7530d236fc7bff5126b08a7d38a 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3561,6 +3561,45 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + String getClientBrandName(); + // Paper end + ++ // Paper start - Teleport API ++ /** ++ * Sets the player's rotation. ++ * ++ * @param yaw the yaw ++ * @param pitch the pitch ++ */ ++ void setRotation(float yaw, float pitch); ++ ++ /** ++ * Causes the player to look towards the given position. ++ * ++ * @param x x coordinate ++ * @param y y coordinate ++ * @param z z coordinate ++ * @param playerAnchor What part of the player should face the given position ++ */ ++ void lookAt(double x, double y, double z, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor); ++ ++ /** ++ * Causes the player to look towards the given position. ++ * ++ * @param position Position to look at in the player's current world ++ * @param playerAnchor What part of the player should face the given position ++ */ ++ default void lookAt(@NotNull io.papermc.paper.math.Position position, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor) { ++ this.lookAt(position.x(), position.y(), position.z(), playerAnchor); ++ } ++ ++ /** ++ * Causes the player to look towards the given entity. ++ * ++ * @param entity Entity to look at ++ * @param playerAnchor What part of the player should face the entity ++ * @param entityAnchor What part of the entity the player should face ++ */ ++ void lookAt(@NotNull org.bukkit.entity.Entity entity, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor, @NotNull io.papermc.paper.entity.LookAnchor entityAnchor); ++ // Paper end - Teleport API ++ + @NotNull + @Override + Spigot spigot(); +diff --git a/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java b/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java +index 2deae344c88920ab95eefd2f65df5c858e04750b..ccfb08af8c57ddac3062c2cec28d7ff428082709 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java +@@ -13,8 +13,14 @@ public class PlayerTeleportEvent extends PlayerMoveEvent { + private static final HandlerList handlers = new HandlerList(); + private TeleportCause cause = TeleportCause.UNKNOWN; + ++ // Paper start - Teleport API ++ private boolean dismounted = true; ++ private final java.util.Set teleportFlagSet; ++ // Paper end ++ + public PlayerTeleportEvent(@NotNull final Player player, @NotNull final Location from, @Nullable final Location to) { + super(player, from, to); ++ teleportFlagSet = java.util.Collections.emptySet(); // Paper - Teleport API + } + + public PlayerTeleportEvent(@NotNull final Player player, @NotNull final Location from, @Nullable final Location to, @NotNull final TeleportCause cause) { +@@ -23,6 +29,15 @@ public class PlayerTeleportEvent extends PlayerMoveEvent { + this.cause = cause; + } + ++ // Paper start - Teleport API ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PlayerTeleportEvent(@NotNull final Player player, @NotNull final Location from, @Nullable final Location to, @NotNull final TeleportCause cause, @NotNull java.util.Set teleportFlagSet) { ++ super(player, from, to); ++ this.teleportFlagSet = teleportFlagSet; ++ this.cause = cause; ++ } ++ // Paper end ++ + /** + * Gets the cause of this teleportation event + * +@@ -88,6 +103,30 @@ public class PlayerTeleportEvent extends PlayerMoveEvent { + UNKNOWN; + } + ++ // Paper start - Teleport API ++ /** ++ * Gets if the player will be dismounted in this teleportation. ++ * ++ * @return dismounted or not ++ * @deprecated dismounting on tp is no longer controlled by the server ++ */ ++ @Deprecated(forRemoval = true) ++ public boolean willDismountPlayer() { ++ return this.dismounted; ++ } ++ ++ /** ++ * Returns the relative teleportation flags used in this teleportation. ++ * This determines which axis the player will not lose their velocity in. ++ * ++ * @return an immutable set of relative teleportation flags ++ */ ++ @NotNull ++ public java.util.Set getRelativeTeleportationFlags() { ++ return this.teleportFlagSet; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api/0354-Add-EntityPortalReadyEvent.patch b/patches/api/0354-Add-EntityPortalReadyEvent.patch new file mode 100644 index 000000000000..042c707eb3f6 --- /dev/null +++ b/patches/api/0354-Add-EntityPortalReadyEvent.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 May 2021 04:30:53 -0700 +Subject: [PATCH] Add EntityPortalReadyEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityPortalReadyEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityPortalReadyEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bc5f0ed43f5d341ec551e48eecf2614cdfd52d79 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityPortalReadyEvent.java +@@ -0,0 +1,95 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.PortalType; ++import org.bukkit.World; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Called when an entity is ready to be teleported by a plugin. ++ * Currently, this is only called after the required ++ * ticks have passed for a Nether Portal. ++ *

      ++ * Cancelling this event resets the entity's readiness ++ * regarding the current portal. ++ */ ++@NullMarked ++public class EntityPortalReadyEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final PortalType portalType; ++ private @Nullable World targetWorld; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityPortalReadyEvent(final Entity entity, final @Nullable World targetWorld, final PortalType portalType) { ++ super(entity); ++ this.targetWorld = targetWorld; ++ this.portalType = portalType; ++ } ++ ++ /** ++ * Gets the world this portal will teleport to. ++ * Can be {@code null} if "allow-nether" is false in server.properties ++ * or if there is another situation where there is no world to teleport to. ++ *

      ++ * This world may be modified by later events such as {@link PlayerPortalEvent} ++ * or {@link EntityPortalEvent}. ++ * ++ * @return the world the portal will teleport the entity to. ++ */ ++ public @Nullable World getTargetWorld() { ++ return this.targetWorld; ++ } ++ ++ /** ++ * Sets the world this portal will teleport to. A {@code null} value ++ * will essentially cancel the teleport and prevent further events ++ * such as {@link PlayerPortalEvent} from firing. ++ *

      ++ * This world may be modified by later events such as {@link PlayerPortalEvent} ++ * or {@link EntityPortalEvent}. ++ * ++ * @param targetWorld the world ++ */ ++ public void setTargetWorld(final @Nullable World targetWorld) { ++ this.targetWorld = targetWorld; ++ } ++ ++ /** ++ * Gets the portal type for this event. ++ * ++ * @return the portal type ++ */ ++ public PortalType getPortalType() { ++ return this.portalType; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0355-Custom-Chat-Completion-Suggestions-API.patch b/patches/api/0355-Custom-Chat-Completion-Suggestions-API.patch new file mode 100644 index 000000000000..5be45fe69224 --- /dev/null +++ b/patches/api/0355-Custom-Chat-Completion-Suggestions-API.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sat, 30 Jul 2022 11:23:11 -0400 +Subject: [PATCH] Custom Chat Completion Suggestions API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 7d39bf96ac7dd7530d236fc7bff5126b08a7d38a..460ac4d102f3e2f0162fd1e489b0866b74f776f1 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3445,6 +3445,31 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void sendOpLevel(byte level); + // Paper end - sendOpLevel API + ++ // Paper start - custom chat completions API ++ /** ++ * Adds custom chat completion suggestions that the client will ++ * suggest when typing in chat. ++ * ++ * @param completions custom completions ++ * @deprecated use {@link #addCustomChatCompletions(Collection)} ++ */ ++ @Deprecated(since = "1.20.1") ++ void addAdditionalChatCompletions(@NotNull java.util.Collection completions); ++ ++ /** ++ * Removes custom chat completion suggestions that the client ++ * suggests when typing in chat. ++ * ++ * Note: this only applies to previously added custom completions, ++ * online player names are always suggested and cannot be removed. ++ * ++ * @param completions custom completions ++ * @deprecated use {@link #addCustomChatCompletions(Collection)} ++ */ ++ @Deprecated(since = "1.20.1") ++ void removeAdditionalChatCompletions(@NotNull java.util.Collection completions); ++ // Paper end - custom chat completions API ++ + // Spigot start + public class Spigot extends Entity.Spigot { + diff --git a/patches/api/0356-Collision-API.patch b/patches/api/0356-Collision-API.patch new file mode 100644 index 000000000000..0248530e5015 --- /dev/null +++ b/patches/api/0356-Collision-API.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 6 Oct 2021 20:10:36 -0400 +Subject: [PATCH] Collision API + + +diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bukkit/RegionAccessor.java +index 44ee56a5956cc17194c767a0c1071a2abffe818a..43dd6c59cceba12f27e6b265acc3ad97eea37abd 100644 +--- a/src/main/java/org/bukkit/RegionAccessor.java ++++ b/src/main/java/org/bukkit/RegionAccessor.java +@@ -493,5 +493,15 @@ public interface RegionAccessor extends Keyed { // Paper + * @return whether a line of sight exists between {@code from} and {@code to} + */ + public boolean lineOfSightExists(@NotNull Location from, @NotNull Location to); ++ ++ /** ++ * Checks if the world collides with the given boundingbox. ++ * This will check for any colliding hard entities (boats, shulkers) / worldborder / blocks. ++ * Does not load chunks that are within the bounding box. ++ * ++ * @param boundingBox the box to check collisions in ++ * @return collides or not ++ */ ++ boolean hasCollisionsIn(@NotNull org.bukkit.util.BoundingBox boundingBox); + // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index b39ade088062c5e636915f09b7094bc27bac1fcf..2b4058dace5d071f60a9629f81c2323ee8c6d109 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -1023,4 +1023,26 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + boolean isInPowderedSnow(); + // Paper end ++ ++ // Paper start - Collision API ++ /** ++ * Checks for any collisions with the entity's bounding box at the provided location. ++ * This will check for any colliding entities (boats, shulkers) / worldborder / blocks. ++ * Does not load chunks that are within the bounding box at the specified location. ++ * ++ * @param location the location to check collisions in ++ * @return collides or not ++ */ ++ boolean collidesAt(@NotNull Location location); ++ ++ /** ++ * This checks using the given boundingbox as the entity's boundingbox if the entity would collide with anything. ++ * This will check for any colliding entities (boats, shulkers) / worldborder / blocks. ++ * Does not load chunks that are within the bounding box. ++ * ++ * @param boundingBox the box to check collisions in ++ * @return collides or not ++ */ ++ boolean wouldCollideUsing(@NotNull BoundingBox boundingBox); ++ // Paper end - Collision API + } diff --git a/patches/api/0357-Block-Ticking-API.patch b/patches/api/0357-Block-Ticking-API.patch new file mode 100644 index 000000000000..fa6fe2a810e2 --- /dev/null +++ b/patches/api/0357-Block-Ticking-API.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 26 Dec 2021 13:23:52 -0500 +Subject: [PATCH] Block Ticking API + + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index b47804da74e143b8d3665c3ec7dd9d858eee6a6b..b7530e7f389fdc6d815bdff0949fca4b14298c07 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -593,6 +593,41 @@ public interface Block extends Metadatable, Translatable, net.kyori.adventure.tr + * @return true if the block was destroyed + */ + boolean breakNaturally(@NotNull ItemStack tool, boolean triggerEffect, boolean dropExperience); ++ ++ /** ++ * Causes the block to be ticked, this is different from {@link Block#randomTick()}, ++ * in that it is usually scheduled to occur, for example ++ * redstone components being activated, sand falling, etc. ++ *

      ++ * This method may directly fire events relating to block ticking. ++ * ++ * @see #fluidTick() ++ */ ++ void tick(); ++ ++ /** ++ * Causes the fluid to be ticked, this is different from {@link Block#randomTick()}, ++ * in that it is usually scheduled to occur, for example ++ * causing waterlogged blocks to spread. ++ *

      ++ * This method may directly fire events relating to fluid ticking. ++ * ++ * @see #tick() ++ */ ++ void fluidTick(); ++ ++ /** ++ * Causes the block to be ticked randomly. ++ * This has a chance to execute naturally if {@link BlockData#isRandomlyTicked()} is true. ++ *

      ++ * For certain blocks, this behavior may be the same as {@link Block#tick()}. ++ *

      ++ * This method may directly fire events relating to block random ticking. ++ * ++ * @see #tick() ++ * @see #fluidTick() ++ */ ++ void randomTick(); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/block/data/BlockData.java b/src/main/java/org/bukkit/block/data/BlockData.java +index 890a511355dd3f2aa9330fdc72c0fb4b3e44e5cb..54664651f34311e95f6c2dcfd93e58477beda8c2 100644 +--- a/src/main/java/org/bukkit/block/data/BlockData.java ++++ b/src/main/java/org/bukkit/block/data/BlockData.java +@@ -295,4 +295,14 @@ public interface BlockData extends Cloneable { + */ + float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants); + // Paper end - destroy speed API ++ ++ // Paper start - Tick API ++ /** ++ * Gets if this block is ticked randomly in the world. ++ * The blocks current state may change this value. ++ * ++ * @return is ticked randomly ++ */ ++ boolean isRandomlyTicked(); ++ // Paper end - Tick API + } diff --git a/patches/api/0358-Add-NamespacedKey-biome-methods.patch b/patches/api/0358-Add-NamespacedKey-biome-methods.patch new file mode 100644 index 000000000000..4eab10357b7e --- /dev/null +++ b/patches/api/0358-Add-NamespacedKey-biome-methods.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josh Roy <10731363+JRoy@users.noreply.github.com> +Date: Sun, 14 Aug 2022 12:22:54 -0400 +Subject: [PATCH] Add NamespacedKey biome methods + +Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 5be89089da4e8230dc7aa078712428189f38d9f9..3328ae3bab6b4929506a518d6426b81594b1b300 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -223,4 +223,37 @@ public interface UnsafeValues { + */ + @org.jetbrains.annotations.NotNull org.bukkit.attribute.Attributable getDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); + // Paper end ++ ++ // Paper start - namespaced key biome methods ++ /** ++ * Gets the {@link NamespacedKey} for the biome at the given location. ++ * ++ * @param accessor The {@link RegionAccessor} of the provided coordinates ++ * @param x X-coordinate of the block ++ * @param y Y-coordinate of the block ++ * @param z Z-coordinate of the block ++ * @deprecated custom biomes are properly supported in API now ++ * @return the biome's {@link NamespacedKey} ++ */ ++ @org.jetbrains.annotations.NotNull ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ NamespacedKey getBiomeKey(RegionAccessor accessor, int x, int y, int z); ++ ++ /** ++ * Sets the biome at the given location to a biome registered ++ * to the given {@link NamespacedKey}. If no biome by the given ++ * {@link NamespacedKey} exists, an {@link IllegalStateException} ++ * will be thrown. ++ * ++ * @param accessor The {@link RegionAccessor} of the provided coordinates ++ * @param x X-coordinate of the block ++ * @param y Y-coordinate of the block ++ * @param z Z-coordinate of the block ++ * @param biomeKey Biome key ++ * @deprecated custom biomes are properly supported in API now ++ * @throws IllegalStateException if no biome by the given key is registered. ++ */ ++ @Deprecated(since = "1.21.3", forRemoval = true) ++ void setBiomeKey(RegionAccessor accessor, int x, int y, int z, NamespacedKey biomeKey); ++ // Paper end - namespaced key biome methods + } diff --git a/patches/api/0359-Also-load-resources-from-LibraryLoader.patch b/patches/api/0359-Also-load-resources-from-LibraryLoader.patch new file mode 100644 index 000000000000..c2a41c2e53dc --- /dev/null +++ b/patches/api/0359-Also-load-resources-from-LibraryLoader.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nick Hensel +Date: Sun, 28 Aug 2022 23:44:18 +0200 +Subject: [PATCH] Also load resources from LibraryLoader + + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index de017d10db19ca7ca7f73ff0ac08fe6e1773d7dc..7e4f7cb2afbc145e532285c793573ad107bc3033 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -109,14 +109,35 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + + @Override + public URL getResource(String name) { +- return findResource(name); ++ // Paper start ++ URL resource = findResource(name); ++ if (resource == null && libraryLoader != null) { ++ return libraryLoader.getResource(name); ++ } ++ return resource; ++ // Paper end + } + + @Override + public Enumeration getResources(String name) throws IOException { +- return findResources(name); ++ // Paper start ++ java.util.ArrayList resources = new java.util.ArrayList<>(); ++ addEnumeration(resources, findResources(name)); ++ if (libraryLoader != null) { ++ addEnumeration(resources, libraryLoader.getResources(name)); ++ } ++ return Collections.enumeration(resources); ++ // Paper end + } + ++ // Paper start ++ private void addEnumeration(java.util.ArrayList list, Enumeration enumeration) { ++ while (enumeration.hasMoreElements()) { ++ list.add(enumeration.nextElement()); ++ } ++ } ++ // Paper end ++ + // Paper start + @Override + public Class loadClass(@NotNull String name, boolean resolve, boolean checkGlobal, boolean checkLibraries) throws ClassNotFoundException { diff --git a/patches/api/0360-Added-byte-array-serialization-deserialization-for-P.patch b/patches/api/0360-Added-byte-array-serialization-deserialization-for-P.patch new file mode 100644 index 000000000000..9b71f12681f6 --- /dev/null +++ b/patches/api/0360-Added-byte-array-serialization-deserialization-for-P.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nex +Date: Thu, 24 Feb 2022 16:28:08 +0100 +Subject: [PATCH] Added byte array serialization/deserialization for + PersistentDataContainers + + +diff --git a/src/main/java/org/bukkit/persistence/PersistentDataContainer.java b/src/main/java/org/bukkit/persistence/PersistentDataContainer.java +index 18fc4f1c7151bfdeed32a52cf5050a76ebc391d6..decf3b1949d4653a9fb01684b93ff91048137076 100644 +--- a/src/main/java/org/bukkit/persistence/PersistentDataContainer.java ++++ b/src/main/java/org/bukkit/persistence/PersistentDataContainer.java +@@ -184,4 +184,39 @@ public interface PersistentDataContainer { + */ + @NotNull + PersistentDataAdapterContext getAdapterContext(); ++ ++ // Paper start - byte array serialization ++ /** ++ * Serialize this {@link PersistentDataContainer} instance to a ++ * byte array. ++ * ++ * @return a binary representation of this container ++ * @throws java.io.IOException if we fail to write this container to a byte array ++ */ ++ byte @NotNull [] serializeToBytes() throws java.io.IOException; ++ ++ /** ++ * Read values from a serialised byte array into this ++ * {@link PersistentDataContainer} instance. ++ * ++ * @param bytes the byte array to read from ++ * @param clear if true, this {@link PersistentDataContainer} instance ++ * will be cleared before reading ++ * @throws java.io.IOException if the byte array has an invalid format ++ */ ++ void readFromBytes(byte @NotNull [] bytes, boolean clear) throws java.io.IOException; ++ ++ /** ++ * Read values from a serialised byte array into this ++ * {@link PersistentDataContainer} instance. ++ * This method has the same effect as ++ * PersistentDataContainer#readFromBytes(bytes, true) ++ * ++ * @param bytes the byte array to read from ++ * @throws java.io.IOException if the byte array has an invalid format ++ */ ++ default void readFromBytes(final byte @NotNull [] bytes) throws java.io.IOException { ++ this.readFromBytes(bytes, true); ++ } ++ // Paper end - byte array serialization + } diff --git a/patches/api/0361-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch b/patches/api/0361-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch new file mode 100644 index 000000000000..08a6f15997d4 --- /dev/null +++ b/patches/api/0361-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Thu, 22 Sep 2022 07:04:30 +0100 +Subject: [PATCH] Expose codepoint limit in YamlConfigOptions, and increase + default + + +diff --git a/src/main/java/org/bukkit/configuration/file/YamlConfiguration.java b/src/main/java/org/bukkit/configuration/file/YamlConfiguration.java +index b76cf252f44ca858d96b1af52cb38bc801d5f3c1..ed81e850b22b83ac872707daf3c7d5d0cac6176b 100644 +--- a/src/main/java/org/bukkit/configuration/file/YamlConfiguration.java ++++ b/src/main/java/org/bukkit/configuration/file/YamlConfiguration.java +@@ -98,6 +98,7 @@ public class YamlConfiguration extends FileConfiguration { + public void loadFromString(@NotNull String contents) throws InvalidConfigurationException { + Preconditions.checkArgument(contents != null, "Contents cannot be null"); + yamlLoaderOptions.setProcessComments(options().parseComments()); ++ yamlLoaderOptions.setCodePointLimit(options().codePointLimit()); // Paper + + MappingNode node; + try (Reader reader = new UnicodeReader(new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)))) { +diff --git a/src/main/java/org/bukkit/configuration/file/YamlConfigurationOptions.java b/src/main/java/org/bukkit/configuration/file/YamlConfigurationOptions.java +index 3f69667e6bb89eb1cfdf43598be73640063b2006..6e43fbbe7b43ab5700bb0066b40337b2e47f6c6a 100644 +--- a/src/main/java/org/bukkit/configuration/file/YamlConfigurationOptions.java ++++ b/src/main/java/org/bukkit/configuration/file/YamlConfigurationOptions.java +@@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable; + public class YamlConfigurationOptions extends FileConfigurationOptions { + private int indent = 2; + private int width = 80; ++ private int codePointLimit = Integer.MAX_VALUE; // Paper - use upstream's default from YamlConfiguration + + protected YamlConfigurationOptions(@NotNull YamlConfiguration configuration) { + super(configuration); +@@ -122,4 +123,29 @@ public class YamlConfigurationOptions extends FileConfigurationOptions { + this.width = value; + return this; + } ++ ++ // Paper start ++ /** ++ * Gets the maximum code point limit, that being, the maximum length of the document ++ * in which the loader will read ++ * ++ * @return The current value ++ */ ++ public int codePointLimit() { ++ return codePointLimit; ++ } ++ ++ /** ++ * Sets the maximum code point limit, that being, the maximum length of the document ++ * in which the loader will read ++ * ++ * @param codePointLimit new codepoint limit ++ * @return This object, for chaining ++ */ ++ @NotNull ++ public YamlConfigurationOptions codePointLimit(int codePointLimit) { ++ this.codePointLimit = codePointLimit; ++ return this; ++ } ++ // Paper end + } diff --git a/patches/api/0362-Add-getDrops-to-BlockState.patch b/patches/api/0362-Add-getDrops-to-BlockState.patch new file mode 100644 index 000000000000..bb0a24c65e63 --- /dev/null +++ b/patches/api/0362-Add-getDrops-to-BlockState.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MelnCat +Date: Fri, 12 Aug 2022 23:24:53 -0700 +Subject: [PATCH] Add getDrops to BlockState + +Originally added isPreferredTool to BlockData but +upstream added that. + +diff --git a/src/main/java/org/bukkit/block/BlockState.java b/src/main/java/org/bukkit/block/BlockState.java +index ee4cbbc584ec1a10c62464a7abb3ea5da656ffc0..3bcdb02f8f6081dcd7f15dc86587d4b790aa4496 100644 +--- a/src/main/java/org/bukkit/block/BlockState.java ++++ b/src/main/java/org/bukkit/block/BlockState.java +@@ -253,5 +253,41 @@ public interface BlockState extends Metadatable { + * @return true if collidable + */ + boolean isCollidable(); ++ ++ /** ++ * Returns an immutable list of items which would drop by destroying this block state. ++ * ++ * @return an immutable list of dropped items for the block state ++ * @throws IllegalStateException if this block state is not placed ++ */ ++ @NotNull ++ default java.util.@org.jetbrains.annotations.Unmodifiable Collection getDrops() { ++ return this.getDrops(null); ++ } ++ ++ /** ++ * Returns an immutable list of items which would drop by destroying this block state ++ * with a specific tool ++ * ++ * @param tool The tool or item in hand used for digging ++ * @return an immutable list of dropped items for the block state ++ * @throws IllegalStateException if this block state is not placed ++ */ ++ @NotNull ++ default java.util.@org.jetbrains.annotations.Unmodifiable Collection getDrops(@Nullable org.bukkit.inventory.ItemStack tool) { ++ return this.getDrops(tool, null); ++ } ++ ++ /** ++ * Returns an immutable list of items which would drop by the entity destroying this ++ * block state with a specific tool ++ * ++ * @param tool The tool or item in hand used for digging ++ * @param entity the entity destroying the block ++ * @return an immutable list of dropped items for the block state ++ * @throws IllegalStateException if this block state is not placed ++ */ ++ @NotNull ++ java.util.@org.jetbrains.annotations.Unmodifiable Collection getDrops(@Nullable org.bukkit.inventory.ItemStack tool, @Nullable org.bukkit.entity.Entity entity); + // Paper end + } diff --git a/patches/api/0363-Add-PlayerInventorySlotChangeEvent.patch b/patches/api/0363-Add-PlayerInventorySlotChangeEvent.patch new file mode 100644 index 000000000000..d0cadabced5e --- /dev/null +++ b/patches/api/0363-Add-PlayerInventorySlotChangeEvent.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jakub Zacek +Date: Sun, 24 Apr 2022 22:56:31 +0200 +Subject: [PATCH] Add PlayerInventorySlotChangeEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerInventorySlotChangeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerInventorySlotChangeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f3a54ed7efabaa0f6413e1598f14e2770a46440d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerInventorySlotChangeEvent.java +@@ -0,0 +1,98 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.Inventory; ++import org.bukkit.inventory.ItemStack; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when a slot contents change in a player's inventory. ++ */ ++@NullMarked ++public class PlayerInventorySlotChangeEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final int rawSlot; ++ private final int slot; ++ private final ItemStack oldItemStack; ++ private final ItemStack newItemStack; ++ private boolean triggerAdvancements = true; ++ ++ public PlayerInventorySlotChangeEvent(final Player player, final int rawSlot, final ItemStack oldItemStack, final ItemStack newItemStack) { ++ super(player); ++ this.rawSlot = rawSlot; ++ this.slot = player.getOpenInventory().convertSlot(rawSlot); ++ this.oldItemStack = oldItemStack; ++ this.newItemStack = newItemStack; ++ } ++ ++ /** ++ * The raw slot number that was changed. ++ * ++ * @return The raw slot number. ++ */ ++ public int getRawSlot() { ++ return this.rawSlot; ++ } ++ ++ /** ++ * The slot number that was changed, ready for passing to ++ * {@link Inventory#getItem(int)}. Note that there may be two slots with ++ * the same slot number, since a view links two different inventories. ++ *

      ++ * If no inventory is opened, internal crafting view is used for conversion. ++ * ++ * @return The slot number. ++ */ ++ public int getSlot() { ++ return this.slot; ++ } ++ ++ /** ++ * Clone of ItemStack that was in the slot before the change. ++ * ++ * @return The old ItemStack in the slot. ++ */ ++ public ItemStack getOldItemStack() { ++ return this.oldItemStack; ++ } ++ ++ /** ++ * Clone of ItemStack that is in the slot after the change. ++ * ++ * @return The new ItemStack in the slot. ++ */ ++ public ItemStack getNewItemStack() { ++ return this.newItemStack; ++ } ++ ++ /** ++ * Gets whether the slot change advancements will be triggered. ++ * ++ * @return Whether the slot change advancements will be triggered. ++ */ ++ public boolean shouldTriggerAdvancements() { ++ return this.triggerAdvancements; ++ } ++ ++ /** ++ * Sets whether the slot change advancements will be triggered. ++ * ++ * @param triggerAdvancements Whether the slot change advancements will be triggered. ++ */ ++ public void setShouldTriggerAdvancements(final boolean triggerAdvancements) { ++ this.triggerAdvancements = triggerAdvancements; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0364-Elder-Guardian-appearance-API.patch b/patches/api/0364-Elder-Guardian-appearance-API.patch new file mode 100644 index 000000000000..a0e9bd6ffd62 --- /dev/null +++ b/patches/api/0364-Elder-Guardian-appearance-API.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Tue, 11 Oct 2022 20:38:47 +0300 +Subject: [PATCH] Elder Guardian appearance API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 460ac4d102f3e2f0162fd1e489b0866b74f776f1..c676524280cc091998859fe1945d06bb7f26560d 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3625,6 +3625,24 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void lookAt(@NotNull org.bukkit.entity.Entity entity, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor, @NotNull io.papermc.paper.entity.LookAnchor entityAnchor); + // Paper end - Teleport API + ++ // Paper start ++ /** ++ * Displays elder guardian effect with a sound ++ * ++ * @see #showElderGuardian(boolean) ++ */ ++ default void showElderGuardian() { ++ showElderGuardian(false); ++ } ++ ++ /** ++ * Displays elder guardian effect and optionally plays a sound ++ * ++ * @param silent whether sound should be silenced ++ */ ++ void showElderGuardian(boolean silent); ++ // Paper end ++ + @NotNull + @Override + Spigot spigot(); diff --git a/patches/api/0365-Add-EquipmentSlot-convenience-methods.patch b/patches/api/0365-Add-EquipmentSlot-convenience-methods.patch new file mode 100644 index 000000000000..f7e2301f315e --- /dev/null +++ b/patches/api/0365-Add-EquipmentSlot-convenience-methods.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Sun, 16 Oct 2022 15:28:49 +0300 +Subject: [PATCH] Add EquipmentSlot convenience methods + + +diff --git a/src/main/java/org/bukkit/inventory/EquipmentSlot.java b/src/main/java/org/bukkit/inventory/EquipmentSlot.java +index 5642d8af60b6649497aba9b0f6ab7bba7702b9ee..c1c69ba4c361740f0ad422a7840a7f0f055c186a 100644 +--- a/src/main/java/org/bukkit/inventory/EquipmentSlot.java ++++ b/src/main/java/org/bukkit/inventory/EquipmentSlot.java +@@ -33,4 +33,42 @@ public enum EquipmentSlot { + public EquipmentSlotGroup getGroup() { + return group.get(); + } ++ // Paper start ++ /** ++ * Checks whether this equipment slot is a hand: ++ * either {@link #HAND} or {@link #OFF_HAND} ++ * ++ * @return whether this is a hand slot ++ */ ++ public boolean isHand() { ++ return this == HAND || this == OFF_HAND; ++ } ++ ++ /** ++ * Gets the opposite hand ++ * ++ * @return the opposite hand ++ * @throws IllegalArgumentException if this equipment slot is not a hand ++ * @see #isHand() ++ */ ++ public @NotNull EquipmentSlot getOppositeHand() { ++ return switch (this) { ++ case HAND -> OFF_HAND; ++ case OFF_HAND -> HAND; ++ default -> throw new IllegalArgumentException("Unable to determine an opposite hand for equipment slot: " + name()); ++ }; ++ } ++ ++ /** ++ * Checks whether this equipment slot ++ * is one of the armor slots: ++ * {@link #HEAD}, {@link #CHEST}, ++ * {@link #LEGS}, {@link #FEET}, or {@link #BODY} ++ * ++ * @return whether this is an armor slot ++ */ ++ public boolean isArmor() { ++ return this == HEAD || this == CHEST || this == LEGS || this == FEET || this == BODY; ++ } ++ // Paper end + } diff --git a/patches/api/0366-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch b/patches/api/0366-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch new file mode 100644 index 000000000000..b66bb330f3c9 --- /dev/null +++ b/patches/api/0366-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Tue, 11 Oct 2022 22:35:56 +0300 +Subject: [PATCH] Add LivingEntity#swingHand(EquipmentSlot) convenience method + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 292b8d0370723f019fb90a8b86300fa631bee683..be91821c47ff582576eb845610c3bde7e65ed8b3 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1341,4 +1341,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + @Deprecated + void setHurtDirection(float hurtDirection); + // Paper end - hurt direction API ++ ++ // Paper start - swing hand API ++ /** ++ * Makes this entity swing their hand. ++ * ++ *

      This method does nothing if this entity does not ++ * have an animation for swinging their hand. ++ * ++ * @param hand hand to be swung, either {@link org.bukkit.inventory.EquipmentSlot#HAND} or {@link org.bukkit.inventory.EquipmentSlot#OFF_HAND} ++ * @throws IllegalArgumentException if invalid hand is passed ++ */ ++ default void swingHand(@NotNull org.bukkit.inventory.EquipmentSlot hand) { ++ com.google.common.base.Preconditions.checkArgument(hand != null && hand.isHand(), String.format("Expected a valid hand, got \"%s\" instead!", hand)); ++ if (hand == org.bukkit.inventory.EquipmentSlot.HAND) { ++ this.swingMainHand(); ++ } else { ++ this.swingOffHand(); ++ } ++ } ++ // Paper end - swing hand API + } diff --git a/patches/api/0367-Add-entity-knockback-API.patch b/patches/api/0367-Add-entity-knockback-API.patch new file mode 100644 index 000000000000..73dd5f365870 --- /dev/null +++ b/patches/api/0367-Add-entity-knockback-API.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MelnCat +Date: Sun, 16 Oct 2022 12:10:00 -0700 +Subject: [PATCH] Add entity knockback API + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index be91821c47ff582576eb845610c3bde7e65ed8b3..8ee3f82049541041623c10940bdda1746200b1e6 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1361,4 +1361,18 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + } + } + // Paper end - swing hand API ++ ++ // Paper start - knockback API ++ /** ++ * Knocks back this entity from a specific direction with a specified strength. Mechanics such ++ * as knockback resistance will be factored in. ++ * ++ * The direction specified in this method will be the direction of the source of the knockback, ++ * so the entity will be pushed in the opposite direction. ++ * @param strength The strength of the knockback. Must be greater than 0. ++ * @param directionX The relative x position of the knockback source direction ++ * @param directionZ The relative z position of the knockback source direction ++ */ ++ void knockback(double strength, double directionX, double directionZ); ++ // Paper end - knockback API + } diff --git a/patches/api/0368-Added-EntityToggleSitEvent.patch b/patches/api/0368-Added-EntityToggleSitEvent.patch new file mode 100644 index 000000000000..435450daf4d6 --- /dev/null +++ b/patches/api/0368-Added-EntityToggleSitEvent.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: KyGuy2002 +Date: Fri, 11 Mar 2022 15:33:10 +0000 +Subject: [PATCH] Added EntityToggleSitEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityToggleSitEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityToggleSitEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ab1955bc61114798fe71cffa6fae3ee0beb3bd2a +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityToggleSitEvent.java +@@ -0,0 +1,54 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Is called when an entity sits down or stands up. ++ */ ++@NullMarked ++public class EntityToggleSitEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final boolean isSitting; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityToggleSitEvent(final Entity entity, final boolean isSitting) { ++ super(entity); ++ this.isSitting = isSitting; ++ } ++ ++ /** ++ * Gets the new sitting state that the entity will change to. ++ * ++ * @return If it's going to sit or not. ++ */ ++ public boolean getSittingState() { ++ return this.isSitting; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0369-Add-Moving-Piston-API.patch b/patches/api/0369-Add-Moving-Piston-API.patch new file mode 100644 index 000000000000..e93ac68dd268 --- /dev/null +++ b/patches/api/0369-Add-Moving-Piston-API.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sat, 4 Dec 2021 13:29:45 -0500 +Subject: [PATCH] Add Moving Piston API + + +diff --git a/src/main/java/io/papermc/paper/block/MovingPiston.java b/src/main/java/io/papermc/paper/block/MovingPiston.java +new file mode 100644 +index 0000000000000000000000000000000000000000..962b92d487b3c442d2fe8b665ec3b2d375aaa9aa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/block/MovingPiston.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.block; ++ ++import org.bukkit.block.BlockFace; ++import org.bukkit.block.TileState; ++import org.bukkit.block.data.BlockData; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++public interface MovingPiston extends TileState { ++ ++ /** ++ * Gets the block that is being pushed ++ * ++ * @return the pushed block ++ */ ++ BlockData getMovingBlock(); ++ ++ /** ++ * The direction that the current moving piston ++ * is pushing/pulling a block in. ++ * ++ * @return the direction ++ */ ++ BlockFace getDirection(); ++ ++ /** ++ * Gets if the piston is extending or not. ++ * Returns false if the piston is retracting. ++ * ++ * @return is extending or not ++ */ ++ boolean isExtending(); ++ ++ /** ++ * Returns if this moving piston represents the main piston head ++ * from the original piston. ++ * ++ * @return is the piston head or not ++ */ ++ boolean isPistonHead(); ++ ++} diff --git a/patches/api/0370-Add-PrePlayerAttackEntityEvent.patch b/patches/api/0370-Add-PrePlayerAttackEntityEvent.patch new file mode 100644 index 000000000000..1caf6f769686 --- /dev/null +++ b/patches/api/0370-Add-PrePlayerAttackEntityEvent.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 18 Sep 2022 13:10:28 -0400 +Subject: [PATCH] Add PrePlayerAttackEntityEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PrePlayerAttackEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PrePlayerAttackEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a6c5818bcdd8de5f2d0e9bf72d1e3816652e0199 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PrePlayerAttackEntityEvent.java +@@ -0,0 +1,90 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when the player tries to attack an entity. ++ *

      ++ * This occurs before any of the damage logic, so cancelling this event ++ * will prevent any sort of sounds from being played when attacking. ++ *

      ++ * This event will fire as cancelled for certain entities, with {@link PrePlayerAttackEntityEvent#willAttack()} being false ++ * to indicate that this entity will not actually be attacked. ++ *

      ++ * Note: there may be other factors (invulnerability, etc.) that will prevent this entity from being attacked that this event will not cover ++ */ ++@NullMarked ++public class PrePlayerAttackEntityEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity attacked; ++ private final boolean willAttack; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PrePlayerAttackEntityEvent(final Player player, final Entity attacked, final boolean willAttack) { ++ super(player); ++ this.attacked = attacked; ++ this.willAttack = willAttack; ++ this.cancelled = !willAttack; ++ } ++ ++ /** ++ * Gets the entity that was attacked in this event. ++ * ++ * @return entity that was attacked ++ */ ++ public Entity getAttacked() { ++ return this.attacked; ++ } ++ ++ /** ++ * Gets if this entity will be attacked normally. ++ * Entities like falling sand will return {@code false} because ++ * their entity type does not allow them to be attacked. ++ *

      ++ * Note: there may be other factors (invulnerability, etc.) that will prevent this entity from being attacked that this event will not cover ++ * ++ * @return if the entity will actually be attacked ++ */ ++ public boolean willAttack() { ++ return this.willAttack; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Sets if this attack should be cancelled, note if {@link PrePlayerAttackEntityEvent#willAttack()} returns false ++ * this event will always be cancelled. ++ * ++ * @param cancel {@code true} if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ if (!this.willAttack) { ++ return; ++ } ++ ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0371-Add-Player-Warden-Warning-API.patch b/patches/api/0371-Add-Player-Warden-Warning-API.patch new file mode 100644 index 000000000000..3b23da22254f --- /dev/null +++ b/patches/api/0371-Add-Player-Warden-Warning-API.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dawon +Date: Sat, 15 Oct 2022 00:46:32 +0200 +Subject: [PATCH] Add Player Warden Warning API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index c676524280cc091998859fe1945d06bb7f26560d..8873f0eb1451cd4e8801b75e8bd477eae588e73b 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3641,6 +3641,59 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param silent whether sound should be silenced + */ + void showElderGuardian(boolean silent); ++ ++ /** ++ * Returns the player's cooldown in ticks until the next Warden warning can occur. ++ * ++ * @return ticks until next Warden warning can occur. 0 means there is no cooldown left. ++ */ ++ int getWardenWarningCooldown(); ++ ++ /** ++ * Sets the player's cooldown in ticks until next Warden warning can occur. ++ * ++ * @param cooldown ticks until next Warden warning can occur. 0 means there is no cooldown left. Values less than 0 are set to 0. ++ */ ++ void setWardenWarningCooldown(int cooldown); ++ ++ /** ++ * Returns time since last Warden warning in ticks. ++ * ++ * @return ticks since last Warden warning ++ */ ++ int getWardenTimeSinceLastWarning(); ++ ++ /** ++ * Sets time since last Warden warning in ticks. ++ * ++ * @param time ticks since last Warden warning ++ */ ++ void setWardenTimeSinceLastWarning(int time); ++ ++ /** ++ * Returns the player's current Warden warning level. ++ * ++ * @return current Warden warning level ++ */ ++ int getWardenWarningLevel(); ++ ++ /** ++ * Sets the player's Warden warning level. ++ *

      ++ * Note: This will not actually spawn the Warden. ++ * Even if the warning level is over threshold, the player still needs to activate a Shrieker in order to summon the Warden. ++ * ++ * @param warningLevel player's Warden warning level. The warning level is internally limited to valid values. ++ */ ++ void setWardenWarningLevel(int warningLevel); ++ ++ /** ++ * Increases the player's Warden warning level if possible and not on cooldown. ++ *

      ++ * Note: This will not actually spawn the Warden. ++ * Even if the warning level is over threshold, the player still needs to activate a Shrieker in order to summon the Warden. ++ */ ++ void increaseWardenWarningLevel(); + // Paper end + + @NotNull diff --git a/patches/api/0372-More-vanilla-friendly-methods-to-update-trades.patch b/patches/api/0372-More-vanilla-friendly-methods-to-update-trades.patch new file mode 100644 index 000000000000..b56f34f9d14d --- /dev/null +++ b/patches/api/0372-More-vanilla-friendly-methods-to-update-trades.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> +Date: Sun, 16 Oct 2022 15:58:38 +0200 +Subject: [PATCH] More vanilla friendly methods to update trades + + +diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java +index 163f1afde2e04fdf4dddb894da62b301b52ed539..bc7137eb802d4613d042fba5fd97eca54a6eea29 100644 +--- a/src/main/java/org/bukkit/entity/Villager.java ++++ b/src/main/java/org/bukkit/entity/Villager.java +@@ -64,8 +64,11 @@ public interface Villager extends AbstractVillager { + * A villager with a level of 1 and no experience is liable to lose its + * profession. + * ++ * This doesn't update the trades of this villager. ++ * + * @param level the new level + * @throws IllegalArgumentException if level not between [1, 5] ++ * @see #increaseLevel(int) + */ + public void setVillagerLevel(int level); + +@@ -85,6 +88,34 @@ public interface Villager extends AbstractVillager { + public void setVillagerExperience(int experience); + + // Paper start ++ /** ++ * Increases the level of this villager. ++ * The villager will also unlock new recipes unlike the raw ++ * method {@link #setVillagerLevel(int)}. ++ *

      ++ * A villager with a level of 1 and no experience is liable to lose its ++ * profession. ++ *

      ++ * A master villager has a level of 5 in its profession and ++ * will unlock 10 trades (2 per level). ++ * ++ * @param amount The amount of level ++ * @return Whether trades are unlocked ++ * @throws IllegalArgumentException if current level plus the amount ++ * isn't between [1, 5] or the amount isn't positive ++ * @see #setVillagerLevel(int) ++ */ ++ boolean increaseLevel(int amount); ++ ++ /** ++ * Gives to this villager some potential new trades ++ * based to its profession and level. ++ * @param amount The amount of trades to give ++ * @return Whether trades are added ++ * @throws IllegalArgumentException if the amount isn't positive ++ */ ++ boolean addTrades(int amount); ++ + /** + * Gets the amount of times a villager has restocked their trades today + * @return The amount of trade restocks. diff --git a/patches/api/0373-Add-paper-dumplisteners-command.patch b/patches/api/0373-Add-paper-dumplisteners-command.patch new file mode 100644 index 000000000000..8ad550e4eede --- /dev/null +++ b/patches/api/0373-Add-paper-dumplisteners-command.patch @@ -0,0 +1,175 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Warrior <50800980+Warriorrrr@users.noreply.github.com> +Date: Sat, 19 Nov 2022 19:46:44 +0100 +Subject: [PATCH] Add /paper dumplisteners command + + +diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java +index a3ad690691eb5537a565d7ba684354acfec5ee2d..157617933a772451f6c073d97afaf305769b4d40 100644 +--- a/src/main/java/co/aikar/timings/TimedEventExecutor.java ++++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java +@@ -84,4 +84,10 @@ public class TimedEventExecutor implements EventExecutor { + executor.execute(listener, event); + } + } ++ ++ @Override ++ @NotNull ++ public String toString() { ++ return "TimedEventExecutor['" + this.executor.toString() + "']"; ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +index 5a702481d28d90cb503faad0d9b9c3231bbff940..2a169d2f6fdada6c361ee4291abb38446d45d654 100644 +--- a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java ++++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java +@@ -18,10 +18,12 @@ public class MethodHandleEventExecutor implements EventExecutor { + + private final Class eventClass; + private final MethodHandle handle; ++ private final @Nullable Method method; + + public MethodHandleEventExecutor(final Class eventClass, final MethodHandle handle) { + this.eventClass = eventClass; + this.handle = handle; ++ this.method = null; + } + + public MethodHandleEventExecutor(final Class eventClass, final Method m) { +@@ -32,6 +34,7 @@ public class MethodHandleEventExecutor implements EventExecutor { + } catch (final IllegalAccessException e) { + throw new AssertionError("Unable to set accessible", e); + } ++ this.method = m; + } + + @Override +@@ -43,4 +46,9 @@ public class MethodHandleEventExecutor implements EventExecutor { + SneakyThrow.sneaky(t); + } + } ++ ++ @Override ++ public String toString() { ++ return "MethodHandleEventExecutor['" + this.method + "']"; ++ } + } +diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +index bbdb5b472df116b71c459bdc6cc4b74267ea0f5e..e98962b6c6651c580684d8580484de87b5ad65a5 100644 +--- a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java ++++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java +@@ -19,6 +19,7 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { + + private final Class eventClass; + private final MethodHandle handle; ++ private final Method method; + + public StaticMethodHandleEventExecutor(final Class eventClass, final Method m) { + Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m); +@@ -30,6 +31,7 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { + } catch (final IllegalAccessException e) { + throw new AssertionError("Unable to set accessible", e); + } ++ this.method = m; + } + + @Override +@@ -41,4 +43,9 @@ public class StaticMethodHandleEventExecutor implements EventExecutor { + SneakyThrow.sneaky(throwable); + } + } ++ ++ @Override ++ public String toString() { ++ return "StaticMethodHandleEventExecutor['" + this.method + "']"; ++ } + } +diff --git a/src/main/java/org/bukkit/event/HandlerList.java b/src/main/java/org/bukkit/event/HandlerList.java +index ed78cca71f83b296d082d0af147ca8d622c7606a..2292bd460ce2be113beb4ba6b4eb19350060f01c 100644 +--- a/src/main/java/org/bukkit/event/HandlerList.java ++++ b/src/main/java/org/bukkit/event/HandlerList.java +@@ -33,6 +33,13 @@ public class HandlerList { + */ + private static ArrayList allLists = new ArrayList(); + ++ // Paper start ++ /** ++ * Event types which have instantiated a {@link HandlerList}. ++ */ ++ private static final java.util.Set EVENT_TYPES = java.util.concurrent.ConcurrentHashMap.newKeySet(); ++ // Paper end ++ + /** + * Bake all handler lists. Best used just after all normal event + * registration is complete, ie just after all plugins are loaded if +@@ -94,6 +101,12 @@ public class HandlerList { + * The HandlerList is then added to meta-list for use in bakeAll() + */ + public HandlerList() { ++ // Paper start ++ java.lang.StackWalker.getInstance(java.util.EnumSet.of(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE), 4) ++ .walk(s -> s.filter(f -> Event.class.isAssignableFrom(f.getDeclaringClass())).findFirst()) ++ .map(f -> f.getDeclaringClass().getName()) ++ .ifPresent(EVENT_TYPES::add); ++ // Paper end + handlerslots = new EnumMap>(EventPriority.class); + for (EventPriority o : EventPriority.values()) { + handlerslots.put(o, new ArrayList()); +diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java +index 5fa52419f21d8e8b3d8f9aafd248b05774a28348..60e086be70529e0804280b24a2a3e7ae72d8d363 100644 +--- a/src/main/java/org/bukkit/plugin/EventExecutor.java ++++ b/src/main/java/org/bukkit/plugin/EventExecutor.java +@@ -70,9 +70,18 @@ public interface EventExecutor { + try { + EventExecutor asmExecutor = executorClass.newInstance(); + // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) +- return (listener, event) -> { +- if (!eventClass.isInstance(event)) return; +- asmExecutor.execute(listener, event); ++ return new EventExecutor() { ++ @Override ++ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { ++ if (!eventClass.isInstance(event)) return; ++ asmExecutor.execute(listener, event); ++ } ++ ++ @Override ++ @NotNull ++ public String toString() { ++ return "ASMEventExecutor['" + m + "']"; ++ } + }; + } catch (InstantiationException | IllegalAccessException e) { + throw new AssertionError("Unable to initialize generated event executor", e); +diff --git a/src/main/java/org/bukkit/plugin/RegisteredListener.java b/src/main/java/org/bukkit/plugin/RegisteredListener.java +index 419aec56b0e3fa8bcec2ea7f340caa3456b57d00..3b3d9642a8d63798dc28f2f8df77f0466451cbff 100644 +--- a/src/main/java/org/bukkit/plugin/RegisteredListener.java ++++ b/src/main/java/org/bukkit/plugin/RegisteredListener.java +@@ -78,4 +78,27 @@ public class RegisteredListener { + public boolean isIgnoringCancelled() { + return ignoreCancelled; + } ++ ++ // Paper start ++ /** ++ * Get the executor for this registration. ++ * ++ * @return executor ++ */ ++ @NotNull ++ public EventExecutor getExecutor() { ++ return this.executor; ++ } ++ ++ @Override ++ public String toString() { ++ return "RegisteredListener{" ++ + "plugin=\"" + this.plugin.getName() ++ + "\", listener=\"" + this.listener ++ + "\", executor=\"" + this.executor ++ + "\", priority=\"" + this.priority.name() + " (" + this.priority.getSlot() + ")" ++ + "\", ignoringCancelled=" + this.ignoreCancelled ++ + "}"; ++ } ++ // Paper end + } diff --git a/patches/api/0374-ItemStack-damage-API.patch b/patches/api/0374-ItemStack-damage-API.patch new file mode 100644 index 000000000000..56fe1421a75b --- /dev/null +++ b/patches/api/0374-ItemStack-damage-API.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 8 May 2022 13:35:58 -0700 +Subject: [PATCH] ItemStack damage API + +Adds methods notify clients about item breaks and +to simulate damage done to an itemstack and all +the logic associated with damaging them + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 8ee3f82049541041623c10940bdda1746200b1e6..fd4d74a637a93c85a057e867b8c07e574916175a 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1375,4 +1375,53 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + void knockback(double strength, double directionX, double directionZ); + // Paper end - knockback API ++ ++ // Paper start - ItemStack damage API ++ /** ++ * Notifies all clients tracking this entity that the item in ++ * the slot of this entity broke. ++ *

      ++ * NOTE: this does not mutate any entity state ++ * ++ * @param slot the slot ++ */ ++ void broadcastSlotBreak(org.bukkit.inventory.@NotNull EquipmentSlot slot); ++ ++ /** ++ * Notifies specified players that the item in the slot ++ * of this entity broke. ++ *

      ++ * NOTE: this does not mutate any entity state ++ * ++ * @param slot the slot ++ * @param players the players to notify ++ */ ++ void broadcastSlotBreak(org.bukkit.inventory.@NotNull EquipmentSlot slot, @NotNull Collection players); ++ ++ /** ++ * Damages the itemstack in this slot by the specified amount. ++ *

      ++ * This runs all logic associated with damaging an itemstack like ++ * gamemode and enchantment checks, events, stat changes, and advancement ++ * triggers. ++ * ++ * @param stack the itemstack to damage ++ * @param amount the amount of damage to do ++ * @return the damaged itemstack, or an empty stack if it broke. There are no ++ * guarantees the returned itemstack is the same instance ++ */ ++ @NotNull ItemStack damageItemStack(@NotNull ItemStack stack, int amount); ++ ++ /** ++ * Damages the itemstack in this slot by the specified amount. ++ *

      ++ * This runs all logic associated with damaging an itemstack like ++ * gamemode and enchantment checks, events, stat changes, advancement ++ * triggers, and notifying clients to play break animations. ++ * ++ * @param slot the slot of the stack to damage ++ * @param amount the amount of damage to do ++ */ ++ void damageItemStack(org.bukkit.inventory.@NotNull EquipmentSlot slot, int amount); ++ // Paper end - ItemStack damage API + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index e9b88bb759af1a5c926d3d4c30a333e7720519cd..6393e5249b4469b1c8ebfb05a0f09572d116c40f 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -1090,5 +1090,19 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + public boolean canRepair(@NotNull ItemStack toBeRepaired) { + return Bukkit.getUnsafe().isValidRepairItemStack(toBeRepaired, this); + } ++ ++ /** ++ * Damages this itemstack by the specified amount. This ++ * runs all logic associated with damaging an itemstack like ++ * events and stat changes. ++ * ++ * @param amount the amount of damage to do ++ * @param livingEntity the entity related to the damage ++ * @return the damaged itemstack or an empty one if it broke. May return the same instance of ItemStack ++ * @see org.bukkit.entity.LivingEntity#damageItemStack(EquipmentSlot, int) to damage itemstacks in equipment slots ++ */ ++ public @NotNull ItemStack damage(int amount, @NotNull org.bukkit.entity.LivingEntity livingEntity) { ++ return livingEntity.damageItemStack(this, amount); ++ } + // Paper end + } diff --git a/patches/api/0375-Add-Tick-TemporalUnit.patch b/patches/api/0375-Add-Tick-TemporalUnit.patch new file mode 100644 index 000000000000..2f5ad025dd49 --- /dev/null +++ b/patches/api/0375-Add-Tick-TemporalUnit.patch @@ -0,0 +1,162 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kieran Wallbanks +Date: Fri, 2 Apr 2021 17:28:58 +0100 +Subject: [PATCH] Add Tick TemporalUnit + + +diff --git a/src/main/java/io/papermc/paper/util/Tick.java b/src/main/java/io/papermc/paper/util/Tick.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1b264819c6faf2a4390d76350deb8e93804c6772 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/Tick.java +@@ -0,0 +1,101 @@ ++package io.papermc.paper.util; ++ ++import java.time.Duration; ++import java.time.temporal.ChronoUnit; ++import java.time.temporal.Temporal; ++import java.time.temporal.TemporalUnit; ++import java.util.Objects; ++import net.kyori.adventure.util.Ticks; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A TemporalUnit that represents the target length of one server tick. This is defined ++ * as 50 milliseconds. Note that this class is not for measuring the length that a tick ++ * took, rather it is used for simple conversion between times and ticks. ++ * ++ * @see #tick() ++ */ ++@NullMarked ++public final class Tick implements TemporalUnit { ++ ++ private static final Tick INSTANCE = new Tick(Ticks.SINGLE_TICK_DURATION_MS); ++ ++ private final long milliseconds; ++ ++ /** ++ * Gets the instance of the tick temporal unit. ++ * ++ * @return the tick instance ++ */ ++ public static Tick tick() { ++ return INSTANCE; ++ } ++ ++ /** ++ * Creates a new tick. ++ * ++ * @param length the length of the tick in milliseconds ++ * @see #tick() ++ */ ++ private Tick(final long length) { ++ this.milliseconds = length; ++ } ++ ++ /** ++ * Creates a duration from an amount of ticks. This is shorthand for ++ * {@link Duration#of(long, TemporalUnit)} called with the amount of ticks and ++ * {@link #tick()}. ++ * ++ * @param ticks the amount of ticks ++ * @return the duration ++ */ ++ public static Duration of(final long ticks) { ++ return Duration.of(ticks, INSTANCE); ++ } ++ ++ /** ++ * Gets the number of whole ticks that occur in the provided duration. Note that this ++ * method returns an {@code int} as this is the unit that Minecraft stores ticks in. ++ * ++ * @param duration the duration ++ * @return the number of whole ticks in this duration ++ * @throws ArithmeticException if the duration is zero or an overflow occurs ++ */ ++ public int fromDuration(final Duration duration) { ++ Objects.requireNonNull(duration, "duration cannot be null"); ++ return Math.toIntExact(Math.floorDiv(duration.toMillis(), this.milliseconds)); ++ } ++ ++ @Override ++ public Duration getDuration() { ++ return Duration.ofMillis(this.milliseconds); ++ } ++ ++ // Note: This is a workaround in order to allow calculations with this duration. ++ // See: Duration#add ++ @Override ++ public boolean isDurationEstimated() { ++ return false; ++ } ++ ++ @Override ++ public boolean isDateBased() { ++ return false; ++ } ++ ++ @Override ++ public boolean isTimeBased() { ++ return true; ++ } ++ ++ @SuppressWarnings("unchecked") // following ChronoUnit#addTo ++ @Override ++ public R addTo(final R temporal, final long amount) { ++ return (R) temporal.plus(this.getDuration().multipliedBy(amount)); ++ } ++ ++ @Override ++ public long between(final Temporal start, final Temporal end) { ++ return start.until(end, ChronoUnit.MILLIS) / this.milliseconds; ++ } ++} +diff --git a/src/test/java/io/papermc/paper/util/TickTest.java b/src/test/java/io/papermc/paper/util/TickTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f147d909f2fc710c1d12bac3c7b66c2883139026 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/util/TickTest.java +@@ -0,0 +1,43 @@ ++package io.papermc.paper.util; ++ ++import java.time.Duration; ++import java.time.Instant; ++import java.time.temporal.ChronoUnit; ++import org.junit.jupiter.api.Test; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; ++ ++public class TickTest { ++ ++ @Test ++ public void testTickLength() { ++ assertEquals(50, Duration.of(1, Tick.tick()).toMillis()); ++ assertEquals(100, Duration.of(2, Tick.tick()).toMillis()); ++ } ++ ++ @Test ++ public void testTickFromDuration() { ++ assertEquals(0, Tick.tick().fromDuration(Duration.ofMillis(0))); ++ assertEquals(0, Tick.tick().fromDuration(Duration.ofMillis(10))); ++ assertEquals(1, Tick.tick().fromDuration(Duration.ofMillis(60))); ++ assertEquals(2, Tick.tick().fromDuration(Duration.ofMillis(100))); ++ } ++ ++ @Test ++ public void testAddTickToInstant() { ++ Instant now = Instant.now(); ++ assertEquals(now, now.plus(0, Tick.tick())); ++ assertEquals(now.plus(50, ChronoUnit.MILLIS), now.plus(1, Tick.tick())); ++ assertEquals(now.plus(100, ChronoUnit.MILLIS), now.plus(2, Tick.tick())); ++ assertEquals(now.plus(150, ChronoUnit.MILLIS), now.plus(3, Tick.tick())); ++ } ++ ++ @Test ++ public void testTicksBetweenInstants() { ++ Instant now = Instant.now(); ++ assertEquals(0, now.until(now.plus(20, ChronoUnit.MILLIS), Tick.tick())); ++ assertEquals(1, now.until(now.plus(50, ChronoUnit.MILLIS), Tick.tick())); ++ assertEquals(1, now.until(now.plus(60, ChronoUnit.MILLIS), Tick.tick())); ++ assertEquals(2, now.until(now.plus(100, ChronoUnit.MILLIS), Tick.tick())); ++ } ++} diff --git a/patches/api/0376-Friction-API.patch b/patches/api/0376-Friction-API.patch new file mode 100644 index 000000000000..8c1155dd714a --- /dev/null +++ b/patches/api/0376-Friction-API.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Noah van der Aa +Date: Wed, 15 Sep 2021 20:40:51 +0200 +Subject: [PATCH] Friction API + + +diff --git a/src/main/java/io/papermc/paper/entity/Frictional.java b/src/main/java/io/papermc/paper/entity/Frictional.java +new file mode 100644 +index 0000000000000000000000000000000000000000..315558d8a592f7238f45fd1e68b70476e721be92 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/Frictional.java +@@ -0,0 +1,35 @@ ++package io.papermc.paper.entity; ++ ++import net.kyori.adventure.util.TriState; ++import org.bukkit.entity.Entity; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents an {@link Entity} that can experience friction with the air and ground. ++ */ ++@NullMarked ++public interface Frictional { ++ ++ /** ++ * Gets the friction state of this entity. ++ * When set to {@link TriState#TRUE}, the entity will always experience friction. ++ * When set to {@link TriState#FALSE}, the entity will never experience friction. ++ * When set to {@link TriState#NOT_SET}, the entity will fall back to Minecraft's default behaviour. ++ * ++ * @return the entity's friction state ++ */ ++ TriState getFrictionState(); ++ ++ /** ++ * Sets the friction state of this entity. ++ * When set to {@link TriState#TRUE}, the entity will always experience friction. ++ * When set to {@link TriState#FALSE}, the entity will never experience friction. ++ * When set to {@link TriState#NOT_SET}, the entity will fall back to Minecraft's default behaviour. ++ *

      ++ * Please note that changing this value will do nothing for a player. ++ * ++ * @param state the new friction state to set for the entity ++ */ ++ void setFrictionState(TriState state); ++ ++} +diff --git a/src/main/java/org/bukkit/entity/Item.java b/src/main/java/org/bukkit/entity/Item.java +index ced419f8655bff72f0257b639d5f7d73afe3c2e2..bcc6ba95bd21c7972865838c636a03f50b6c1f1a 100644 +--- a/src/main/java/org/bukkit/entity/Item.java ++++ b/src/main/java/org/bukkit/entity/Item.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a dropped item. + */ +-public interface Item extends Entity { ++public interface Item extends Entity, io.papermc.paper.entity.Frictional { // Paper + + /** + * Gets the item stack associated with this item drop. +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index fd4d74a637a93c85a057e867b8c07e574916175a..8cc4ab8f560f5db9cf7f58233578838945a52deb 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a living entity, such as a monster or player + */ +-public interface LivingEntity extends Attributable, Damageable, ProjectileSource { ++public interface LivingEntity extends Attributable, Damageable, ProjectileSource, io.papermc.paper.entity.Frictional { // Paper + + /** + * Gets the height of the living entity's eyes above its Location. +diff --git a/src/main/java/org/bukkit/entity/Minecart.java b/src/main/java/org/bukkit/entity/Minecart.java +index c3c94a5694f1e8d79e5acc45af1cd2e0fa6a621f..0e4163c9358dc2dc6b8b0aca1da0f59c805e47f4 100644 +--- a/src/main/java/org/bukkit/entity/Minecart.java ++++ b/src/main/java/org/bukkit/entity/Minecart.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a minecart entity. + */ +-public interface Minecart extends Vehicle { ++public interface Minecart extends Vehicle, io.papermc.paper.entity.Frictional { // Paper + + /** + * Sets a minecart's damage. diff --git a/patches/api/0377-Player-Entity-Tracking-Events.patch b/patches/api/0377-Player-Entity-Tracking-Events.patch new file mode 100644 index 000000000000..ff550d451b2d --- /dev/null +++ b/patches/api/0377-Player-Entity-Tracking-Events.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yannick Lamprecht +Date: Wed, 30 Mar 2022 18:16:37 +0200 +Subject: [PATCH] Player Entity Tracking Events + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0e37c8c94a77f6f1c2c4f5290722ca02d76ab924 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java +@@ -0,0 +1,60 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Is called when a {@link Player} tracks an {@link Entity}. ++ *

      ++ * If cancelled entity is not shown to the player and interaction in both directions is not possible. ++ *

      ++ * Adding or removing entities from the world at the point in time this event is called is completely ++ * unsupported and should be avoided. ++ */ ++@NullMarked ++public class PlayerTrackEntityEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity entity; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PlayerTrackEntityEvent(final Player player, final Entity entity) { ++ super(player); ++ this.entity = entity; ++ } ++ ++ /** ++ * Gets the entity that will be tracked ++ * ++ * @return the entity tracked ++ */ ++ public Entity getEntity() { ++ return this.entity; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..30e01ffc8b0d4a8e43a046d85f1903cc20e0e84d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java +@@ -0,0 +1,46 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Is called when a {@link Player} untracks an {@link Entity}. ++ *

      ++ * Adding or removing entities from the world at the point in time this event is called is completely ++ * unsupported and should be avoided. ++ */ ++@NullMarked ++public class PlayerUntrackEntityEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity entity; ++ ++ @ApiStatus.Internal ++ public PlayerUntrackEntityEvent(final Player player, final Entity entity) { ++ super(player); ++ this.entity = entity; ++ } ++ ++ /** ++ * Gets the entity that will be untracked ++ * ++ * @return the entity untracked ++ */ ++ public Entity getEntity() { ++ return this.entity; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0378-fix-Instruments.patch b/patches/api/0378-fix-Instruments.patch new file mode 100644 index 000000000000..3ce4ac68fafa --- /dev/null +++ b/patches/api/0378-fix-Instruments.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 9 Dec 2022 01:34:03 -0800 +Subject: [PATCH] fix Instruments + +Add missing instrument enums +fix some wrong javadocs + +diff --git a/src/main/java/org/bukkit/Instrument.java b/src/main/java/org/bukkit/Instrument.java +index 90bf1521e5b8b6c6d47489145e116f2a43fd3250..8df26e0d7bea77bb257cddbc2ab9e969fa160681 100644 +--- a/src/main/java/org/bukkit/Instrument.java ++++ b/src/main/java/org/bukkit/Instrument.java +@@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable; + public enum Instrument { + + /** +- * Piano is the standard instrument for a note block. ++ * Piano (Harp) is the standard instrument for a note block. + */ + PIANO(0x0, Sound.BLOCK_NOTE_BLOCK_HARP), + /** +@@ -21,7 +21,7 @@ public enum Instrument { + */ + SNARE_DRUM(0x2, Sound.BLOCK_NOTE_BLOCK_SNARE), + /** +- * Sticks are normally played when a note block is on top of a glass ++ * Sticks (Hat) are normally played when a note block is on top of a glass + * block. + */ + STICKS(0x3, Sound.BLOCK_NOTE_BLOCK_HAT), +@@ -78,39 +78,37 @@ public enum Instrument { + /** + * Zombie is normally played when a Zombie Head is on top of the note block. + */ +- ZOMBIE(Sound.BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE), ++ ZOMBIE(0x10, Sound.BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE), // Paper + /** + * Skeleton is normally played when a Skeleton Head is on top of the note block. + */ +- SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_SKELETON), ++ SKELETON(0x11, Sound.BLOCK_NOTE_BLOCK_IMITATE_SKELETON), // Paper + /** + * Creeper is normally played when a Creeper Head is on top of the note block. + */ +- CREEPER(Sound.BLOCK_NOTE_BLOCK_IMITATE_CREEPER), ++ CREEPER(0x12, Sound.BLOCK_NOTE_BLOCK_IMITATE_CREEPER), // Paper + /** + * Dragon is normally played when a Dragon Head is on top of the note block. + */ +- DRAGON(Sound.BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON), ++ DRAGON(0x13, Sound.BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON), // Paper + /** + * Wither Skeleton is normally played when a Wither Skeleton Head is on top of the note block. + */ +- WITHER_SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON), ++ WITHER_SKELETON(0x14, Sound.BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON), // Paper + /** + * Piglin is normally played when a Piglin Head is on top of the note block. + */ +- PIGLIN(Sound.BLOCK_NOTE_BLOCK_IMITATE_PIGLIN), ++ PIGLIN(0x15, Sound.BLOCK_NOTE_BLOCK_IMITATE_PIGLIN), // Paper + /** + * Custom Sound is normally played when a Player Head with the required data is on top of the note block. + */ +- CUSTOM_HEAD(null); ++ CUSTOM_HEAD(0x16, null); // Paper + + private final byte type; + private final Sound sound; + private static final Map BY_DATA = Maps.newHashMap(); + +- private Instrument(final Sound sound) { +- this(-1, sound); +- } ++ // Paper - remove ctor (the server still uses the byte magic value) + + private Instrument(final int type, final Sound sound) { + this.type = (byte) type; +@@ -130,9 +128,8 @@ public enum Instrument { + + /** + * @return The type ID of this instrument. +- * @deprecated Magic value + */ +- @Deprecated(since = "1.6.2") ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper + public byte getType() { + return this.type; + } +@@ -142,9 +139,8 @@ public enum Instrument { + * + * @param type The type ID + * @return The instrument +- * @deprecated Magic value + */ +- @Deprecated(since = "1.6.2") ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper + @Nullable + public static Instrument getByType(final byte type) { + return BY_DATA.get(type); +diff --git a/src/test/java/org/bukkit/InstrumentTest.java b/src/test/java/org/bukkit/InstrumentTest.java +deleted file mode 100644 +index 6f27b260d9dbe76da733459c8341282e23440b8a..0000000000000000000000000000000000000000 +--- a/src/test/java/org/bukkit/InstrumentTest.java ++++ /dev/null +@@ -1,19 +0,0 @@ +-package org.bukkit; +- +-import static org.bukkit.support.MatcherAssert.*; +-import static org.hamcrest.CoreMatchers.*; +-import org.bukkit.support.AbstractTestingBase; +-import org.junit.jupiter.api.Test; +- +-public class InstrumentTest extends AbstractTestingBase { +- @Test +- public void getByType() { +- for (Instrument instrument : Instrument.values()) { +- if (instrument.getType() < 0) { +- continue; +- } +- +- assertThat(Instrument.getByType(instrument.getType()), is(instrument)); +- } +- } +-} diff --git a/patches/api/0379-Add-BlockLockCheckEvent.patch b/patches/api/0379-Add-BlockLockCheckEvent.patch new file mode 100644 index 000000000000..b9a9adb70ce8 --- /dev/null +++ b/patches/api/0379-Add-BlockLockCheckEvent.patch @@ -0,0 +1,242 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 21 May 2022 20:59:56 -0700 +Subject: [PATCH] Add BlockLockCheckEvent + + +diff --git a/src/main/java/io/papermc/paper/block/LockableTileState.java b/src/main/java/io/papermc/paper/block/LockableTileState.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f309961e0e96b6baacc4fe6d80dabd6c7c5d2e1d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/block/LockableTileState.java +@@ -0,0 +1,11 @@ ++package io.papermc.paper.block; ++ ++import org.bukkit.Nameable; ++import org.bukkit.block.Lockable; ++import org.bukkit.block.TileState; ++ ++/** ++ * Interface for tile entities that are lockable. ++ */ ++public interface LockableTileState extends TileState, Lockable, Nameable { ++} +diff --git a/src/main/java/io/papermc/paper/event/block/BlockLockCheckEvent.java b/src/main/java/io/papermc/paper/event/block/BlockLockCheckEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f08d390f0ee9357dcc229d7a2520da602677d9ef +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BlockLockCheckEvent.java +@@ -0,0 +1,187 @@ ++package io.papermc.paper.event.block; ++ ++import com.google.common.base.Preconditions; ++import io.papermc.paper.block.LockableTileState; ++import java.util.Objects; ++import net.kyori.adventure.sound.Sound; ++import net.kyori.adventure.text.Component; ++import org.bukkit.block.Block; ++import org.bukkit.block.BlockState; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Called when the server tries to check the lock on a lockable block entity. ++ *
      ++ * See {@link #setResult(Result)} to change behavior ++ */ ++@NullMarked ++public class BlockLockCheckEvent extends BlockEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Player player; ++ private @Nullable Component lockedMessage; ++ private @Nullable Sound lockedSound; ++ private @Nullable ItemStack itemStack; ++ private Result result = Result.DEFAULT; ++ ++ @ApiStatus.Internal ++ public BlockLockCheckEvent(final Block block, final Player player, final Component lockedMessage, final Sound lockedSound) { ++ super(block); ++ this.player = player; ++ this.lockedMessage = lockedMessage; ++ this.lockedSound = lockedSound; ++ } ++ ++ /** ++ * Gets the snapshot {@link LockableTileState} of the block entity ++ * whose lock is being checked. ++ * ++ * @return the snapshot block state. ++ */ ++ public LockableTileState getBlockState() { ++ final BlockState blockState = this.getBlock().getState(); ++ Preconditions.checkState(blockState instanceof LockableTileState, "Block state of lock-checked block is no longer a lockable tile state!"); ++ return (LockableTileState) blockState; ++ } ++ ++ /** ++ * Get the player involved this lock check. ++ * ++ * @return the player ++ */ ++ public Player getPlayer() { ++ return this.player; ++ } ++ ++ /** ++ * Gets the itemstack that will be used as the key itemstack. Initially ++ * this will be the item in the player's main hand but an override can be set ++ * with {@link #setKeyItem(ItemStack)}. Use {@link #isUsingCustomKeyItemStack()} ++ * to check if a custom key stack has been set. ++ * ++ * @return the item being used as the key item ++ * @see #isUsingCustomKeyItemStack() ++ */ ++ public ItemStack getKeyItem() { ++ return Objects.requireNonNullElseGet(this.itemStack, this.player.getInventory()::getItemInMainHand); ++ } ++ ++ /** ++ * Sets the itemstack that will be used as the key item. ++ * ++ * @param stack the stack to use as a key ++ * @see #resetKeyItem() to clear a custom key item ++ */ ++ public void setKeyItem(final ItemStack stack) { ++ Preconditions.checkArgument(stack != null, "stack cannot be null"); ++ this.itemStack = stack; ++ } ++ ++ /** ++ * Reset the key stack to the default (the player's main hand). ++ */ ++ public void resetKeyItem() { ++ this.itemStack = null; ++ } ++ ++ /** ++ * Checks if a custom key stack has been set. ++ * ++ * @return {@code true} if a custom key itemstack has been set ++ */ ++ public boolean isUsingCustomKeyItemStack() { ++ return this.itemStack != null; ++ } ++ ++ /** ++ * Gets the result of this event. ++ * ++ * @return the result ++ * @see #setResult(Result) ++ */ ++ public Result getResult() { ++ return this.result; ++ } ++ ++ /** ++ * Gets the result of this event. {@link Result#DEFAULT} is the default ++ * allowing the vanilla logic to check the lock of this block. Set to {@link Result#ALLOW} ++ * or {@link Result#DENY} to override that behavior. ++ *

      ++ * Setting this to {@link Result#ALLOW} bypasses the spectator check. ++ * ++ * @param result the result of this event ++ */ ++ public void setResult(final Result result) { ++ this.result = result; ++ } ++ ++ /** ++ * Shorthand method to set the {@link #getResult()} to {@link Result#DENY}, ++ * the locked message and locked sound. ++ * ++ * @param lockedMessage the message to show if locked (or {@code null} for none) ++ * @param lockedSound the sound to play if locked (or {@code null} for none) ++ */ ++ public void denyWithMessageAndSound(final @Nullable Component lockedMessage, final @Nullable Sound lockedSound) { ++ this.result = Result.DENY; ++ this.lockedMessage = lockedMessage; ++ this.lockedSound = lockedSound; ++ } ++ ++ /** ++ * Gets the locked message that will be sent if the ++ * player cannot open the block. ++ * ++ * @return the locked message (or {@code null} if none) ++ */ ++ public @Nullable Component getLockedMessage() { ++ return this.lockedMessage; ++ } ++ ++ /** ++ * Sets the locked message that will be sent if the ++ * player cannot open the block. ++ * ++ * @param lockedMessage the locked message (or {@code null} for none) ++ */ ++ public void setLockedMessage(final @Nullable Component lockedMessage) { ++ this.lockedMessage = lockedMessage; ++ } ++ ++ /** ++ * Gets the locked sound that will play if the ++ * player cannot open the block. ++ * ++ * @return the locked sound (or {@code null} if none) ++ */ ++ public @Nullable Sound getLockedSound() { ++ return this.lockedSound; ++ } ++ ++ /** ++ * Sets the locked sound that will play if the ++ * player cannot open the block. ++ * ++ * @param lockedSound the locked sound (or {@code null} for none) ++ */ ++ public void setLockedSound(final @Nullable Sound lockedSound) { ++ this.lockedSound = lockedSound; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/org/bukkit/block/Beacon.java b/src/main/java/org/bukkit/block/Beacon.java +index 7d212c409035ccb8b22d4ffc322b4a1aea367627..79c04b840adb768f7a38e95a82f79287f42681f5 100644 +--- a/src/main/java/org/bukkit/block/Beacon.java ++++ b/src/main/java/org/bukkit/block/Beacon.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a beacon. + */ +-public interface Beacon extends TileState, Lockable, Nameable { ++public interface Beacon extends io.papermc.paper.block.LockableTileState { // Paper + + /** + * Returns the list of players within the beacon's range of effect. +diff --git a/src/main/java/org/bukkit/block/Container.java b/src/main/java/org/bukkit/block/Container.java +index bc06199f0a1cc43e0bdfd5b11fa170badd46e180..a67ee0cb0cd2cbab8dab375e2fe44168c250bcb7 100644 +--- a/src/main/java/org/bukkit/block/Container.java ++++ b/src/main/java/org/bukkit/block/Container.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a captured state of a container block. + */ +-public interface Container extends TileState, BlockInventoryHolder, Lockable, Nameable { ++public interface Container extends io.papermc.paper.block.LockableTileState, BlockInventoryHolder { // Paper + + /** + * Gets the inventory of the block represented by this block state. diff --git a/patches/api/0380-Add-Sneaking-API-for-Entities.patch b/patches/api/0380-Add-Sneaking-API-for-Entities.patch new file mode 100644 index 000000000000..638560281fe1 --- /dev/null +++ b/patches/api/0380-Add-Sneaking-API-for-Entities.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dawon +Date: Wed, 19 Oct 2022 23:36:42 +0200 +Subject: [PATCH] Add Sneaking API for Entities + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 2b4058dace5d071f60a9629f81c2323ee8c6d109..9cfffc02da491450c080cdd80e96f60921518fb9 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -823,6 +823,25 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + @NotNull + Pose getPose(); + ++ // Paper start ++ /** ++ * Returns if the entity is in sneak mode ++ * ++ * @return true if the entity is in sneak mode ++ */ ++ boolean isSneaking(); ++ ++ /** ++ * Sets the sneak mode the entity. ++ *

      ++ * Note: For most Entities this does not update Entity's pose ++ * and just makes its name tag less visible. ++ * ++ * @param sneak true if the entity should be sneaking ++ */ ++ void setSneaking(boolean sneak); ++ // Paper end ++ + /** + * Get the category of spawn to which this entity belongs. + * +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 8873f0eb1451cd4e8801b75e8bd477eae588e73b..acb65c90ad87b35c00fafc4e60803adc13af1225 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -475,6 +475,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @return true if player is in sneak mode + */ ++ @Override // Paper + public boolean isSneaking(); + + /** +@@ -482,6 +483,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * + * @param sneak true if player should appear sneaking + */ ++ @Override // Paper + public void setSneaking(boolean sneak); + + /** diff --git a/patches/api/0381-Improve-PortalEvents.patch b/patches/api/0381-Improve-PortalEvents.patch new file mode 100644 index 000000000000..88c76230fdee --- /dev/null +++ b/patches/api/0381-Improve-PortalEvents.patch @@ -0,0 +1,225 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 15 Dec 2022 10:33:34 -0800 +Subject: [PATCH] Improve PortalEvents + + +diff --git a/src/main/java/org/bukkit/PortalType.java b/src/main/java/org/bukkit/PortalType.java +index 427cfbb8b542215c5d9993056e0cadf18ab9bd4b..e6120b83259c15189bbbf6b6dd13fbe7ccdf073d 100644 +--- a/src/main/java/org/bukkit/PortalType.java ++++ b/src/main/java/org/bukkit/PortalType.java +@@ -14,6 +14,12 @@ public enum PortalType { + * This is an Ender portal. + */ + ENDER, ++ // Paper start ++ /** ++ * This is an end gateway ++ */ ++ END_GATEWAY, ++ // Paper end + + /** + * This is a custom Plugin portal. +diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +index 6818e9f0ba32ca1a1e612703f7526b29f5a6438f..d3724db0a5a67cde15b05fecd32b2ca370cca998 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +@@ -7,14 +7,25 @@ import org.jetbrains.annotations.NotNull; + + /** + * Called when an entity comes into contact with a portal ++ *

      ++ * Cancelling this event prevents any further processing of the portal for that tick. ++ * @see io.papermc.paper.event.entity.EntityInsideBlockEvent + */ +-public class EntityPortalEnterEvent extends EntityEvent { ++public class EntityPortalEnterEvent extends EntityEvent implements org.bukkit.event.Cancellable { // Paper + private static final HandlerList handlers = new HandlerList(); + private final Location location; + ++ @Deprecated(since = "1.21") @io.papermc.paper.annotation.DoNotUse // Paper + public EntityPortalEnterEvent(@NotNull final Entity entity, @NotNull final Location location) { ++ // Paper start ++ this(entity, location, org.bukkit.PortalType.CUSTOM); ++ } ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public EntityPortalEnterEvent(@NotNull final Entity entity, @NotNull final Location location, @NotNull final org.bukkit.PortalType portalType) { ++ // Paper end + super(entity); + this.location = location; ++ this.portalType = portalType; // Paper + } + + /** +@@ -27,6 +38,30 @@ public class EntityPortalEnterEvent extends EntityEvent { + return location; + } + ++ // Paper start ++ private boolean cancelled = false; ++ private final org.bukkit.PortalType portalType; ++ ++ /** ++ * Get the portal type. ++ * ++ * @return the portal type ++ */ ++ public org.bukkit.@NotNull PortalType getPortalType() { ++ return this.portalType; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { +diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java b/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java +index d70400236b08217ba675e560877f951ea4f143ca..4544e7e155619a6ae31cbb2999ae3dedfd3b5f4b 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java +@@ -3,6 +3,7 @@ package org.bukkit.event.entity; + import org.bukkit.Location; + import org.bukkit.entity.Entity; + import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +@@ -17,23 +18,68 @@ public class EntityPortalEvent extends EntityTeleportEvent { + private int searchRadius = 128; + private boolean canCreatePortal = true; + private int creationRadius = 16; ++ private final org.bukkit.PortalType type; // Paper + + public EntityPortalEvent(@NotNull final Entity entity, @NotNull final Location from, @Nullable final Location to) { +- super(entity, from, to); ++ this(entity, from, to, 128); // Paper + } + + public EntityPortalEvent(@NotNull Entity entity, @NotNull Location from, @Nullable Location to, int searchRadius) { + super(entity, from, to); + this.searchRadius = searchRadius; ++ this.type = org.bukkit.PortalType.CUSTOM; // Paper + } + + public EntityPortalEvent(@NotNull Entity entity, @NotNull Location from, @Nullable Location to, int searchRadius, boolean canCreatePortal, int creationRadius) { ++ // Paper start ++ this(entity, from, to, searchRadius, canCreatePortal, creationRadius, org.bukkit.PortalType.CUSTOM); ++ } ++ ++ @ApiStatus.Internal ++ public EntityPortalEvent(@NotNull Entity entity, @NotNull Location from, @Nullable Location to, int searchRadius, boolean canCreatePortal, int creationRadius, final @NotNull org.bukkit.PortalType portalType) { + super(entity, from, to); ++ this.type = portalType; ++ // Paper end + this.searchRadius = searchRadius; + this.canCreatePortal = canCreatePortal; + this.creationRadius = creationRadius; + } + ++ // Paper start ++ /** ++ * Get the portal type relating to this event. ++ * ++ * @return the portal type ++ */ ++ public @NotNull org.bukkit.PortalType getPortalType() { ++ return this.type; ++ } ++ /** ++ * For {@link org.bukkit.PortalType#NETHER}, this is initially just the starting point ++ * for the search for a portal to teleport to. It will initially just be the {@link #getFrom()} ++ * scaled for dimension scaling and clamped to be inside the world border. ++ *

      ++ * For {@link org.bukkit.PortalType#ENDER}, this will initially be the exact destination ++ * either, the world spawn for end->any world or end spawn for any world->end. ++ * ++ * @return starting point for search or exact destination ++ */ ++ @Override ++ public @Nullable Location getTo() { ++ return super.getTo(); ++ } ++ ++ /** ++ * See the description of {@link #getTo()}. ++ * @param to starting point for search or exact destination ++ * or null to cancel ++ */ ++ @Override ++ public void setTo(@Nullable final Location to) { ++ super.setTo(to); ++ } ++ // Paper end ++ + /** + * Set the Block radius to search in for available portals. + * +diff --git a/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java b/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java +index 57eeeafae84f83a939925820e827769749ff27ec..929a997671de8202efb9da97fbf9b4a0bf7c37e8 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java +@@ -32,6 +32,53 @@ public class PlayerPortalEvent extends PlayerTeleportEvent { + this.canCreatePortal = canCreatePortal; + this.creationRadius = creationRadius; + } ++ // Paper start ++ /** ++ * For {@link TeleportCause#NETHER_PORTAL}, this is initially just the starting point ++ * for the search for a portal to teleport to. It will initially just be the {@link #getFrom()} ++ * scaled for dimension scaling and clamped to be inside the world border. ++ *

      ++ * For {@link TeleportCause#END_PORTAL}, this will initially be the exact destination ++ * either, the world spawn for end->any world or end spawn for any world->end. ++ * ++ * @return starting point for search or exact destination ++ */ ++ @Override ++ public @NotNull Location getTo() { ++ return super.getTo(); ++ } ++ ++ /** ++ * See the description of {@link #getTo()}. ++ * @param to starting point for search or exact destination ++ */ ++ @Override ++ public void setTo(@NotNull final Location to) { ++ super.setTo(to); ++ } ++ ++ /** ++ * No effect ++ * @return no effect ++ * @deprecated No effect ++ */ ++ @Deprecated ++ @Override ++ public boolean willDismountPlayer() { ++ return super.willDismountPlayer(); ++ } ++ ++ /** ++ * No effect ++ * @return no effect ++ * @deprecated No effect ++ */ ++ @Deprecated ++ @Override ++ public @NotNull java.util.Set getRelativeTeleportationFlags() { ++ return super.getRelativeTeleportationFlags(); ++ } ++ // Paper end + + /** + * Set the Block radius to search in for available portals. diff --git a/patches/api/0382-Flying-Fall-Damage-API.patch b/patches/api/0382-Flying-Fall-Damage-API.patch new file mode 100644 index 000000000000..8144d7e6d5b9 --- /dev/null +++ b/patches/api/0382-Flying-Fall-Damage-API.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TreyRuffy +Date: Fri, 27 May 2022 02:25:38 -0600 +Subject: [PATCH] Flying Fall Damage API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index acb65c90ad87b35c00fafc4e60803adc13af1225..4e15db5b6dacc784d6893874295dbd9b84595011 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1948,6 +1948,23 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void setAllowFlight(boolean flight); + ++ // Paper start - flying fall damage ++ /** ++ * Allows you to enable fall damage while {@link #getAllowFlight()} is {@code true} ++ * ++ * @param flyingFallDamage Enables fall damage when {@link #getAllowFlight()} is {@code true} ++ */ ++ public void setFlyingFallDamage(@NotNull net.kyori.adventure.util.TriState flyingFallDamage); ++ ++ /** ++ * Allows you to get if fall damage is enabled while {@link #getAllowFlight()} is {@code true} ++ * ++ * @return A tristate of whether fall damage is enabled, not set, or disabled when {@link #getAllowFlight()} is {@code true} ++ */ ++ @NotNull ++ public net.kyori.adventure.util.TriState hasFlyingFallDamage(); ++ // Paper end ++ + /** + * Hides a player from this player + * diff --git a/patches/api/0383-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch b/patches/api/0383-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch new file mode 100644 index 000000000000..475ca65bbf54 --- /dev/null +++ b/patches/api/0383-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Thu, 5 Jan 2023 10:45:20 +0100 +Subject: [PATCH] Replace ItemFlag.HIDE_POTION_EFFECTS + + +diff --git a/src/main/java/org/bukkit/inventory/ItemFlag.java b/src/main/java/org/bukkit/inventory/ItemFlag.java +index 1b3580d1861af402396121805715e4087b3bc587..5b8dac777bb1640dc00bbe98feb6460c36eebb98 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFlag.java ++++ b/src/main/java/org/bukkit/inventory/ItemFlag.java +@@ -38,4 +38,27 @@ public enum ItemFlag { + * Setting to show/hide armor trim from armor. + */ + HIDE_ARMOR_TRIM; ++ // Paper start ++ /** ++ * Setting to show/hide item-specific information, including, but not limited to: ++ *

        ++ *
      • Potion effects on potions, tipped arrows, and suspicious stew
      • ++ *
      • Enchanted book enchantments
      • ++ *
      • Book author and generation
      • ++ *
      • Record names
      • ++ *
      • Patterns of banners and shields
      • ++ *
      • Fish bucket variants
      • ++ *
      • Instrument item descriptions (i.e. goat horn sounds)
      • ++ *
      • Map data
      • ++ *
      • Firework data
      • ++ *
      • Crossbow projectile info
      • ++ *
      • Bundle fullness
      • ++ *
      • Shulker box contents
      • ++ *
      • Spawner descriptions
      • ++ *
      ++ * @deprecated use {@link #HIDE_ADDITIONAL_TOOLTIP} ++ */ ++ @Deprecated(since = "1.20.5") ++ public static final ItemFlag HIDE_ITEM_SPECIFICS = HIDE_ADDITIONAL_TOOLTIP; ++ // Paper end + } diff --git a/patches/api/0384-Win-Screen-API.patch b/patches/api/0384-Win-Screen-API.patch new file mode 100644 index 000000000000..03a11e325b63 --- /dev/null +++ b/patches/api/0384-Win-Screen-API.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lama06 +Date: Sat, 21 Jan 2023 13:45:22 +0100 +Subject: [PATCH] Win Screen API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 4e15db5b6dacc784d6893874295dbd9b84595011..c2d49ff3aee971598451734f95144ac5dbbf131a 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1287,6 +1287,47 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public void sendMap(@NotNull MapView map); + ++ // Paper start ++ /** ++ * Shows the player the win screen that normally is only displayed after one kills the ender dragon ++ * and exits the end for the first time. ++ * In vanilla, the win screen starts with a poem and then continues with the credits but its content can be ++ * changed by using a resource pack. ++ *
      ++ * Calling this method does not change the value of {@link #hasSeenWinScreen()}. ++ * That means that the win screen is still displayed to a player if they leave the end for the first time, even though ++ * they have seen it before because this method was called. ++ * Note this method does not make the player invulnerable, which is normally expected when viewing credits. ++ * ++ * @see #hasSeenWinScreen() ++ * @see #setHasSeenWinScreen(boolean) ++ * @see https://minecraft.wiki/wiki/End_Poem#Technical_details ++ */ ++ public void showWinScreen(); ++ ++ /** ++ * Returns whether this player has seen the win screen before. ++ * When a player leaves the end the win screen is shown to them if they have not seen it before. ++ * ++ * @return Whether this player has seen the win screen before ++ * @see #setHasSeenWinScreen(boolean) ++ * @see #showWinScreen() ++ * @see https://minecraft.wiki/wiki/End_Poem ++ */ ++ public boolean hasSeenWinScreen(); ++ ++ /** ++ * Changes whether this player has seen the win screen before. ++ * When a player leaves the end the win screen is shown to them if they have not seen it before. ++ * ++ * @param hasSeenWinScreen Whether this player has seen the win screen before ++ * @see #hasSeenWinScreen() ++ * @see #showWinScreen() ++ * @see https://minecraft.wiki/wiki/End_Poem ++ */ ++ public void setHasSeenWinScreen(boolean hasSeenWinScreen); ++ // Paper end ++ + // Paper start + /** + * Permanently Bans the Profile and IP address currently used by the player. diff --git a/patches/api/0385-Add-Entity-Body-Yaw-API.patch b/patches/api/0385-Add-Entity-Body-Yaw-API.patch new file mode 100644 index 000000000000..aba64c12663b --- /dev/null +++ b/patches/api/0385-Add-Entity-Body-Yaw-API.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheTuso +Date: Thu, 2 Feb 2023 16:40:11 +0100 +Subject: [PATCH] Add Entity Body Yaw API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 9cfffc02da491450c080cdd80e96f60921518fb9..0ca7cb73c4007647841ed6a78c8949fcc3ed97ff 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -1041,6 +1041,43 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * @return true if in powdered snow. + */ + boolean isInPowderedSnow(); ++ ++ /** ++ * Gets the x-coordinate of this entity ++ * ++ * @return x-coordinate ++ */ ++ double getX(); ++ ++ /** ++ * Gets the y-coordinate of this entity ++ * ++ * @return y-coordinate ++ */ ++ double getY(); ++ ++ /** ++ * Gets the z-coordinate of this entity ++ * ++ * @return z-coordinate ++ */ ++ double getZ(); ++ ++ /** ++ * Gets this entity's pitch ++ * ++ * @see Location#getPitch() ++ * @return the entity's pitch ++ */ ++ float getPitch(); ++ ++ /** ++ * Gets this entity's yaw ++ * ++ * @see Location#getYaw() ++ * @return the entity's yaw ++ */ ++ float getYaw(); + // Paper end + + // Paper start - Collision API +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 8cc4ab8f560f5db9cf7f58233578838945a52deb..8375ec85b78378f6ebc0a970fb0df205feb984e7 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1424,4 +1424,22 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + void damageItemStack(org.bukkit.inventory.@NotNull EquipmentSlot slot, int amount); + // Paper end - ItemStack damage API ++ ++ // Paper start - body yaw API ++ /** ++ * Gets entity body yaw ++ * ++ * @return entity body yaw ++ * @see Location#getYaw() ++ */ ++ float getBodyYaw(); ++ ++ /** ++ * Sets entity body yaw ++ * ++ * @param bodyYaw new entity body yaw ++ * @see Location#setYaw(float) ++ */ ++ void setBodyYaw(float bodyYaw); ++ // Paper end - body yaw API + } diff --git a/patches/api/0386-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch b/patches/api/0386-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch new file mode 100644 index 000000000000..c375206bf7e8 --- /dev/null +++ b/patches/api/0386-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 7 Feb 2023 08:20:27 -0800 +Subject: [PATCH] Fix HandlerList for InventoryBlockStartEvent subclasses + + +diff --git a/src/main/java/org/bukkit/event/block/BrewingStartEvent.java b/src/main/java/org/bukkit/event/block/BrewingStartEvent.java +index 37be83184cae203d5e99518b0ff5c708fafb0331..43eac972f45d1cbb6278b048f8e6d7882c0aabeb 100644 +--- a/src/main/java/org/bukkit/event/block/BrewingStartEvent.java ++++ b/src/main/java/org/bukkit/event/block/BrewingStartEvent.java +@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; + @org.jetbrains.annotations.ApiStatus.Experimental // Paper + public class BrewingStartEvent extends InventoryBlockStartEvent { + +- private static final HandlerList handlers = new HandlerList(); ++ // Paper - remove HandlerList + private int brewingTime; + + public BrewingStartEvent(@NotNull final Block furnace, @NotNull ItemStack source, int brewingTime) { +@@ -37,14 +37,5 @@ public class BrewingStartEvent extends InventoryBlockStartEvent { + this.brewingTime = brewTime; + } + +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } ++ // Paper - remove HandlerList + } +diff --git a/src/main/java/org/bukkit/event/block/CampfireStartEvent.java b/src/main/java/org/bukkit/event/block/CampfireStartEvent.java +index 2d084214e991fecc51f8e18e3d733e43b1dca248..4b12575107b3f1fa6d0ed7f667bf0d0ae40acae0 100644 +--- a/src/main/java/org/bukkit/event/block/CampfireStartEvent.java ++++ b/src/main/java/org/bukkit/event/block/CampfireStartEvent.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; + @org.jetbrains.annotations.ApiStatus.Experimental // Paper + public class CampfireStartEvent extends InventoryBlockStartEvent { + +- private static final HandlerList handlers = new HandlerList(); ++ // Paper - remove HandlerList + private int cookingTime; + private CampfireRecipe campfireRecipe; + +@@ -50,14 +50,5 @@ public class CampfireStartEvent extends InventoryBlockStartEvent { + this.cookingTime = cookTime; + } + +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } ++ // Paper - remove HandlerList + } +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java +index d386ab5dd46cc6706ace61fe6b646713ffd50cb7..abfd0441f1dd485e59ce5a9f7fca88ffa32e87f7 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; + * {@link org.bukkit.block.Smoker}, and {@link org.bukkit.block.BlastFurnace}. + */ + public class FurnaceStartSmeltEvent extends InventoryBlockStartEvent { +- private static final HandlerList handlers = new HandlerList(); ++ // Paper - remove HandlerList + private final CookingRecipe recipe; + private int totalCookTime; + +@@ -59,14 +59,5 @@ public class FurnaceStartSmeltEvent extends InventoryBlockStartEvent { + this.totalCookTime = cookTime; + } + +- @NotNull +- @Override +- public HandlerList getHandlers() { +- return handlers; +- } +- +- @NotNull +- public static HandlerList getHandlerList() { +- return handlers; +- } ++ // Paper - remove HandlerList + } diff --git a/patches/api/0387-Add-EntityFertilizeEggEvent.patch b/patches/api/0387-Add-EntityFertilizeEggEvent.patch new file mode 100644 index 000000000000..8c15e656f8b1 --- /dev/null +++ b/patches/api/0387-Add-EntityFertilizeEggEvent.patch @@ -0,0 +1,145 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> +Date: Fri, 24 Jun 2022 11:56:32 +0200 +Subject: [PATCH] Add EntityFertilizeEggEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityFertilizeEggEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityFertilizeEggEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a96c28678c5f6a52710ae287d3bbc25e180d058e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityFertilizeEggEvent.java +@@ -0,0 +1,133 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.Material; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Called when two entities mate and the mating process results in a fertilization. ++ * Fertilization differs from normal breeding, as represented by the {@link EntityBreedEvent}, as ++ * it does not result in the immediate creation of the child entity in the world. ++ *

      ++ * An example of this would be: ++ *

        ++ *
      • A frog being marked as "is_pregnant" and laying {@link Material#FROGSPAWN} later.
      • ++ *
      • Sniffers producing the {@link Material#SNIFFER_EGG} item, which needs to be placed before it can begin to hatch.
      • ++ *
      • A turtle being marked with "HasEgg" and laying a {@link Material#TURTLE_EGG} later.
      • ++ *
      ++ *

      ++ * The event hence only exposes the two parent entities in the fertilization process and cannot provide the child entity, as it will only exist at a later point in time. ++ */ ++@NullMarked ++public class EntityFertilizeEggEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final LivingEntity mother; ++ private final LivingEntity father; ++ private final @Nullable Player breeder; ++ private final @Nullable ItemStack bredWith; ++ private int experience; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityFertilizeEggEvent(final LivingEntity mother, final LivingEntity father, final @Nullable Player breeder, final @Nullable ItemStack bredWith, final int experience) { ++ super(mother); ++ this.mother = mother; ++ this.father = father; ++ this.breeder = breeder; ++ this.bredWith = bredWith; ++ this.experience = experience; ++ } ++ ++ @Override ++ public LivingEntity getEntity() { ++ return (LivingEntity) super.getEntity(); ++ } ++ ++ /** ++ * Provides the entity in the fertilization process that will eventually be responsible for "creating" offspring, ++ * may that be by setting a block that later hatches or dropping an egg that has to be placed. ++ * ++ * @return The "mother" entity. ++ */ ++ public LivingEntity getMother() { ++ return this.mother; ++ } ++ ++ /** ++ * Provides the "father" entity in the fertilization process that is not responsible for initiating the offspring ++ * creation. ++ * ++ * @return the other parent ++ */ ++ public LivingEntity getFather() { ++ return this.father; ++ } ++ ++ /** ++ * Gets the Entity responsible for fertilization. Breeder is {@code null} for spontaneous ++ * conception. ++ * ++ * @return The Entity who initiated fertilization. ++ */ ++ public @Nullable Player getBreeder() { ++ return this.breeder; ++ } ++ ++ /** ++ * The ItemStack that was used to initiate fertilization, if present. ++ * ++ * @return ItemStack used to initiate fertilization. ++ */ ++ public @Nullable ItemStack getBredWith() { ++ return this.bredWith; ++ } ++ ++ /** ++ * Get the amount of experience granted by fertilization. ++ * ++ * @return experience amount ++ */ ++ public int getExperience() { ++ return this.experience; ++ } ++ ++ /** ++ * Set the amount of experience granted by fertilization. ++ * If the amount is negative or zero, no experience will be dropped. ++ * ++ * @param experience experience amount ++ */ ++ public void setExperience(final int experience) { ++ this.experience = experience; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0388-Add-CompostItemEvent-and-EntityCompostItemEvent.patch b/patches/api/0388-Add-CompostItemEvent-and-EntityCompostItemEvent.patch new file mode 100644 index 000000000000..e639e46b4dec --- /dev/null +++ b/patches/api/0388-Add-CompostItemEvent-and-EntityCompostItemEvent.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Noah van der Aa +Date: Sat, 7 Aug 2021 15:11:27 +0200 +Subject: [PATCH] Add CompostItemEvent and EntityCompostItemEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/CompostItemEvent.java b/src/main/java/io/papermc/paper/event/block/CompostItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..03497ac2489b159716811f03ab68e345ff864fa6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/CompostItemEvent.java +@@ -0,0 +1,66 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when an item is about to be composted by a hopper. ++ * To prevent hoppers from moving items into composters, cancel the {@link InventoryMoveItemEvent}. ++ */ ++@NullMarked ++public class CompostItemEvent extends BlockEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final ItemStack item; ++ private boolean willRaiseLevel; ++ ++ @ApiStatus.Internal ++ public CompostItemEvent(final Block composter, final ItemStack item, final boolean willRaiseLevel) { ++ super(composter); ++ this.item = item; ++ this.willRaiseLevel = willRaiseLevel; ++ } ++ ++ /** ++ * Gets the item that was used on the composter. ++ * ++ * @return the item ++ */ ++ public ItemStack getItem() { ++ return this.item; ++ } ++ ++ /** ++ * Gets whether the composter will rise a level. ++ * ++ * @return {@code true} if successful ++ */ ++ public boolean willRaiseLevel() { ++ return this.willRaiseLevel; ++ } ++ ++ /** ++ * Sets whether the composter will rise a level. ++ * ++ * @param willRaiseLevel {@code true} if the composter should rise a level ++ */ ++ public void setWillRaiseLevel(final boolean willRaiseLevel) { ++ this.willRaiseLevel = willRaiseLevel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/event/entity/EntityCompostItemEvent.java b/src/main/java/io/papermc/paper/event/entity/EntityCompostItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..213d957fdc68aa32d77424c84c5cf3b244cd4314 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/EntityCompostItemEvent.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.event.entity; ++ ++import io.papermc.paper.event.block.CompostItemEvent; ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when an item is about to be composted by an entity. ++ */ ++@NullMarked ++public class EntityCompostItemEvent extends CompostItemEvent implements Cancellable { ++ ++ private final Entity entity; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public EntityCompostItemEvent(final Entity entity, final Block composter, final ItemStack item, final boolean willRaiseLevel) { ++ super(composter, item, willRaiseLevel); ++ this.entity = entity; ++ } ++ ++ /** ++ * Gets the entity that interacted with the composter. ++ * ++ * @return the entity that composted an item. ++ */ ++ public Entity getEntity() { ++ return this.entity; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++} diff --git a/patches/api/0389-Add-Shearable-API.patch b/patches/api/0389-Add-Shearable-API.patch new file mode 100644 index 000000000000..29875e12d92d --- /dev/null +++ b/patches/api/0389-Add-Shearable-API.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 17 Oct 2021 15:39:41 -0400 +Subject: [PATCH] Add Shearable API + + +diff --git a/src/main/java/io/papermc/paper/entity/Shearable.java b/src/main/java/io/papermc/paper/entity/Shearable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3991f2aa530c588f52e1f596d3b03743e8a8ecc4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/entity/Shearable.java +@@ -0,0 +1,44 @@ ++package io.papermc.paper.entity; ++ ++import net.kyori.adventure.sound.Sound; ++import org.bukkit.entity.Entity; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents an entity that can be sheared. ++ */ ++@NullMarked ++public interface Shearable extends Entity { ++ ++ /** ++ * Forces the entity to be sheared and then play the effect as if it were sheared by a player. ++ * This will cause the entity to be sheared, even if {@link Shearable#readyToBeSheared()} is false. ++ *

      ++ * Some shearing behavior may cause the entity to no longer be valid ++ * due to it being replaced by a different entity. ++ */ ++ default void shear() { ++ this.shear(Sound.Source.PLAYER); ++ } ++ ++ /** ++ * Forces the entity to be sheared and then play the effect as if it were sheared by the provided source. ++ * This will cause the entity to be sheared, even if {@link Shearable#readyToBeSheared()} is false. ++ *

      ++ * Some shearing behavior may cause the entity to no longer be valid ++ * due to it being replaced by a different entity. ++ *

      ++ * This simulates the behavior of an actual shearing, which may cause events like EntityTransformEvent to be called ++ * for mooshrooms, and EntityDropItemEvent to be called for sheep. ++ * ++ * @param source Sound source to play any sound effects on ++ */ ++ void shear(Sound.Source source); ++ ++ /** ++ * Gets if the entity would be able to be sheared or not naturally using shears. ++ * ++ * @return if the entity can be sheared ++ */ ++ boolean readyToBeSheared(); ++} +diff --git a/src/main/java/org/bukkit/entity/Bogged.java b/src/main/java/org/bukkit/entity/Bogged.java +index 0e5aaf54df0a5d0995147a905daef52442b070c5..6093b1dad8ad48708267a83bf4c1ad20467b3cf9 100644 +--- a/src/main/java/org/bukkit/entity/Bogged.java ++++ b/src/main/java/org/bukkit/entity/Bogged.java +@@ -6,7 +6,7 @@ import org.jetbrains.annotations.ApiStatus; + * Represents a Bogged Skeleton. + */ + @ApiStatus.Experimental +-public interface Bogged extends AbstractSkeleton, Shearable { ++public interface Bogged extends AbstractSkeleton, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API + + /** + * Gets whether the bogged is in its sheared state. +diff --git a/src/main/java/org/bukkit/entity/MushroomCow.java b/src/main/java/org/bukkit/entity/MushroomCow.java +index cef1700834643fe28ed5737578d91ecefbe99e2f..86c0043ef4e1288b6fe2f68a9b6d01c3de2c3454 100644 +--- a/src/main/java/org/bukkit/entity/MushroomCow.java ++++ b/src/main/java/org/bukkit/entity/MushroomCow.java +@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a mushroom {@link Cow} + */ +-public interface MushroomCow extends Cow { ++public interface MushroomCow extends Cow, io.papermc.paper.entity.Shearable { // Paper + + /** + * Checks for the presence of custom potion effects to be applied to the +diff --git a/src/main/java/org/bukkit/entity/Shearable.java b/src/main/java/org/bukkit/entity/Shearable.java +index 0215d20f81bfbef080f86ce46147a38f71310f65..9967c8a52ddd2c7e10db49a3f166731373f1ba45 100644 +--- a/src/main/java/org/bukkit/entity/Shearable.java ++++ b/src/main/java/org/bukkit/entity/Shearable.java +@@ -2,20 +2,30 @@ package org.bukkit.entity; + + /** + * Represents an entity which can be shorn with shears. ++ * @deprecated Spigots shearable API miserably fails at capturing all entities that may be sheared by a player, like ++ * mushroom cows which, once sheared, convert into normal cows. For such entities, methods like ++ * {@link #setSheared(boolean)} or {@link #isSheared()} make no sense, making this API and interface dead API from ++ * the get-go. + */ ++@Deprecated(forRemoval = true, since = "1.21") + public interface Shearable { + + /** + * Gets whether the entity is in its sheared state. + * + * @return Whether the entity is sheared. ++ * @deprecated Use {@link io.papermc.paper.entity.Shearable#readyToBeSheared()} instead. + */ ++ @Deprecated(forRemoval = true, since = "1.21") + boolean isSheared(); + + /** + * Sets whether the entity is in its sheared state. + * + * @param flag Whether to shear the entity ++ * @deprecated Use {@link io.papermc.paper.entity.Shearable#shear()} instead if applicable. ++ * Some entities cannot be "unsheared". + */ ++ @Deprecated(forRemoval = true, since = "1.21") + void setSheared(boolean flag); + } +diff --git a/src/main/java/org/bukkit/entity/Sheep.java b/src/main/java/org/bukkit/entity/Sheep.java +index 9ed473e5e993ef2d9558fe18bbcea7dad9b42994..f67f478945a7ba99bf72601678a153553526799a 100644 +--- a/src/main/java/org/bukkit/entity/Sheep.java ++++ b/src/main/java/org/bukkit/entity/Sheep.java +@@ -5,7 +5,7 @@ import org.bukkit.material.Colorable; + /** + * Represents a Sheep. + */ +-public interface Sheep extends Animals, Colorable, Shearable { ++public interface Sheep extends Animals, Colorable, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API + + /** + * Gets whether the sheep is in its sheared state. +diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java +index 10f8f6d45ae9280651c3ebddd1f90acbd7d6ff29..7fbfdb07585c7b28acea1f0c1f58ada0cc744441 100644 +--- a/src/main/java/org/bukkit/entity/Snowman.java ++++ b/src/main/java/org/bukkit/entity/Snowman.java +@@ -5,7 +5,7 @@ import com.destroystokyo.paper.entity.RangedEntity; + /** + * Represents a snowman entity + */ +-public interface Snowman extends Golem, RangedEntity { // Paper ++public interface Snowman extends Golem, RangedEntity, io.papermc.paper.entity.Shearable { // Paper + + /** + * Gets whether this snowman is in "derp mode", meaning it is not wearing a diff --git a/patches/api/0390-Fix-SpawnEggMeta-get-setSpawnedType.patch b/patches/api/0390-Fix-SpawnEggMeta-get-setSpawnedType.patch new file mode 100644 index 000000000000..6eeaa9736fe2 --- /dev/null +++ b/patches/api/0390-Fix-SpawnEggMeta-get-setSpawnedType.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 26 Feb 2023 07:14:19 -0800 +Subject: [PATCH] Fix SpawnEggMeta#get/setSpawnedType + + +diff --git a/src/main/java/org/bukkit/inventory/meta/SpawnEggMeta.java b/src/main/java/org/bukkit/inventory/meta/SpawnEggMeta.java +index 2151946cf791c4c37b2ad527fe20bd784a037190..159055dfc6bd1eb77e07c5eb199c3ae892a749e0 100644 +--- a/src/main/java/org/bukkit/inventory/meta/SpawnEggMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/SpawnEggMeta.java +@@ -17,7 +17,7 @@ public interface SpawnEggMeta extends ItemMeta { + * @return The entity type. May be null for implementation specific default. + * @deprecated different types are different items + */ +- @Deprecated(since = "1.13") ++ @Deprecated(since = "1.13", forRemoval = true) // Paper + @Contract("-> fail") + EntityType getSpawnedType(); + +@@ -28,7 +28,7 @@ public interface SpawnEggMeta extends ItemMeta { + * default. + * @deprecated different types are different items + */ +- @Deprecated(since = "1.13") ++ @Deprecated(since = "1.13", forRemoval = true) // Paper + @Contract("_ -> fail") + void setSpawnedType(EntityType type); + +@@ -54,6 +54,22 @@ public interface SpawnEggMeta extends ItemMeta { + */ + void setSpawnedEntity(@NotNull EntitySnapshot snapshot); + ++ // Paper start ++ /** ++ * Get the custom type of entity this egg will spawn. ++ * ++ * @return the entity type or null if no custom type is set ++ */ ++ @org.jetbrains.annotations.Nullable EntityType getCustomSpawnedType(); ++ ++ /** ++ * Set the custom type of entity this egg will spawn. ++ * ++ * @param type the entity type or null to clear the custom type ++ */ ++ void setCustomSpawnedType(@org.jetbrains.annotations.Nullable EntityType type); ++ // Paper end ++ + @NotNull + @Override + SpawnEggMeta clone(); diff --git a/patches/api/0391-Add-Mob-Experience-reward-API.patch b/patches/api/0391-Add-Mob-Experience-reward-API.patch new file mode 100644 index 000000000000..354d6d1eb467 --- /dev/null +++ b/patches/api/0391-Add-Mob-Experience-reward-API.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: GodOfPro <1387ilia@gmail.com> +Date: Tue, 11 Apr 2023 16:30:58 +0430 +Subject: [PATCH] Add Mob Experience reward API + + +diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java +index d55250d820b02f3a23b99a59e68d3361698baddf..256e5645bcfa76e7ede58ae365e69b4a4bed6204 100644 +--- a/src/main/java/org/bukkit/entity/Mob.java ++++ b/src/main/java/org/bukkit/entity/Mob.java +@@ -220,4 +220,13 @@ public interface Mob extends LivingEntity, Lootable { + */ + public void setLeftHanded(boolean leftHanded); + // Paper end - left-handed API ++ ++ // Paper start - mob xp reward API ++ /** ++ * Gets the amount of experience the mob will possibly drop. This value is randomized and it can give different results ++ * ++ * @return the amount of experience the mob will possibly drop ++ */ ++ public int getPossibleExperienceReward(); ++ // Paper end - mob xp reward API + } diff --git a/patches/api/0392-Expand-PlayerItemMendEvent.patch b/patches/api/0392-Expand-PlayerItemMendEvent.patch new file mode 100644 index 000000000000..d13509496bc0 --- /dev/null +++ b/patches/api/0392-Expand-PlayerItemMendEvent.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 20 Jan 2022 18:11:44 -0800 +Subject: [PATCH] Expand PlayerItemMendEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerItemMendEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemMendEvent.java +index cfbd0b42ae0d7c083467e9c3139fd1ed99d9e94b..f0533271dd38276e210061f8767a8acc0fef2a64 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerItemMendEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerItemMendEvent.java +@@ -6,6 +6,7 @@ import org.bukkit.event.Cancellable; + import org.bukkit.event.HandlerList; + import org.bukkit.inventory.EquipmentSlot; + import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.Contract; + import org.jetbrains.annotations.NotNull; + + /** +@@ -23,14 +24,67 @@ public class PlayerItemMendEvent extends PlayerEvent implements Cancellable { + private final ExperienceOrb experienceOrb; + private int repairAmount; + private boolean cancelled; ++ private final int consumedExperience; // Paper + ++ @Deprecated // Paper + public PlayerItemMendEvent(@NotNull Player who, @NotNull ItemStack item, @NotNull EquipmentSlot slot, @NotNull ExperienceOrb experienceOrb, int repairAmount) { ++ // Paper start ++ this(who, item, slot, experienceOrb, repairAmount, repairAmount / 2); ++ } ++ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PlayerItemMendEvent(@NotNull Player who, @NotNull ItemStack item, @NotNull EquipmentSlot slot, @NotNull ExperienceOrb experienceOrb, int repairAmount, int consumedExperience) { ++ // Paper end + super(who); + this.item = item; + this.slot = slot; + this.experienceOrb = experienceOrb; + this.repairAmount = repairAmount; ++ // Paper start ++ this.consumedExperience = consumedExperience; ++ } ++ ++ /** ++ * Get the operation used to calculate xp used based on ++ * the set repair amount. Used to calculate how much of ++ * an XP orb will be consumed by this mend operation. ++ * ++ * @return the durability-to-xp operation ++ * @deprecated the mending enchantment uses enchantment effects to compute how much durability is granted per xp. ++ * The enchantment effects operation are too complex to reliably offer the inverse function. ++ */ ++ @Contract("-> fail") ++ @Deprecated(forRemoval = true, since = "1.21") ++ public @NotNull java.util.function.IntUnaryOperator getDurabilityToXpOperation() { ++ throw new UnsupportedOperationException("Enchantments use effects to compute xp to durability since 1.21."); ++ } ++ ++ /** ++ * Sets the operation used to calculate xp used based on ++ * the set repair amount. Used to calculate how much of ++ * an XP orb will be consumed by this mend operation. ++ * ++ * @param durabilityToXpOp the durability-to-xp operation ++ * @deprecated the mending enchantment uses enchantment effects to compute how much durability is granted per xp. ++ * The enchantment effects operation are too complex to reliably offer the inverse function. ++ */ ++ @Contract("_ -> fail") ++ @Deprecated(forRemoval = true, since = "1.21") ++ public void setDurabilityToXpOperation(@NotNull java.util.function.IntUnaryOperator durabilityToXpOp) { ++ throw new UnsupportedOperationException("Enchantments use effects to compute xp to durability since 1.21."); ++ } ++ ++ /** ++ * Helper method to get the amount of experience that will be consumed. ++ * This method just returns the result of inputting {@link #getRepairAmount()} ++ * into the function {@link #getDurabilityToXpOperation()}. ++ * ++ * @return the amount of xp that will be consumed ++ */ ++ public int getConsumedExperience() { ++ return this.consumedExperience; + } ++ // Paper end + + @Deprecated(since = "1.19.2") + public PlayerItemMendEvent(@NotNull Player who, @NotNull ItemStack item, @NotNull ExperienceOrb experienceOrb, int repairAmount) { diff --git a/patches/api/0393-Add-method-to-remove-all-active-potion-effects.patch b/patches/api/0393-Add-method-to-remove-all-active-potion-effects.patch new file mode 100644 index 000000000000..cbbc90e94a21 --- /dev/null +++ b/patches/api/0393-Add-method-to-remove-all-active-potion-effects.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 17 Jun 2023 13:17:20 -0700 +Subject: [PATCH] Add method to remove all active potion effects + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 8375ec85b78378f6ebc0a970fb0df205feb984e7..7cc29c7a9e2c30feaedaab188024387e12f51c75 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -657,6 +657,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + @NotNull + public Collection getActivePotionEffects(); + ++ // Paper start - LivingEntity#clearActivePotionEffects(); ++ /** ++ * Removes all active potion effects for this entity. ++ * ++ * @return true if any were removed ++ */ ++ boolean clearActivePotionEffects(); ++ // Paper end ++ + /** + * Checks whether the living entity has block line of sight to another. + *

      diff --git a/patches/api/0394-Folia-scheduler-and-owned-region-API.patch b/patches/api/0394-Folia-scheduler-and-owned-region-API.patch new file mode 100644 index 000000000000..6017268d79c0 --- /dev/null +++ b/patches/api/0394-Folia-scheduler-and-owned-region-API.patch @@ -0,0 +1,832 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 17 Jun 2023 11:52:41 +0200 +Subject: [PATCH] Folia scheduler and owned region API + +Pulling Folia API to Paper is primarily intended for plugins +that want to target both Paper and Folia without unnecessary +compatibility layers. + +Add both a location based scheduler, an entity based scheduler, +and a global region scheduler. + +Owned region API may be useful for plugins which want to perform +operations over large areas outside of the buffer zone provided +by the regionaliser, as it is not guaranteed that anything +outside of the buffer zone is owned. Then, the plugins may use +the schedulers depending on the result of the ownership check. + +diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9852e14e68d12ca56b0d57cd6e83e252f47bde72 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/AsyncScheduler.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.threadedregions.scheduler; ++ ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.concurrent.TimeUnit; ++import java.util.function.Consumer; ++ ++/** ++ * Scheduler that may be used by plugins to schedule tasks to execute asynchronously from the server tick process. ++ */ ++public interface AsyncScheduler { ++ ++ /** ++ * Schedules the specified task to be executed asynchronously immediately. ++ * @param plugin Plugin which owns the specified task. ++ * @param task Specified task. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runNow(@NotNull Plugin plugin, @NotNull Consumer task); ++ ++ /** ++ * Schedules the specified task to be executed asynchronously after the time delay has passed. ++ * @param plugin Plugin which owns the specified task. ++ * @param task Specified task. ++ * @param delay The time delay to pass before the task should be executed. ++ * @param unit The time unit for the time delay. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer task, long delay, ++ @NotNull TimeUnit unit); ++ ++ /** ++ * Schedules the specified task to be executed asynchronously after the initial delay has passed, ++ * and then periodically executed with the specified period. ++ * @param plugin Plugin which owns the specified task. ++ * @param task Specified task. ++ * @param initialDelay The time delay to pass before the first execution of the task. ++ * @param period The time between task executions after the first execution of the task. ++ * @param unit The time unit for the initial delay and period. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer task, ++ long initialDelay, long period, @NotNull TimeUnit unit); ++ ++ /** ++ * Attempts to cancel all tasks scheduled by the specified plugin. ++ * @param plugin Specified plugin. ++ */ ++ void cancelTasks(@NotNull Plugin plugin); ++} +diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..99e9e20ae01f9b4b8cde585d29c57e27c53c996e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/EntityScheduler.java +@@ -0,0 +1,104 @@ ++package io.papermc.paper.threadedregions.scheduler; ++ ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.function.Consumer; ++ ++/** ++ * An entity can move between worlds with an arbitrary tick delay, be temporarily removed ++ * for players (i.e end credits), be partially removed from world state (i.e inactive but not removed), ++ * teleport between ticking regions, teleport between worlds, and even be removed entirely from the server. ++ * The uncertainty of an entity's state can make it difficult to schedule tasks without worrying about undefined ++ * behaviors resulting from any of the states listed previously. ++ * ++ *

      ++ * This class is designed to eliminate those states by providing an interface to run tasks only when an entity ++ * is contained in a world, on the owning thread for the region, and by providing the current Entity object. ++ * The scheduler also allows a task to provide a callback, the "retired" callback, that will be invoked ++ * if the entity is removed before a task that was scheduled could be executed. The scheduler is also ++ * completely thread-safe, allowing tasks to be scheduled from any thread context. The scheduler also indicates ++ * properly whether a task was scheduled successfully (i.e scheduler not retired), thus the code scheduling any task ++ * knows whether the given callbacks will be invoked eventually or not - which may be critical for off-thread ++ * contexts. ++ *

      ++ */ ++public interface EntityScheduler { ++ ++ /** ++ * Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity ++ * removed), then returns {@code false}. Otherwise, either the run callback will be invoked after the specified delay, ++ * or the retired callback will be invoked if the scheduler is retired. ++ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove ++ * other entities, load chunks, load worlds, modify ticket levels, etc. ++ * ++ *

      ++ * It is guaranteed that the run and retired callback are invoked on the region which owns the entity. ++ *

      ++ * @param run The callback to run after the specified delay, may not be null. ++ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null. ++ * @param delay The delay in ticks before the run callback is invoked. Any value less-than 1 is treated as 1. ++ * @return {@code true} if the task was scheduled, which means that either the run function or the retired function ++ * will be invoked (but never both), or {@code false} indicating neither the run nor retired function will be invoked ++ * since the scheduler has been retired. ++ */ ++ boolean execute(@NotNull Plugin plugin, @NotNull Runnable run, @Nullable Runnable retired, long delay); ++ ++ /** ++ * Schedules a task to execute on the next tick. If the task failed to schedule because the scheduler is retired (entity ++ * removed), then returns {@code null}. Otherwise, either the task callback will be invoked after the specified delay, ++ * or the retired callback will be invoked if the scheduler is retired. ++ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove ++ * other entities, load chunks, load worlds, modify ticket levels, etc. ++ * ++ *

      ++ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity. ++ *

      ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null. ++ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed. ++ */ ++ @Nullable ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer task, ++ @Nullable Runnable retired); ++ ++ /** ++ * Schedules a task with the given delay. If the task failed to schedule because the scheduler is retired (entity ++ * removed), then returns {@code null}. Otherwise, either the task callback will be invoked after the specified delay, ++ * or the retired callback will be invoked if the scheduler is retired. ++ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove ++ * other entities, load chunks, load worlds, modify ticket levels, etc. ++ * ++ *

      ++ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity. ++ *

      ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null. ++ * @param delayTicks The delay, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed. ++ */ ++ @Nullable ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer task, ++ @Nullable Runnable retired, long delayTicks); ++ ++ /** ++ * Schedules a repeating task with the given delay and period. If the task failed to schedule because the scheduler ++ * is retired (entity removed), then returns {@code null}. Otherwise, either the task callback will be invoked after ++ * the specified delay, or the retired callback will be invoked if the scheduler is retired. ++ * Note that the retired callback is invoked in critical code, so it should not attempt to remove the entity, remove ++ * other entities, load chunks, load worlds, modify ticket levels, etc. ++ * ++ *

      ++ * It is guaranteed that the task and retired callback are invoked on the region which owns the entity. ++ *

      ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @param retired Retire callback to run if the entity is retired before the run callback can be invoked, may be null. ++ * @param initialDelayTicks The initial delay, in ticks. ++ * @param periodTicks The period, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task, or {@code null} if the entity has been removed. ++ */ ++ @Nullable ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer task, ++ @Nullable Runnable retired, long initialDelayTicks, long periodTicks); ++} +diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..57455aca80ecc458b96b44c086cea94ddcecae47 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java +@@ -0,0 +1,58 @@ ++package io.papermc.paper.threadedregions.scheduler; ++ ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.function.Consumer; ++ ++/** ++ * The global region task scheduler may be used to schedule tasks that will execute on the global region. ++ *

      ++ * The global region is responsible for maintaining world day time, world game time, weather cycle, ++ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region. ++ *

      ++ */ ++public interface GlobalRegionScheduler { ++ ++ /** ++ * Schedules a task to be executed on the global region. ++ * @param plugin The plugin that owns the task ++ * @param run The task to execute ++ */ ++ void execute(@NotNull Plugin plugin, @NotNull Runnable run); ++ ++ /** ++ * Schedules a task to be executed on the global region on the next tick. ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Consumer task); ++ ++ /** ++ * Schedules a task to be executed on the global region after the specified delay in ticks. ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @param delayTicks The delay, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Consumer task, long delayTicks); ++ ++ /** ++ * Schedules a repeating task to be executed on the global region after the initial delay with the ++ * specified period. ++ * @param plugin The plugin that owns the task ++ * @param task The task to execute ++ * @param initialDelayTicks The initial delay, in ticks. ++ * @param periodTicks The period, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Consumer task, ++ long initialDelayTicks, long periodTicks); ++ ++ /** ++ * Attempts to cancel all tasks scheduled by the specified plugin. ++ * @param plugin Specified plugin. ++ */ ++ void cancelTasks(@NotNull Plugin plugin); ++} +diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7557e170f84cde7292869fbd92b44b0e6eb43b4f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/RegionScheduler.java +@@ -0,0 +1,127 @@ ++package io.papermc.paper.threadedregions.scheduler; ++ ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.entity.Entity; ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.function.Consumer; ++ ++/** ++ * The region task scheduler can be used to schedule tasks by location to be executed on the region which owns the location. ++ *

      ++ * Note: It is entirely inappropriate to use the region scheduler to schedule tasks for entities. ++ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()} ++ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler ++ * will not. ++ *

      ++ */ ++public interface RegionScheduler { ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location. ++ * ++ * @param plugin The plugin that owns the task ++ * @param world The world of the region that owns the task ++ * @param chunkX The chunk X coordinate of the region that owns the task ++ * @param chunkZ The chunk Z coordinate of the region that owns the task ++ * @param run The task to execute ++ */ ++ void execute(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Runnable run); ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location. ++ * ++ * @param plugin The plugin that owns the task ++ * @param location The location at which the region executing should own ++ * @param run The task to execute ++ */ ++ default void execute(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable run) { ++ this.execute(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, run); ++ } ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location on the next tick. ++ * ++ * @param plugin The plugin that owns the task ++ * @param world The world of the region that owns the task ++ * @param chunkX The chunk X coordinate of the region that owns the task ++ * @param chunkZ The chunk Z coordinate of the region that owns the task ++ * @param task The task to execute ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer task); ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location on the next tick. ++ * ++ * @param plugin The plugin that owns the task ++ * @param location The location at which the region executing should own ++ * @param task The task to execute ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ default @NotNull ScheduledTask run(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer task) { ++ return this.run(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task); ++ } ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks. ++ * ++ * @param plugin The plugin that owns the task ++ * @param world The world of the region that owns the task ++ * @param chunkX The chunk X coordinate of the region that owns the task ++ * @param chunkZ The chunk Z coordinate of the region that owns the task ++ * @param task The task to execute ++ * @param delayTicks The delay, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer task, ++ long delayTicks); ++ ++ /** ++ * Schedules a task to be executed on the region which owns the location after the specified delay in ticks. ++ * ++ * @param plugin The plugin that owns the task ++ * @param location The location at which the region executing should own ++ * @param task The task to execute ++ * @param delayTicks The delay, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ default @NotNull ScheduledTask runDelayed(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer task, ++ long delayTicks) { ++ return this.runDelayed(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks); ++ } ++ ++ /** ++ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the ++ * specified period. ++ * ++ * @param plugin The plugin that owns the task ++ * @param world The world of the region that owns the task ++ * @param chunkX The chunk X coordinate of the region that owns the task ++ * @param chunkZ The chunk Z coordinate of the region that owns the task ++ * @param task The task to execute ++ * @param initialDelayTicks The initial delay, in ticks. ++ * @param periodTicks The period, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull World world, int chunkX, int chunkZ, @NotNull Consumer task, ++ long initialDelayTicks, long periodTicks); ++ ++ /** ++ * Schedules a repeating task to be executed on the region which owns the location after the initial delay with the ++ * specified period. ++ * ++ * @param plugin The plugin that owns the task ++ * @param location The location at which the region executing should own ++ * @param task The task to execute ++ * @param initialDelayTicks The initial delay, in ticks. ++ * @param periodTicks The period, in ticks. ++ * @return The {@link ScheduledTask} that represents the scheduled task. ++ */ ++ default @NotNull ScheduledTask runAtFixedRate(@NotNull Plugin plugin, @NotNull Location location, @NotNull Consumer task, ++ long initialDelayTicks, long periodTicks) { ++ return this.runAtFixedRate(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, initialDelayTicks, periodTicks); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a6b50c9d8af589cc4747e14d343d2045216c249c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/ScheduledTask.java +@@ -0,0 +1,112 @@ ++package io.papermc.paper.threadedregions.scheduler; ++ ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents a task scheduled to a scheduler. ++ */ ++public interface ScheduledTask { ++ ++ /** ++ * Returns the plugin that scheduled this task. ++ * @return the plugin that scheduled this task. ++ */ ++ @NotNull Plugin getOwningPlugin(); ++ ++ /** ++ * Returns whether this task executes on a fixed period, as opposed to executing only once. ++ * @return whether this task executes on a fixed period, as opposed to executing only once. ++ */ ++ boolean isRepeatingTask(); ++ ++ /** ++ * Attempts to cancel this task, returning the result of the attempt. In all cases, if the task is currently ++ * being executed no attempt is made to halt the task, however any executions in the future are halted. ++ * @return the result of the cancellation attempt. ++ */ ++ @NotNull CancelledState cancel(); ++ ++ /** ++ * Returns the current execution state of this task. ++ * @return the current execution state of this task. ++ */ ++ @NotNull ExecutionState getExecutionState(); ++ ++ /** ++ * Returns whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}. ++ * @return whether the current execution state is {@link ExecutionState#CANCELLED} or {@link ExecutionState#CANCELLED_RUNNING}. ++ */ ++ default boolean isCancelled() { ++ final ExecutionState state = this.getExecutionState(); ++ return state == ExecutionState.CANCELLED || state == ExecutionState.CANCELLED_RUNNING; ++ } ++ ++ /** ++ * Represents the result of attempting to cancel a task. ++ */ ++ enum CancelledState { ++ /** ++ * The task (repeating or not) has been successfully cancelled by the caller thread. The task is not executing ++ * currently, and it will not begin execution in the future. ++ */ ++ CANCELLED_BY_CALLER, ++ /** ++ * The task (repeating or not) is already cancelled. The task is not executing currently, and it will not ++ * begin execution in the future. ++ */ ++ CANCELLED_ALREADY, ++ ++ /** ++ * The task is not a repeating task, and could not be cancelled because the task is being executed. ++ */ ++ RUNNING, ++ /** ++ * The task is not a repeating task, and could not be cancelled because the task has already finished execution. ++ */ ++ ALREADY_EXECUTED, ++ ++ /** ++ * The caller thread successfully stopped future executions of a repeating task, but the task is currently ++ * being executed. ++ */ ++ NEXT_RUNS_CANCELLED, ++ ++ /** ++ * The repeating task's future executions are cancelled already, but the task is currently ++ * being executed. ++ */ ++ NEXT_RUNS_CANCELLED_ALREADY, ++ } ++ ++ /** ++ * Represents the current execution state of the task. ++ */ ++ enum ExecutionState { ++ /** ++ * The task is currently not executing, but may begin execution in the future. ++ */ ++ IDLE, ++ ++ /** ++ * The task is currently executing. ++ */ ++ RUNNING, ++ ++ /** ++ * The task is not repeating, and the task finished executing. ++ */ ++ FINISHED, ++ ++ /** ++ * The task is not executing and will not begin execution in the future. If this task is not repeating, then ++ * this task was never executed. ++ */ ++ CANCELLED, ++ ++ /** ++ * The task is repeating and currently executing, but future executions are cancelled and will not occur. ++ */ ++ CANCELLED_RUNNING; ++ } ++} +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 629d062b76ff4186cc5c824b1bdcafe3667b50fe..5170f7ba71d8a09f2b4ae0d945c758fd4ae4130f 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2696,6 +2696,164 @@ public final class Bukkit { + } + // Paper end + ++ // Paper start - Folia region threading API ++ /** ++ * Returns the region task scheduler. The region task scheduler can be used to schedule ++ * tasks by location to be executed on the region which owns the location. ++ *

      ++ * Note: It is entirely inappropriate to use the region scheduler to schedule tasks for entities. ++ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()} ++ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler ++ * will not. ++ *

      ++ *

      If you do not need/want to make your plugin run on Folia, use {@link #getScheduler()} instead.

      ++ * @return the region task scheduler ++ */ ++ public static @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler() { ++ return server.getRegionScheduler(); ++ } ++ ++ /** ++ * Returns the async task scheduler. The async task scheduler can be used to schedule tasks ++ * that execute asynchronously from the server tick process. ++ * @return the async task scheduler ++ */ ++ public static @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler() { ++ return server.getAsyncScheduler(); ++ } ++ ++ /** ++ * Returns the global region task scheduler. The global task scheduler can be used to schedule ++ * tasks to execute on the global region. ++ *

      ++ * The global region is responsible for maintaining world day time, world game time, weather cycle, ++ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region. ++ *

      ++ *

      If you do not need/want to make your plugin run on Folia, use {@link #getScheduler()} instead.

      ++ * @return the global region scheduler ++ */ ++ public static @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler() { ++ return server.getGlobalRegionScheduler(); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position. ++ * @param world Specified world. ++ * @param position Specified block position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position) { ++ return server.isOwnedByCurrentRegion(world, position); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified block position within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param position Specified block position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(world, position, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position as included in the specified location. ++ * @param location Specified location, must have a non-null world. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Location location) { ++ return server.isOwnedByCurrentRegion(location); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and block position as included in the specified location ++ * within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param location Specified location, must have a non-null world. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(location, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified block position. ++ * @param block Specified block position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block) { ++ return server.isOwnedByCurrentRegion(block.getLocation()); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and chunk position. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ) { ++ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and chunk position within the specified ++ * square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks) { ++ return server.isOwnedByCurrentRegion(world, chunkX, chunkZ, squareRadiusChunks); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks in the rectangle specified by the min and max parameters. ++ * Specifically, this function checks that every chunk with position x in [minChunkX, maxChunkX] and ++ * position z in [minChunkZ, maxChunkZ] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param minChunkX Specified x-coordinate of the minimum chunk position. ++ * @param minChunkZ Specified z-coordinate of the minimum chunk position. ++ * @param maxChunkX Specified x-coordinate of the maximum chunk position. ++ * @param maxChunkZ Specified z-coordinate of the maximum chunk position. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull World world, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ) { ++ return server.isOwnedByCurrentRegion(world, minChunkX, minChunkZ, maxChunkX, maxChunkZ); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the specified entity. Note that this function is the only appropriate method of checking ++ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned ++ * by the current region. ++ * @param entity Specified entity. ++ */ ++ public static boolean isOwnedByCurrentRegion(@NotNull Entity entity) { ++ return server.isOwnedByCurrentRegion(entity); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking the global region. ++ * @see io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler ++ */ ++ public static boolean isGlobalTickThread() { ++ return server.isGlobalTickThread(); ++ } ++ // Paper end - Folia region threading API ++ + @NotNull + public static Server.Spigot spigot() { + return server.spigot(); +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 3f21dfaaa8a6575c9f9b0d33b60fb9913fec8987..d05ea34d8f58b475628157a7bd2ba0143e9a6c36 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2351,4 +2351,138 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer(); + // Paper end ++ ++ // Paper start - Folia region threading API ++ /** ++ * Returns the Folia region task scheduler. The region task scheduler can be used to schedule ++ * tasks by location to be executed on the region which owns the location. ++ *

      ++ * Note: It is entirely inappropriate to use the region scheduler to schedule tasks for entities. ++ * If you wish to schedule tasks to perform actions on entities, you should be using {@link Entity#getScheduler()} ++ * as the entity scheduler will "follow" an entity if it is teleported, whereas the region task scheduler ++ * will not. ++ *

      ++ *

      If you do not need/want to make your plugin run on Folia, use {@link #getScheduler()} instead.

      ++ * @return the region task scheduler ++ */ ++ @NotNull io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler(); ++ ++ /** ++ * Returns the Folia async task scheduler. The async task scheduler can be used to schedule tasks ++ * that execute asynchronously from the server tick process. ++ * @return the async task scheduler ++ */ ++ @NotNull io.papermc.paper.threadedregions.scheduler.AsyncScheduler getAsyncScheduler(); ++ ++ /** ++ * Returns the Folia global region task scheduler. The global task scheduler can be used to schedule ++ * tasks to execute on the global region. ++ *

      ++ * The global region is responsible for maintaining world day time, world game time, weather cycle, ++ * sleep night skipping, executing commands for console, and other misc. tasks that do not belong to any specific region. ++ *

      ++ *

      If you do not need/want to make your plugin run on Folia, use {@link #getScheduler()} instead.

      ++ * @return the global region scheduler ++ */ ++ @NotNull io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler getGlobalRegionScheduler(); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position. ++ * @param world Specified world. ++ * @param position Specified block position. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified block position within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param position Specified block position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull World world, @NotNull io.papermc.paper.math.Position position, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and block position as included in the specified location. ++ * @param location Specified location, must have a non-null world. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull Location location); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and block position as included in the specified location ++ * within the specified square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param location Specified location, must have a non-null world. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull Location location, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified block position. ++ * @param block Specified block position. ++ */ ++ default boolean isOwnedByCurrentRegion(@NotNull org.bukkit.block.Block block) { ++ return isOwnedByCurrentRegion(block.getLocation()); ++ } ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunk at the specified world and chunk position. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks centered at the specified world and chunk position within the specified ++ * square radius. ++ * Specifically, this function checks that every chunk with position x in [centerX - radius, centerX + radius] and ++ * position z in [centerZ - radius, centerZ + radius] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param chunkX Specified x-coordinate of the chunk position. ++ * @param chunkZ Specified z-coordinate of the chunk position. ++ * @param squareRadiusChunks Specified square radius. Must be >= 0. Note that this parameter is not a squared ++ * radius, but rather a Chebyshev Distance. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull World world, int chunkX, int chunkZ, int squareRadiusChunks); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the chunks in the rectangle specified by the min and max parameters. ++ * Specifically, this function checks that every chunk with position x in [minChunkX, maxChunkX] and ++ * position z in [minChunkZ, maxChunkZ] is owned by the current ticking region. ++ * @param world Specified world. ++ * @param minChunkX Specified x-coordinate of the minimum chunk position. ++ * @param minChunkZ Specified z-coordinate of the minimum chunk position. ++ * @param maxChunkX Specified x-coordinate of the maximum chunk position. ++ * @param maxChunkZ Specified z-coordinate of the maximum chunk position. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull World world, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ); ++ ++ /** ++ * Returns whether the current thread is ticking a region and that the region being ticked ++ * owns the specified entity. Note that this function is the only appropriate method of checking ++ * for ownership of an entity, as retrieving the entity's location is undefined unless the entity is owned ++ * by the current region. ++ * @param entity Specified entity. ++ */ ++ boolean isOwnedByCurrentRegion(@NotNull Entity entity); ++ ++ /** ++ * Returns whether the current thread is ticking the global region. ++ * @see io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler ++ */ ++ public boolean isGlobalTickThread(); ++ // Paper end - Folia region threading API + } +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 0ca7cb73c4007647841ed6a78c8949fcc3ed97ff..e196b66c02b5ba9ca35df804182f9b7ab4f7b45c 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -1101,4 +1101,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + boolean wouldCollideUsing(@NotNull BoundingBox boundingBox); + // Paper end - Collision API ++ ++ // Paper start - Folia schedulers ++ /** ++ * Returns the task scheduler for this entity. The entity scheduler can be used to schedule tasks ++ * that are guaranteed to always execute on the tick thread that owns the entity. ++ *

      If you do not need/want to make your plugin run on Folia, use {@link org.bukkit.Server#getScheduler()} instead.

      ++ * @return the task scheduler for this entity. ++ * @see io.papermc.paper.threadedregions.scheduler.EntityScheduler ++ */ ++ @NotNull io.papermc.paper.threadedregions.scheduler.EntityScheduler getScheduler(); ++ // Paper end - Folia schedulers + } diff --git a/patches/api/0395-Add-event-for-player-editing-sign.patch b/patches/api/0395-Add-event-for-player-editing-sign.patch new file mode 100644 index 000000000000..c0b95f9d58e6 --- /dev/null +++ b/patches/api/0395-Add-event-for-player-editing-sign.patch @@ -0,0 +1,132 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: by77er +Date: Sat, 10 Jun 2023 19:06:24 -0400 +Subject: [PATCH] Add event for player editing sign + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerOpenSignEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerOpenSignEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b905aafe5b228993944af1850c93c797f6eaf47 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerOpenSignEvent.java +@@ -0,0 +1,105 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.block.Sign; ++import org.bukkit.block.sign.Side; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when a player begins editing a sign's text. ++ *

      ++ * Cancelling this event stops the sign editing menu from opening. ++ */ ++@NullMarked ++public class PlayerOpenSignEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Sign sign; ++ private final Side side; ++ private final Cause cause; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PlayerOpenSignEvent(final Player editor, final Sign sign, final Side side, final Cause cause) { ++ super(editor); ++ this.sign = sign; ++ this.side = side; ++ this.cause = cause; ++ } ++ ++ /** ++ * Gets the sign that was clicked. ++ * ++ * @return {@link Sign} that was clicked ++ */ ++ public Sign getSign() { ++ return this.sign; ++ } ++ ++ /** ++ * Gets which side of the sign was clicked. ++ * ++ * @return {@link Side} that was clicked ++ * @see Sign#getSide(Side) ++ */ ++ public Side getSide() { ++ return this.side; ++ } ++ ++ /** ++ * The cause of this sign open. ++ * ++ * @return the cause ++ */ ++ public Cause getCause() { ++ return this.cause; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ /** ++ * The cause of the {@link PlayerOpenSignEvent}. ++ */ ++ public enum Cause { ++ /** ++ * The event was triggered by the placement of a sign. ++ */ ++ PLACE, ++ /** ++ * The event was triggered by an interaction with a sign. ++ */ ++ INTERACT, ++ /** ++ * The event was triggered via a plugin with {@link HumanEntity#openSign(Sign, Side)} ++ */ ++ PLUGIN, ++ /** ++ * Fallback cause for any unknown cause. ++ */ ++ UNKNOWN, ++ } ++} +diff --git a/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java b/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java +index cf935d9c8d8f9a9684024507846a9754f0207986..72fe69c3830f07dd264cfd89e92410dc107034a4 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java +@@ -9,7 +9,10 @@ import org.jetbrains.annotations.NotNull; + + /** + * This event is fired when a sign is opened by the player. ++ * @deprecated use {@link io.papermc.paper.event.player.PlayerOpenSignEvent} + */ ++@Deprecated(forRemoval = true) // Paper ++@org.bukkit.Warning(false) // Paper + public class PlayerSignOpenEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); diff --git a/patches/api/0396-More-Sign-Block-API.patch b/patches/api/0396-More-Sign-Block-API.patch new file mode 100644 index 000000000000..d01d6037166f --- /dev/null +++ b/patches/api/0396-More-Sign-Block-API.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 23 Jun 2023 12:16:35 -0700 +Subject: [PATCH] More Sign Block API + +Co-authored-by: SoSeDiK + +diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java +index be36f722c7e465fae09ae7c99d92bfa032b66cc3..859217e0109beb555e2357d806be96b53471955d 100644 +--- a/src/main/java/org/bukkit/block/Sign.java ++++ b/src/main/java/org/bukkit/block/Sign.java +@@ -182,9 +182,58 @@ public interface Sign extends TileState, Colorable { + /** + * Gets the player that is currently allowed to edit this sign.
      + * Edits from other players will be rejected if this value is not null. ++ *

      You should prefer {@link #getAllowedEditorUniqueId()} if you don't ++ * need the player instance as this method will fetch the player from UUID. + * + * @return the player allowed to edit this sign, or null + */ + @Nullable + public Player getAllowedEditor(); ++ // Paper start - More Sign Block API ++ /** ++ * Gets the allowed editor's UUID. ++ *
      Edits from other players will be rejected if this value is not null. ++ * ++ * @return the allowed editor's UUID, or null ++ */ ++ @Nullable java.util.UUID getAllowedEditorUniqueId(); ++ ++ /** ++ * Sets the allowed editor's UUID. ++ *

      Note: the server sets the UUID back to null if the player can't ++ * interact with the sign (is either offline or outside the allowed interaction range). ++ * ++ * @param uuid the allowed editor's UUID ++ */ ++ void setAllowedEditorUniqueId(@Nullable java.util.UUID uuid); ++ ++ /** ++ * Compute the side facing the specified entity. ++ * ++ * @param entity the entity ++ * @return the side it is facing ++ */ ++ default @NotNull Side getInteractableSideFor(org.bukkit.entity.@NotNull Entity entity) { ++ return this.getInteractableSideFor(entity.getLocation()); ++ } ++ ++ /** ++ * Compute the side facing the specific position. ++ * ++ * @param position the position ++ * @return the side the position is facing ++ */ ++ default @NotNull Side getInteractableSideFor(io.papermc.paper.math.@NotNull Position position) { ++ return this.getInteractableSideFor(position.x(), position.z()); ++ } ++ ++ /** ++ * Compute the side facing the specific x and z coordinates. ++ * ++ * @param x the x coord ++ * @param z the z coord ++ * @return the side the coordinates are facing ++ */ ++ @NotNull Side getInteractableSideFor(double x, double z); ++ // Paper end - More Sign Block API + } diff --git a/patches/api/0397-Fix-BanList-API.patch b/patches/api/0397-Fix-BanList-API.patch new file mode 100644 index 000000000000..c09a61d37417 --- /dev/null +++ b/patches/api/0397-Fix-BanList-API.patch @@ -0,0 +1,162 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 4 Jul 2023 11:27:18 -0700 +Subject: [PATCH] Fix BanList API + + +diff --git a/src/main/java/org/bukkit/BanList.java b/src/main/java/org/bukkit/BanList.java +index 5829aca9e5aa700bd95f19db3ae032100f74d5a3..60aea29d51a8ad499401f94a7c326d9b415b6a3a 100644 +--- a/src/main/java/org/bukkit/BanList.java ++++ b/src/main/java/org/bukkit/BanList.java +@@ -48,7 +48,7 @@ public interface BanList { + */ + @Deprecated(since = "1.20.1") + @Nullable +- public BanEntry getBanEntry(@NotNull String target); ++ public > E getBanEntry(@NotNull String target); // Paper + + /** + * Gets a {@link BanEntry} by target. +@@ -77,7 +77,7 @@ public interface BanList { + */ + @Deprecated(since = "1.20.1") + @Nullable +- public BanEntry addBan(@NotNull String target, @Nullable String reason, @Nullable Date expires, @Nullable String source); ++ public > E addBan(@NotNull String target, @Nullable String reason, @Nullable Date expires, @Nullable String source); // Paper + + /** + * Adds a ban to this list. If a previous ban exists, this will +@@ -140,7 +140,7 @@ public interface BanList { + * @return an immutable set containing every entry tracked by this list + */ + @NotNull +- public Set> getEntries(); ++ public > Set getEntries(); // Paper + + /** + * Gets if a {@link BanEntry} exists for the target, indicating an active +diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java +index 9facde856fa9b1b8f2a6198a1b541b819ea12518..a8003b4796b3f80986043a9dbc2e6ad08a1bb4d7 100644 +--- a/src/main/java/org/bukkit/OfflinePlayer.java ++++ b/src/main/java/org/bukkit/OfflinePlayer.java +@@ -147,7 +147,7 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Date expires, @Nullable String source); ++ public > E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source); // Paper - fix ban list API + + /** + * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will +@@ -161,7 +161,7 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source); ++ public > E ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source); // Paper - fix ban list API + + /** + * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will +@@ -175,7 +175,7 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source); ++ public > E ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source); // Paper - fix ban list API + + /** + * Checks if this player is whitelisted or not +diff --git a/src/main/java/org/bukkit/ban/ProfileBanList.java b/src/main/java/org/bukkit/ban/ProfileBanList.java +index e805e629cede1c4c0674282c930cb67852718c3e..5248cf08ef83c7304dd76c42a2f646bb81e0efae 100644 +--- a/src/main/java/org/bukkit/ban/ProfileBanList.java ++++ b/src/main/java/org/bukkit/ban/ProfileBanList.java +@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable; + /** + * A {@link BanList} targeting player profile bans. + */ +-public interface ProfileBanList extends BanList { ++public interface ProfileBanList extends BanList { // Paper + + /** + * {@inheritDoc} +@@ -23,8 +23,48 @@ public interface ProfileBanList extends BanList { + * @return the entry for the newly created ban, or the entry for the + * (updated) previous ban + * @throws IllegalArgumentException if ProfilePlayer has an invalid UUID ++ * @deprecated use {@link #addBan(com.destroystokyo.paper.profile.PlayerProfile, String, Date, String)} + */ + @Nullable +- public BanEntry addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source); ++ // Paper start ++ @Deprecated ++ public > E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source); + ++ /** ++ * @throws IllegalArgumentException if ProfilePlayer has an invalid UUID ++ */ ++ @Nullable BanEntry addBan(com.destroystokyo.paper.profile.@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source); ++ ++ // the 5 methods below are added to maintain compat for the bukkit.PlayerProfile parameter type ++ /** ++ * @deprecated use {@link #getBanEntry(Object)} ++ */ ++ @Deprecated ++ @Nullable > E getBanEntry(@NotNull PlayerProfile target); ++ ++ /** ++ * @deprecated use {@link #isBanned(Object)} ++ */ ++ @Deprecated ++ boolean isBanned(@NotNull PlayerProfile target); ++ ++ /** ++ * @deprecated use {@link #pardon(Object)} ++ */ ++ @Deprecated ++ void pardon(@NotNull PlayerProfile target); ++ ++ /** ++ * @deprecated use {@link #addBan(Object, String, java.time.Instant, String)} ++ */ ++ @Deprecated ++ @Nullable > E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable java.time.Instant expires, @Nullable String source); ++ ++ /** ++ * @deprecated use {@link #addBan(Object, String, java.time.Duration, String)} ++ */ ++ @Deprecated ++ @Nullable > E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable java.time.Duration duration, @Nullable String source); ++ ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index c2d49ff3aee971598451734f95144ac5dbbf131a..ad8e53bc528f6a078c85962fb85956bd97d67703 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -359,7 +359,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer); ++ public > E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API + + /** + * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will +@@ -375,7 +375,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source, boolean kickPlayer); ++ public > E ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API + + /** + * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will +@@ -391,7 +391,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * (updated) previous ban + */ + @Nullable +- public BanEntry ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source, boolean kickPlayer); ++ public > E ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API + + /** + * Adds this user's current IP address to the {@link IpBanList}. If a previous ban exists, this will diff --git a/patches/api/0398-Add-whitelist-events.patch b/patches/api/0398-Add-whitelist-events.patch new file mode 100644 index 000000000000..3f768a812431 --- /dev/null +++ b/patches/api/0398-Add-whitelist-events.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SageSphinx63920 +Date: Sun, 14 May 2023 12:56:15 +0200 +Subject: [PATCH] Add whitelist events + + +diff --git a/src/main/java/io/papermc/paper/event/server/WhitelistStateUpdateEvent.java b/src/main/java/io/papermc/paper/event/server/WhitelistStateUpdateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ff8c2c74fc68b1dd564e07c938b28b5950871533 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/server/WhitelistStateUpdateEvent.java +@@ -0,0 +1,83 @@ ++package io.papermc.paper.event.server; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import org.bukkit.Bukkit; ++import org.bukkit.OfflinePlayer; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * This event gets called when the whitelist status of a player is changed ++ */ ++@NullMarked ++public class WhitelistStateUpdateEvent extends Event implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final PlayerProfile playerProfile; ++ private final WhitelistStatus status; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public WhitelistStateUpdateEvent(final PlayerProfile playerProfile, final WhitelistStatus status) { ++ this.playerProfile = playerProfile; ++ this.status = status; ++ } ++ ++ /** ++ * Gets the player whose whitelist status is being changed ++ * ++ * @return the player whose status is being changed ++ */ ++ public OfflinePlayer getPlayer() { ++ return Bukkit.getOfflinePlayer(this.playerProfile.getId()); ++ } ++ ++ /** ++ * Gets the player profile whose whitelist status is being changed ++ * ++ * @return the player profile whose status is being changed ++ */ ++ public PlayerProfile getPlayerProfile() { ++ return this.playerProfile; ++ } ++ ++ /** ++ * Gets the status change of the player profile ++ * ++ * @return the whitelist status ++ */ ++ public WhitelistStatus getStatus() { ++ return this.status; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ /** ++ * Enum for the whitelist status changes ++ */ ++ public enum WhitelistStatus { ++ ADDED, REMOVED ++ } ++} diff --git a/patches/api/0399-API-for-updating-recipes-on-clients.patch b/patches/api/0399-API-for-updating-recipes-on-clients.patch new file mode 100644 index 000000000000..68ba48ebf46d --- /dev/null +++ b/patches/api/0399-API-for-updating-recipes-on-clients.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 21 Aug 2021 17:25:54 -0700 +Subject: [PATCH] API for updating recipes on clients + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 5170f7ba71d8a09f2b4ae0d945c758fd4ae4130f..886c1aab96bd34739665c22793217f3f41ba92d0 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1004,6 +1004,26 @@ public final class Bukkit { + server.reloadData(); + } + ++ // Paper start - update reloadable data ++ /** ++ * Updates all advancement, tag, and recipe data for all connected clients. ++ * Useful for updating clients to new advancements/recipes/tags. ++ * @see #updateRecipes() ++ */ ++ public static void updateResources() { ++ server.updateResources(); ++ } ++ ++ /** ++ * Updates recipe data and the recipe book for all connected clients. Useful for ++ * updating clients to new recipes. ++ * @see #updateResources() ++ */ ++ public static void updateRecipes() { ++ server.updateRecipes(); ++ } ++ // Paper end - update reloadable data ++ + /** + * Returns the primary logger associated with this server instance. + * +@@ -1064,6 +1084,20 @@ public final class Bukkit { + return server.addRecipe(recipe); + } + ++ // Paper start - method to send recipes immediately ++ /** ++ * Adds a recipe to the crafting manager. ++ * ++ * @param recipe the recipe to add ++ * @param resendRecipes true to update the client with the full set of recipes ++ * @return true if the recipe was added, false if it wasn't for some reason ++ */ ++ @Contract("null, _ -> false") ++ public static boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes) { ++ return server.addRecipe(recipe, resendRecipes); ++ } ++ // Paper end - method to send recipes immediately ++ + /** + * Get a list of all recipes for a given item. The stack size is ignored + * in comparisons. If the durability is -1, it will match any data value. +@@ -1255,6 +1289,24 @@ public final class Bukkit { + return server.removeRecipe(key); + } + ++ // Paper start - method to resend recipes ++ /** ++ * Remove a recipe from the server. ++ *

      ++ * Note that removing a recipe may cause permanent loss of data ++ * associated with that recipe (eg whether it has been discovered by ++ * players). ++ * ++ * @param key NamespacedKey of recipe to remove. ++ * @param resendRecipes true to update all clients on the new recipe list. ++ * Will only update if a recipe was actually removed ++ * @return True if recipe was removed ++ */ ++ public static boolean removeRecipe(@NotNull NamespacedKey key, boolean resendRecipes) { ++ return server.removeRecipe(key, resendRecipes); ++ } ++ // Paper end - method to resend recipes ++ + /** + * Gets a list of command aliases defined in the server properties. + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index d05ea34d8f58b475628157a7bd2ba0143e9a6c36..897d659e45d1a32c1bdaf8e0941f00597261a0b9 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -853,6 +853,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + public void reloadData(); + ++ // Paper start - update reloadable data ++ /** ++ * Updates all advancement, tag, and recipe data to all connected clients. ++ * Useful for updating clients to new advancements/recipes/tags. ++ * @see #updateRecipes() ++ */ ++ void updateResources(); ++ ++ /** ++ * Updates recipe data and the recipe book to each player. Useful for ++ * updating clients to new recipes. ++ * @see #updateResources() ++ */ ++ void updateRecipes(); ++ // Paper end - update reloadable data ++ + /** + * Returns the primary logger associated with this server instance. + * +@@ -894,15 +910,34 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + public boolean dispatchCommand(@NotNull CommandSender sender, @NotNull String commandLine) throws CommandException; + + /** +- * Adds a recipe to the crafting manager. ++ * Adds a recipe to the crafting manager. Recipes added with ++ * this method won't be sent to the client automatically. Use ++ * {@link #updateRecipes()} or {@link #updateResources()} to ++ * update clients to new recipes added. ++ *

      ++ * Player's still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)} ++ * before seeing them in their recipe book. + * + * @param recipe the recipe to add + * @return true if the recipe was added, false if it wasn't for some + * reason ++ * @see #addRecipe(Recipe, boolean) + */ + @Contract("null -> false") + public boolean addRecipe(@Nullable Recipe recipe); + ++ // Paper start - method to send recipes immediately ++ /** ++ * Adds a recipe to the crafting manager. ++ * ++ * @param recipe the recipe to add ++ * @param resendRecipes true to update the client with the full set of recipes ++ * @return true if the recipe was added, false if it wasn't for some reason ++ */ ++ @Contract("null, _ -> false") ++ boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes); ++ // Paper end - method to send recipes immediately ++ + /** + * Get a list of all recipes for a given item. The stack size is ignored + * in comparisons. If the durability is -1, it will match any data value. +@@ -1071,6 +1106,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + public boolean removeRecipe(@NotNull NamespacedKey key); + ++ // Paper start - method to resend recipes ++ /** ++ * Remove a recipe from the server. ++ *

      ++ * Note that removing a recipe may cause permanent loss of data ++ * associated with that recipe (eg whether it has been discovered by ++ * players). ++ * ++ * @param key NamespacedKey of recipe to remove. ++ * @param resendRecipes true to update all clients on the new recipe list. ++ * Will only update if a recipe was actually removed ++ * @return True if recipe was removed ++ */ ++ boolean removeRecipe(@NotNull NamespacedKey key, boolean resendRecipes); ++ // Paper end - method to resend recipes ++ + /** + * Gets a list of command aliases defined in the server properties. + * diff --git a/patches/api/0400-Add-PlayerFailMoveEvent.patch b/patches/api/0400-Add-PlayerFailMoveEvent.patch new file mode 100644 index 000000000000..e6903a2b56b6 --- /dev/null +++ b/patches/api/0400-Add-PlayerFailMoveEvent.patch @@ -0,0 +1,125 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Moulberry +Date: Wed, 26 Jul 2023 20:57:11 +0800 +Subject: [PATCH] Add PlayerFailMoveEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c7380874f99cd2aa28a24bbb0dd3375e8842dd0d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java +@@ -0,0 +1,113 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Runs when a player attempts to move, but is prevented from doing so by the server ++ */ ++@NullMarked ++public class PlayerFailMoveEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final FailReason failReason; ++ private final Location from; ++ private final Location to; ++ private boolean allowed; ++ private boolean logWarning; ++ ++ @ApiStatus.Internal ++ public PlayerFailMoveEvent(final Player player, final FailReason failReason, final boolean allowed, final boolean logWarning, final Location from, final Location to) { ++ super(player); ++ this.failReason = failReason; ++ this.allowed = allowed; ++ this.logWarning = logWarning; ++ this.from = from; ++ this.to = to; ++ } ++ ++ /** ++ * Gets the reason this movement was prevented by the server ++ * ++ * @return The reason the movement was prevented ++ */ ++ public FailReason getFailReason() { ++ return this.failReason; ++ } ++ ++ /** ++ * Gets the location this player moved from ++ * ++ * @return Location the player moved from ++ */ ++ public Location getFrom() { ++ return this.from.clone(); ++ } ++ ++ /** ++ * Gets the location this player tried to move to ++ * ++ * @return Location the player tried to move to ++ */ ++ public Location getTo() { ++ return this.to.clone(); ++ } ++ ++ /** ++ * Gets if the check should be bypassed, allowing the movement ++ * ++ * @return whether to bypass the check ++ */ ++ public boolean isAllowed() { ++ return this.allowed; ++ } ++ ++ /** ++ * Set if the check should be bypassed and the movement should be allowed ++ * ++ * @param allowed whether to bypass the check ++ */ ++ public void setAllowed(final boolean allowed) { ++ this.allowed = allowed; ++ } ++ ++ /** ++ * Gets if warnings will be printed to console. e.g. "Player123 moved too quickly!" ++ * ++ * @return whether to log warnings ++ */ ++ public boolean getLogWarning() { ++ return this.logWarning; ++ } ++ ++ /** ++ * Set if a warning is printed to console. e.g. "Player123 moved too quickly!" ++ * ++ * @param logWarning whether to log warnings ++ */ ++ public void setLogWarning(final boolean logWarning) { ++ this.logWarning = logWarning; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public enum FailReason { ++ MOVED_INTO_UNLOADED_CHUNK, // Only fired if the world setting prevent-moving-into-unloaded-chunks is true ++ MOVED_TOO_QUICKLY, ++ MOVED_WRONGLY, ++ CLIPPED_INTO_BLOCK ++ } ++ ++} diff --git a/patches/api/0401-Fix-custom-statistic-criteria-creation.patch b/patches/api/0401-Fix-custom-statistic-criteria-creation.patch new file mode 100644 index 000000000000..06e1015bba8a --- /dev/null +++ b/patches/api/0401-Fix-custom-statistic-criteria-creation.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Noah van der Aa +Date: Sat, 12 Aug 2023 15:33:55 +0200 +Subject: [PATCH] Fix custom statistic criteria creation + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 3328ae3bab6b4929506a518d6426b81594b1b300..8e0877321edb26e1dbdb3570a62814d06c0616af 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -256,4 +256,6 @@ public interface UnsafeValues { + @Deprecated(since = "1.21.3", forRemoval = true) + void setBiomeKey(RegionAccessor accessor, int x, int y, int z, NamespacedKey biomeKey); + // Paper end - namespaced key biome methods ++ ++ String getStatisticCriteriaKey(@NotNull org.bukkit.Statistic statistic); // Paper - fix custom stats criteria creation + } +diff --git a/src/main/java/org/bukkit/scoreboard/Criteria.java b/src/main/java/org/bukkit/scoreboard/Criteria.java +index 7d79d7fadab19bfbefc4797d7e5bbd3e9d733b53..3bc3abaf093d13e22b6ac2ee59ab584c92b4666a 100644 +--- a/src/main/java/org/bukkit/scoreboard/Criteria.java ++++ b/src/main/java/org/bukkit/scoreboard/Criteria.java +@@ -335,7 +335,7 @@ public interface Criteria { + @NotNull + public static Criteria statistic(@NotNull Statistic statistic) { + Preconditions.checkArgument(statistic != null, "statistic must not be null"); +- return Bukkit.getScoreboardCriteria("minecraft.custom:minecraft." + statistic.getKey().getKey()); ++ return Bukkit.getScoreboardCriteria(org.bukkit.Bukkit.getUnsafe().getStatisticCriteriaKey(statistic)); // Paper + } + + /** diff --git a/patches/api/0402-SculkCatalyst-bloom-API.patch b/patches/api/0402-SculkCatalyst-bloom-API.patch new file mode 100644 index 000000000000..49d8c8c2bdb0 --- /dev/null +++ b/patches/api/0402-SculkCatalyst-bloom-API.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Oliwier Miodun +Date: Mon, 10 Jul 2023 17:59:42 +0200 +Subject: [PATCH] SculkCatalyst bloom API + + +diff --git a/src/main/java/org/bukkit/block/SculkCatalyst.java b/src/main/java/org/bukkit/block/SculkCatalyst.java +index 46260df8938bb616dd0e26829a123a24736b0a70..7d53b24003d49c5d7623598e92a6b0603c5d3069 100644 +--- a/src/main/java/org/bukkit/block/SculkCatalyst.java ++++ b/src/main/java/org/bukkit/block/SculkCatalyst.java +@@ -24,4 +24,14 @@ public interface SculkCatalyst extends TileState { + * @param charges how much charge to spawn. + */ + void bloom(@NotNull Block block, int charges); ++ ++ // Paper start - SculkCatalyst bloom API ++ /** ++ * Bloom at the specified location as if an entity that drops experience just died there. ++ * ++ * @param position position to bloom at ++ * @param charge charge to bloom with, normally the amount of experience dropped from the dead entity ++ */ ++ void bloom(@org.jetbrains.annotations.NotNull io.papermc.paper.math.Position position, int charge); ++ // Paper end - SculkCatalyst bloom API + } diff --git a/patches/api/0403-API-for-an-entity-s-scoreboard-name.patch b/patches/api/0403-API-for-an-entity-s-scoreboard-name.patch new file mode 100644 index 000000000000..c7f79f623584 --- /dev/null +++ b/patches/api/0403-API-for-an-entity-s-scoreboard-name.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 9 Jul 2023 11:54:54 -0700 +Subject: [PATCH] API for an entity's scoreboard name + +Was obtainable through different methods, but you had to use different +methods depending on the implementation of Entity you were working with. + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index e196b66c02b5ba9ca35df804182f9b7ab4f7b45c..ee5a27ba09ec4100dbedab4f190cf74549ce858e 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -1112,4 +1112,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + @NotNull io.papermc.paper.threadedregions.scheduler.EntityScheduler getScheduler(); + // Paper end - Folia schedulers ++ ++ // Paper start - entity scoreboard name ++ /** ++ * Gets the string name of the entity used to track it in {@link org.bukkit.scoreboard.Scoreboard Scoreboards}. ++ * ++ * @return the scoreboard entry name ++ * @see org.bukkit.scoreboard.Scoreboard#getScores(String) ++ * @see org.bukkit.scoreboard.Scoreboard#getEntries() ++ */ ++ @NotNull String getScoreboardEntryName(); ++ // Paper end - entity scoreboard name + } diff --git a/patches/api/0404-Deprecate-and-replace-methods-with-old-StructureType.patch b/patches/api/0404-Deprecate-and-replace-methods-with-old-StructureType.patch new file mode 100644 index 000000000000..5edb856e1995 --- /dev/null +++ b/patches/api/0404-Deprecate-and-replace-methods-with-old-StructureType.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 10 Dec 2022 17:52:45 -0800 +Subject: [PATCH] Deprecate and replace methods with old StructureType + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 886c1aab96bd34739665c22793217f3f41ba92d0..c3c76dd82b209f6720afc51622aeb3fd92f1c0c2 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -949,9 +949,6 @@ public final class Bukkit { + /** + * Create a new explorer map targeting the closest nearby structure of a + * given {@link StructureType}. +- *
      +- * This method uses implementation default values for radius and +- * findUnexplored (usually 100, true). + * + * @param world the world the map will belong to + * @param location the origin location to find the nearest structure +@@ -960,7 +957,9 @@ public final class Bukkit { + * + * @see World#locateNearestStructure(org.bukkit.Location, + * org.bukkit.StructureType, int, boolean) ++ * @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type)} + */ ++ @Deprecated // Paper + @NotNull + public static ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType) { + return server.createExplorerMap(world, location, structureType); +@@ -983,11 +982,54 @@ public final class Bukkit { + * + * @see World#locateNearestStructure(org.bukkit.Location, + * org.bukkit.StructureType, int, boolean) ++ * @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type, int, boolean)} + */ ++ @Deprecated // Paper + @NotNull + public static ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType, int radius, boolean findUnexplored) { + return server.createExplorerMap(world, location, structureType, radius, findUnexplored); + } ++ // Paper start ++ /** ++ * Create a new explorer map targeting the closest nearby structure of a ++ * given {@link org.bukkit.generator.structure.StructureType}. ++ *
      ++ * This method uses implementation default values for radius and ++ * findUnexplored (usually 100, true). ++ * ++ * @param world the world the map will belong to ++ * @param location the origin location to find the nearest structure ++ * @param structureType the type of structure to find ++ * @param mapIcon the map icon to use on the map ++ * @return a newly created item stack or null if it can't find a location ++ * ++ * @see World#locateNearestStructure(org.bukkit.Location, ++ * org.bukkit.generator.structure.StructureType, int, boolean) ++ */ ++ public static @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon) { ++ return server.createExplorerMap(world, location, structureType, mapIcon); ++ } ++ ++ /** ++ * Create a new explorer map targeting the closest nearby structure of a ++ * given {@link org.bukkit.generator.structure.StructureType}. ++ * ++ * @param world the world the map will belong to ++ * @param location the origin location to find the nearest structure ++ * @param structureType the type of structure to find ++ * @param mapIcon the map icon to use on the map ++ * @param radius radius to search, see World#locateNearestStructure for more ++ * information ++ * @param findUnexplored whether to find unexplored structures ++ * @return the newly created item stack or null if it can't find a location ++ * ++ * @see World#locateNearestStructure(org.bukkit.Location, ++ * org.bukkit.generator.structure.StructureType, int, boolean) ++ */ ++ public static @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored) { ++ return server.createExplorerMap(world, location, structureType, mapIcon, radius, findUnexplored); ++ } ++ // Paper end + + /** + * Reloads the server, refreshing settings and plugin information. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 897d659e45d1a32c1bdaf8e0941f00597261a0b9..1b968953fdf470bff32122bd06c4f83f27b97383 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -817,16 +817,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * + * @see World#locateNearestStructure(org.bukkit.Location, + * org.bukkit.StructureType, int, boolean) ++ * @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type)} + */ ++ @Deprecated // Paper + @NotNull + public ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType); + + /** + * Create a new explorer map targeting the closest nearby structure of a + * given {@link StructureType}. +- *
      +- * This method uses implementation default values for radius and +- * findUnexplored (usually 100, true). + * + * @param world the world the map will belong to + * @param location the origin location to find the nearest structure +@@ -838,9 +837,50 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * + * @see World#locateNearestStructure(org.bukkit.Location, + * org.bukkit.StructureType, int, boolean) ++ * @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type, int, boolean)} + */ ++ @Deprecated // Paper + @NotNull + public ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType, int radius, boolean findUnexplored); ++ // Paper start ++ /** ++ * Create a new explorer map targeting the closest nearby structure of a ++ * given {@link org.bukkit.generator.structure.StructureType}. ++ *
      ++ * This method uses implementation default values for radius and ++ * findUnexplored (usually 100, true). ++ * ++ * @param world the world the map will belong to ++ * @param location the origin location to find the nearest structure ++ * @param structureType the type of structure to find ++ * @param mapIcon the map icon to use on the map ++ * @return a newly created item stack or null if it can't find a location ++ * ++ * @see World#locateNearestStructure(org.bukkit.Location, ++ * org.bukkit.generator.structure.StructureType, int, boolean) ++ */ ++ default @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon) { ++ return this.createExplorerMap(world, location, structureType, mapIcon, 100, true); ++ } ++ ++ /** ++ * Create a new explorer map targeting the closest nearby structure of a ++ * given {@link org.bukkit.generator.structure.StructureType}. ++ * ++ * @param world the world the map will belong to ++ * @param location the origin location to find the nearest structure ++ * @param structureType the type of structure to find ++ * @param mapIcon the map icon to use on the map ++ * @param radius radius to search, see World#locateNearestStructure for more ++ * information ++ * @param findUnexplored whether to find unexplored structures ++ * @return the newly created item stack or null if it can't find a location ++ * ++ * @see World#locateNearestStructure(org.bukkit.Location, ++ * org.bukkit.generator.structure.StructureType, int, boolean) ++ */ ++ @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored); ++ // Paper end + + /** + * Reloads the server, refreshing settings and plugin information. diff --git a/patches/api/0405-Add-Listing-API-for-Player.patch b/patches/api/0405-Add-Listing-API-for-Player.patch new file mode 100644 index 000000000000..bd09b03dc0c4 --- /dev/null +++ b/patches/api/0405-Add-Listing-API-for-Player.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corey Shupe +Date: Wed, 11 Jan 2023 16:40:31 -0500 +Subject: [PATCH] Add Listing API for Player + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index ad8e53bc528f6a078c85962fb85956bd97d67703..094c2056f4124dbb1caa0a5e962933b653d950a9 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2078,6 +2078,32 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + public boolean canSee(@NotNull Entity entity); + ++ // Paper start ++ /** ++ * Returns whether the {@code other} player is listed for {@code this}. ++ * ++ * @param other The other {@link Player} to check for listing. ++ * @return True if the {@code other} player is listed for {@code this}. ++ */ ++ boolean isListed(@NotNull Player other); ++ ++ /** ++ * Unlists the {@code other} player from the tablist. ++ * ++ * @param other The other {@link Player} to de-list. ++ * @return True if the {@code other} player was listed. ++ */ ++ boolean unlistPlayer(@NotNull Player other); ++ ++ /** ++ * Lists the {@code other} player. ++ * ++ * @param other The other {@link Player} to list. ++ * @return True if the {@code other} player was not listed. ++ */ ++ boolean listPlayer(@NotNull Player other); ++ // Paper end ++ + /** + * Checks to see if this player is currently flying or not. + * diff --git a/patches/api/0406-Expose-clicked-BlockFace-during-BlockDamageEvent.patch b/patches/api/0406-Expose-clicked-BlockFace-during-BlockDamageEvent.patch new file mode 100644 index 000000000000..34d194086683 --- /dev/null +++ b/patches/api/0406-Expose-clicked-BlockFace-during-BlockDamageEvent.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: aerulion +Date: Mon, 21 Aug 2023 04:36:07 +0200 +Subject: [PATCH] Expose clicked BlockFace during BlockDamageEvent + + +diff --git a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java +index cd04a0bd9d232857408b38605787016a217cb8d2..392cde07d578d684423e1bf369af28696eb7e484 100644 +--- a/src/main/java/org/bukkit/event/block/BlockDamageEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockDamageEvent.java +@@ -19,9 +19,20 @@ public class BlockDamageEvent extends BlockEvent implements Cancellable { + private boolean instaBreak; + private boolean cancel; + private final ItemStack itemstack; ++ private final org.bukkit.block.BlockFace blockFace; // Paper - Expose BlockFace + ++ // Paper start - expose blockface ++ @Deprecated(forRemoval = true) ++ @io.papermc.paper.annotation.DoNotUse + public BlockDamageEvent(@NotNull final Player player, @NotNull final Block block, @NotNull final ItemStack itemInHand, final boolean instaBreak) { ++ this(player, block, null, itemInHand, instaBreak); // Some plugin do bad things... ++ } ++ ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public BlockDamageEvent(@NotNull final Player player, @NotNull final Block block, @NotNull final org.bukkit.block.BlockFace blockFace, @NotNull final ItemStack itemInHand, final boolean instaBreak) { // Paper - Expose BlockFace + super(block); ++ this.blockFace = blockFace; ++ // Paper end - expose blockface + this.instaBreak = instaBreak; + this.player = player; + this.itemstack = itemInHand; +@@ -67,6 +78,20 @@ public class BlockDamageEvent extends BlockEvent implements Cancellable { + public ItemStack getItemInHand() { + return itemstack; + } ++ // Paper start - Expose BlockFace ++ /** ++ * Gets the BlockFace the player is interacting with. ++ * ++ * @return The BlockFace clicked to damage the block ++ */ ++ @NotNull ++ public org.bukkit.block.BlockFace getBlockFace() { ++ if (this.blockFace == null) { ++ throw new IllegalStateException("BlockFace is not available for this event, most likely due to a bad constructor call by a plugin"); ++ } ++ return this.blockFace; ++ } ++ //Paper end + + @Override + public boolean isCancelled() { diff --git a/patches/api/0407-Fix-NPE-on-Boat-getStatus.patch b/patches/api/0407-Fix-NPE-on-Boat-getStatus.patch new file mode 100644 index 000000000000..03398ef0e74d --- /dev/null +++ b/patches/api/0407-Fix-NPE-on-Boat-getStatus.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: LemonCaramel +Date: Tue, 11 Apr 2023 04:04:41 +0900 +Subject: [PATCH] Fix NPE on Boat getStatus + + +diff --git a/src/main/java/org/bukkit/entity/Boat.java b/src/main/java/org/bukkit/entity/Boat.java +index 9e8224d7e0a83a6252a32d352b9db55a9079325e..219a2f06c57c8a64052c372a62892389a98f9ae1 100644 +--- a/src/main/java/org/bukkit/entity/Boat.java ++++ b/src/main/java/org/bukkit/entity/Boat.java +@@ -175,6 +175,7 @@ public interface Boat extends Vehicle { + */ + public enum Status { + ++ NOT_IN_WORLD, // Paper + IN_WATER, + UNDER_WATER, + UNDER_FLOWING_WATER, diff --git a/patches/api/0408-Expand-Pose-API.patch b/patches/api/0408-Expand-Pose-API.patch new file mode 100644 index 000000000000..cdc5e59a2aab --- /dev/null +++ b/patches/api/0408-Expand-Pose-API.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Wed, 11 Jan 2023 20:59:02 +0200 +Subject: [PATCH] Expand Pose API + + +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index ee5a27ba09ec4100dbedab4f190cf74549ce858e..e56808a884a4fda9a891468a787b3dff9303debc 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -840,6 +840,42 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + * @param sneak true if the entity should be sneaking + */ + void setSneaking(boolean sneak); ++ ++ /** ++ * Sets the entity's current {@link Pose}. ++ * ++ *

      Note: While poses affect some things like hitboxes, they do not change the entity's state ++ * (e.g. having {@link Pose#SNEAKING} does not guarantee {@link #isSneaking()} being {@code true}). ++ * ++ *

      If applied to the {@link Player}, they might see a different pose client-side. ++ * ++ * @param pose a new {@link Pose} ++ * @see #setPose(Pose, boolean) ++ */ ++ default void setPose(@NotNull Pose pose) { ++ setPose(pose, false); ++ } ++ ++ /** ++ * Sets the entity's current {@link Pose}. ++ * ++ *

      Note: While poses affect some things like hitboxes, they do not change the entity's state ++ * (e.g. having {@link Pose#SNEAKING} does not guarantee {@link #isSneaking()} being {@code true}). ++ * ++ *

      If applied to the {@link Player}, they might see a different pose client-side. ++ * ++ * @param pose a new {@link Pose} ++ * @param fixed whether the new {@link Pose} should stay until manually changed ++ */ ++ void setPose(@NotNull Pose pose, boolean fixed); ++ ++ /** ++ * Checks whether the entity has a fixed {@link Pose} ++ * ++ * @see #setPose(Pose, boolean) ++ * @return whether the entity has a fixed {@link Pose} ++ */ ++ boolean hasFixedPose(); + // Paper end + + /** diff --git a/patches/api/0409-MerchantRecipe-add-copy-constructor.patch b/patches/api/0409-MerchantRecipe-add-copy-constructor.patch new file mode 100644 index 000000000000..1c5ba2803c26 --- /dev/null +++ b/patches/api/0409-MerchantRecipe-add-copy-constructor.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Joo200 +Date: Tue, 20 Dec 2022 15:26:36 +0100 +Subject: [PATCH] MerchantRecipe: add copy constructor + + +diff --git a/src/main/java/org/bukkit/inventory/MerchantRecipe.java b/src/main/java/org/bukkit/inventory/MerchantRecipe.java +index afaa21b9347683fa373a938d9b1aa01c2058192a..39f9766a03d420340d79841197f75c8b1dd49f4a 100644 +--- a/src/main/java/org/bukkit/inventory/MerchantRecipe.java ++++ b/src/main/java/org/bukkit/inventory/MerchantRecipe.java +@@ -91,6 +91,13 @@ public class MerchantRecipe implements Recipe { + this.specialPrice = specialPrice; + } + ++ // Paper start - add copy ctor ++ public MerchantRecipe(@NotNull MerchantRecipe recipe) { ++ this(recipe.result.clone(), recipe.uses, recipe.maxUses, recipe.experienceReward, recipe.villagerExperience, recipe.priceMultiplier, recipe.demand, recipe.specialPrice, recipe.ignoreDiscounts); ++ this.setIngredients(recipe.ingredients); ++ } ++ // Paper end ++ + @NotNull + @Override + public ItemStack getResult() { diff --git a/patches/api/0410-More-DragonBattle-API.patch b/patches/api/0410-More-DragonBattle-API.patch new file mode 100644 index 000000000000..e25208ec1931 --- /dev/null +++ b/patches/api/0410-More-DragonBattle-API.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 18 Dec 2022 13:40:17 -0800 +Subject: [PATCH] More DragonBattle API + + +diff --git a/src/main/java/org/bukkit/boss/DragonBattle.java b/src/main/java/org/bukkit/boss/DragonBattle.java +index 6e5fc92243ee63c2a965f8a4905e29a7993588fd..5dbd12a786a66640ce80acafe2a42e35adef41eb 100644 +--- a/src/main/java/org/bukkit/boss/DragonBattle.java ++++ b/src/main/java/org/bukkit/boss/DragonBattle.java +@@ -145,4 +145,44 @@ public interface DragonBattle { + */ + NONE; + } ++ // Paper start ++ /** ++ * Gets the number of gateways tracked by this DragonBattle. ++ * This starts out at 0 and will increase to 20, once for each ++ * kill of the {@link EnderDragon}. ++ * ++ * @return the number of gateways around the end island tracked by this ++ */ ++ int getGatewayCount(); ++ ++ /** ++ * Tries to spawn a new end gateway using default game mechanics. ++ * ++ * @return true if successful, false if there is already the maximum. ++ */ ++ boolean spawnNewGateway(); ++ ++ /** ++ * Spawns a new end gateway at the specified position. This will ++ * spawn regardless of the number of gateways already present. ++ * ++ * @param position position for the new gateway ++ */ ++ void spawnNewGateway(@NotNull io.papermc.paper.math.Position position); ++ ++ /** ++ * Gets the {@link org.bukkit.entity.EnderCrystal}s being used to respawn the dragon. If no respawn ++ * is ongoing, the list will be empty. ++ * ++ * @return the respawn crystals ++ */ ++ java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List getRespawnCrystals(); ++ ++ /** ++ * Gets the {@link org.bukkit.entity.EnderCrystal}s on top of the pillars that heal the dragon. ++ * ++ * @return the healing crystals ++ */ ++ java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List getHealingCrystals(); ++ // Paper end + } diff --git a/patches/api/0411-Add-PlayerPickItemEvent.patch b/patches/api/0411-Add-PlayerPickItemEvent.patch new file mode 100644 index 000000000000..f1ceb87ff2d8 --- /dev/null +++ b/patches/api/0411-Add-PlayerPickItemEvent.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: RodneyMKay <36546810+RodneyMKay@users.noreply.github.com> +Date: Wed, 8 Sep 2021 22:15:43 +0200 +Subject: [PATCH] Add PlayerPickItemEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7de240399f3ae069c496add9f0d437a41ed8f58d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java +@@ -0,0 +1,95 @@ ++package io.papermc.paper.event.player; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Range; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Event that is fired when a player uses the pick item functionality (middle-clicking a block or entity to get the ++ * appropriate item). After the handling of this event, the contents of the source and the target slot will be swapped ++ * and the currently selected hotbar slot of the player will be set to the target slot. ++ */ ++@NullMarked ++public class PlayerPickItemEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private int targetSlot; ++ private int sourceSlot; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PlayerPickItemEvent(final Player player, final int targetSlot, final int sourceSlot) { ++ super(player); ++ this.targetSlot = targetSlot; ++ this.sourceSlot = sourceSlot; ++ } ++ ++ /** ++ * Returns the slot the item that is being picked goes into. ++ * ++ * @return hotbar slot (0-8 inclusive) ++ */ ++ public @Range(from = 0, to = 8) int getTargetSlot() { ++ return this.targetSlot; ++ } ++ ++ /** ++ * Changes the slot the item that is being picked goes into. ++ * ++ * @param targetSlot hotbar slot (0-8 inclusive) ++ */ ++ public void setTargetSlot(final @Range(from = 0, to = 8) int targetSlot) { ++ Preconditions.checkArgument(targetSlot >= 0 && targetSlot <= 8, "Target slot must be in range 0 - 8 (inclusive)"); ++ this.targetSlot = targetSlot; ++ } ++ ++ /** ++ * Returns the slot in which the item that will be put into the players hotbar is located. ++ *

      ++ * Returns {@code -1} if the item is not in the player's inventory. ++ * If this is the case and the player is in creative mode, the item will be spawned in. ++ * ++ * @return player inventory slot (0-35 inclusive, or {@code -1} if not in the player inventory) ++ */ ++ public @Range(from = -1, to = 35) int getSourceSlot() { ++ return this.sourceSlot; ++ } ++ ++ /** ++ * Change the source slot from which the item that will be put in the players hotbar will be taken. ++ *

      ++ * If set to {@code -1} and the player is in creative mode, the item will be spawned in. ++ * ++ * @param sourceSlot player inventory slot (0-35 inclusive, or {@code -1} if not in the player inventory) ++ */ ++ public void setSourceSlot(final @Range(from = -1, to = 35) int sourceSlot) { ++ Preconditions.checkArgument(sourceSlot >= -1 && sourceSlot <= 35, "Source slot must be in range of the player's inventory slot, or -1"); ++ this.sourceSlot = sourceSlot; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0412-Allow-trident-custom-damage.patch b/patches/api/0412-Allow-trident-custom-damage.patch new file mode 100644 index 000000000000..870b7355485c --- /dev/null +++ b/patches/api/0412-Allow-trident-custom-damage.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> +Date: Wed, 13 Jul 2022 15:29:53 +0200 +Subject: [PATCH] Allow trident custom damage + + +diff --git a/src/main/java/org/bukkit/entity/Trident.java b/src/main/java/org/bukkit/entity/Trident.java +index 02584eced96944a551140f8150c65a7c0f4bb55e..d21df39ceef657575f3c2e9070bf6d2671978c7a 100644 +--- a/src/main/java/org/bukkit/entity/Trident.java ++++ b/src/main/java/org/bukkit/entity/Trident.java +@@ -57,5 +57,23 @@ public interface Trident extends AbstractArrow, ThrowableProjectile { + * @param hasDealtDamage has dealt damage or hit the floor + */ + void setHasDealtDamage(boolean hasDealtDamage); ++ ++ /** ++ * Sets the base amount of damage this trident will do. ++ * ++ * @param damage new damage amount ++ */ ++ void setDamage(double damage); ++ ++ /** ++ * Gets the base amount of damage this trident will do. ++ * ++ * Defaults to 8.0 for a normal trident with ++ * 0.5 * (1 + power level) added for trident fired from ++ * damage enchanted bows. ++ * ++ * @return base damage amount ++ */ ++ double getDamage(); + } + // Paper end diff --git a/patches/api/0413-Expose-hand-during-BlockCanBuildEvent.patch b/patches/api/0413-Expose-hand-during-BlockCanBuildEvent.patch new file mode 100644 index 000000000000..0d0054f292f8 --- /dev/null +++ b/patches/api/0413-Expose-hand-during-BlockCanBuildEvent.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: The456gamer +Date: Mon, 21 Aug 2023 14:13:43 +0100 +Subject: [PATCH] Expose hand during BlockCanBuildEvent + + +diff --git a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +index 7d2501278812c7f06d1416fa73389e84c258d71c..31fd64187fc5bd50a5ba36b3b68001ce6ff2211c 100644 +--- a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +@@ -25,10 +25,11 @@ public class BlockCanBuildEvent extends BlockEvent { + + protected BlockData blockData; + private final Player player; ++ private final org.bukkit.inventory.EquipmentSlot hand; // Paper - expose hand + + @Deprecated(since = "1.13.2") + public BlockCanBuildEvent(@NotNull final Block block, @NotNull final BlockData type, final boolean canBuild) { +- this(block, null, type, canBuild); ++ this(block, null, type, canBuild, org.bukkit.inventory.EquipmentSlot.HAND); // Paper - expose hand + } + + /** +@@ -37,12 +38,30 @@ public class BlockCanBuildEvent extends BlockEvent { + * @param type the id of the block to place + * @param canBuild whether we can build + */ ++ @java.lang.Deprecated // Paper ++ @io.papermc.paper.annotation.DoNotUse // Paper + public BlockCanBuildEvent(@NotNull final Block block, @Nullable final Player player, @NotNull final BlockData type, final boolean canBuild) { ++ this(block, player, type, canBuild, org.bukkit.inventory.EquipmentSlot.HAND); // Paper start - expose hand ++ } ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public BlockCanBuildEvent(@NotNull final Block block, @Nullable final Player player, @NotNull final BlockData type, final boolean canBuild, @NotNull final org.bukkit.inventory.EquipmentSlot hand) { // Paper end - expose hand + super(block); + this.player = player; + this.buildable = canBuild; + this.blockData = type; ++ this.hand = hand; // Paper ++ } ++ // Paper start ++ /** ++ * Gets the hand the player will use to place the block ++ * ++ * @return the EquipmentSlot representing the players hand. ++ */ ++ @NotNull ++ public org.bukkit.inventory.EquipmentSlot getHand() { ++ return hand; + } ++ // Paper end + + /** + * Gets whether or not the block can be built here. diff --git a/patches/api/0414-Limit-setBurnTime-to-valid-short-values.patch b/patches/api/0414-Limit-setBurnTime-to-valid-short-values.patch new file mode 100644 index 000000000000..2faac56fd883 --- /dev/null +++ b/patches/api/0414-Limit-setBurnTime-to-valid-short-values.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Warrior <50800980+Warriorrrr@users.noreply.github.com> +Date: Fri, 18 Aug 2023 08:07:38 +0200 +Subject: [PATCH] Limit setBurnTime to valid short values + + +diff --git a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +index ba4dc8aed85169e55cac276bdd51116919305019..2f80910dd23dacb30c41189a07a4e54117110bb8 100644 +--- a/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/FurnaceBurnEvent.java +@@ -52,8 +52,8 @@ public class FurnaceBurnEvent extends BlockEvent implements Cancellable { + * + * @param burnTime the burn time for this fuel + */ +- public void setBurnTime(int burnTime) { +- this.burnTime = burnTime; ++ public void setBurnTime(@org.jetbrains.annotations.Range(from = Short.MIN_VALUE, to = Short.MAX_VALUE) int burnTime) { // Paper ++ this.burnTime = Math.max(Short.MIN_VALUE, Math.min(Short.MAX_VALUE, burnTime)); // Paper + } + + /** diff --git a/patches/api/0415-Add-OfflinePlayer-isConnected.patch b/patches/api/0415-Add-OfflinePlayer-isConnected.patch new file mode 100644 index 000000000000..126881d0fd3c --- /dev/null +++ b/patches/api/0415-Add-OfflinePlayer-isConnected.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aeltumn +Date: Thu, 24 Aug 2023 13:05:07 +0200 +Subject: [PATCH] Add OfflinePlayer#isConnected + +This adds an alternative to OfflinePlayer#isOnline that returns true only if the same instance of the player is still online. This is generally more useful than isOnline as it allows you to determine if you have an instance of a Player that still exists. If a player relogs an old Player instance becomes unlinked leading to e.g. messages sent to the old player no longer arriving despite isOnline returning true. Checking against isConnected is more useful there to discard invalid instances. + +diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java +index a8003b4796b3f80986043a9dbc2e6ad08a1bb4d7..18720a965b814d02e783d5039da90af0e966025d 100644 +--- a/src/main/java/org/bukkit/OfflinePlayer.java ++++ b/src/main/java/org/bukkit/OfflinePlayer.java +@@ -24,10 +24,26 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio + /** + * Checks if this player is currently online + * ++ * It should be noted that this will return true if any instance of this player is ++ * online! This instance may have disconnected. If you wish to check if this specific ++ * instance of the player is still online, see {@link OfflinePlayer#isConnected()}. ++ * + * @return true if they are online + */ + public boolean isOnline(); + ++ // Paper start ++ /** ++ * Checks whether the connection to this player is still valid. This will return ++ * true as long as this specific instance of the player is still connected. This ++ * will return false after this instance has disconnected, even if the same player ++ * has reconnected since. ++ * ++ * @return true if this player instance is connected ++ */ ++ public boolean isConnected(); ++ // Paper end ++ + /** + * Returns the name of this player + *

      diff --git a/patches/api/0416-Add-titleOverride-to-InventoryOpenEvent.patch b/patches/api/0416-Add-titleOverride-to-InventoryOpenEvent.patch new file mode 100644 index 000000000000..68e755f0102b --- /dev/null +++ b/patches/api/0416-Add-titleOverride-to-InventoryOpenEvent.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 4 Mar 2022 12:45:21 -0800 +Subject: [PATCH] Add titleOverride to InventoryOpenEvent + + +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java +index ceae092eb782698803c6c3df41267dde20ba62b2..8e2afeab4c62724148e8bb0c83fb7eec569c7a0c 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryOpenEvent.java +@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; + public class InventoryOpenEvent extends InventoryEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; ++ private net.kyori.adventure.text.Component titleOverride; // Paper + + public InventoryOpenEvent(@NotNull InventoryView transaction) { + super(transaction); +@@ -56,6 +57,33 @@ public class InventoryOpenEvent extends InventoryEvent implements Cancellable { + cancelled = cancel; + } + ++ // Paper start ++ /** ++ * Gets the title override set by another event or null ++ * if not set. ++ * ++ * @return the title override or null ++ */ ++ public net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component titleOverride() { ++ return this.titleOverride; ++ } ++ ++ /** ++ * Sets the title override or clears the override. ++ *

      ++ * This is only the title sent to the client in the open packet, this doesn't change ++ * the title returned by {@link InventoryView#title()}, hence "override". ++ *

      ++ * NOTE: Horse inventories are a special case where setting this will ++ * have no effect. Horse inventory titles are set by the horse display name. ++ * ++ * @param titleOverride the title override or null ++ */ ++ public void titleOverride(net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component titleOverride) { ++ this.titleOverride = titleOverride; ++ } ++ // Paper end ++ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/patches/api/0417-Allow-proper-checking-of-empty-item-stacks.patch b/patches/api/0417-Allow-proper-checking-of-empty-item-stacks.patch new file mode 100644 index 000000000000..b413b7e7e7e3 --- /dev/null +++ b/patches/api/0417-Allow-proper-checking-of-empty-item-stacks.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aeltumn +Date: Mon, 28 Aug 2023 13:41:09 +0200 +Subject: [PATCH] Allow proper checking of empty item stacks + +This adds a method to check if an item stack is empty or not. This mirrors vanilla's implementation of the same method. + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 6393e5249b4469b1c8ebfb05a0f09572d116c40f..bcead776776665fc7558ee11f928d842bd2e3da5 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -1104,5 +1104,24 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + public @NotNull ItemStack damage(int amount, @NotNull org.bukkit.entity.LivingEntity livingEntity) { + return livingEntity.damageItemStack(this, amount); + } ++ ++ /** ++ * Returns an empty item stack, consists of an air material and a stack size of 0. ++ * ++ * Any item stack with a material of air or a stack size of 0 is seen ++ * as being empty by {@link ItemStack#isEmpty}. ++ */ ++ @NotNull ++ public static ItemStack empty() { ++ return new ItemStack(); ++ } ++ ++ /** ++ * Returns whether this item stack is empty and contains no item. This means ++ * it is either air or the stack has a size of 0. ++ */ ++ public boolean isEmpty() { ++ return type.isAir() || amount <= 0; ++ } + // Paper end + } diff --git a/patches/api/0418-Fix-PlayerSwapHandItemsEvent-throwing-exception-when.patch b/patches/api/0418-Fix-PlayerSwapHandItemsEvent-throwing-exception-when.patch new file mode 100644 index 000000000000..e72f86be5d20 --- /dev/null +++ b/patches/api/0418-Fix-PlayerSwapHandItemsEvent-throwing-exception-when.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tamion <70228790+notTamion@users.noreply.github.com> +Date: Mon, 25 Sep 2023 19:55:51 +0200 +Subject: [PATCH] Fix PlayerSwapHandItemsEvent throwing exception when mainhand + or offhand set to null + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerSwapHandItemsEvent.java b/src/main/java/org/bukkit/event/player/PlayerSwapHandItemsEvent.java +index 9f592317c920589c22a5fb8e916c6ca58ebe5c59..39dd08de71b8b52fe3462c105ecdbfc1cd2cd9a3 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerSwapHandItemsEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerSwapHandItemsEvent.java +@@ -31,7 +31,7 @@ public class PlayerSwapHandItemsEvent extends PlayerEvent implements Cancellable + * + * @return item in the main hand + */ +- @Nullable ++ @NotNull // Paper + public ItemStack getMainHandItem() { + return mainHandItem; + } +@@ -42,7 +42,7 @@ public class PlayerSwapHandItemsEvent extends PlayerEvent implements Cancellable + * @param mainHandItem new item in the main hand + */ + public void setMainHandItem(@Nullable ItemStack mainHandItem) { +- this.mainHandItem = mainHandItem; ++ this.mainHandItem = mainHandItem == null ? ItemStack.empty() : mainHandItem; // Paper + } + + /** +@@ -50,7 +50,7 @@ public class PlayerSwapHandItemsEvent extends PlayerEvent implements Cancellable + * + * @return item in the off hand + */ +- @Nullable ++ @NotNull // Paper + public ItemStack getOffHandItem() { + return offHandItem; + } +@@ -61,7 +61,7 @@ public class PlayerSwapHandItemsEvent extends PlayerEvent implements Cancellable + * @param offHandItem new item in the off hand + */ + public void setOffHandItem(@Nullable ItemStack offHandItem) { +- this.offHandItem = offHandItem; ++ this.offHandItem = offHandItem == null ? ItemStack.empty() : offHandItem; // Paper + } + + @Override diff --git a/patches/api/0419-Add-player-idle-duration-API.patch b/patches/api/0419-Add-player-idle-duration-API.patch new file mode 100644 index 000000000000..b64d0bcece99 --- /dev/null +++ b/patches/api/0419-Add-player-idle-duration-API.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: booky10 +Date: Sat, 14 Oct 2023 03:11:11 +0200 +Subject: [PATCH] Add player idle duration API + +Implements API for getting and resetting a player's idle duration. + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 094c2056f4124dbb1caa0a5e962933b653d950a9..d84fe3e439f3b190b7bbec15f406cc3a393dccfc 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3782,6 +3782,29 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void increaseWardenWarningLevel(); + // Paper end + ++ // Paper start ++ /** ++ * The idle duration is reset when the player ++ * sends specific action packets. ++ *

      ++ * After the idle duration exceeds {@link org.bukkit.Bukkit#getIdleTimeout()}, the ++ * player will be kicked for {@link org.bukkit.event.player.PlayerKickEvent.Cause#IDLING}. ++ * ++ * @return the current idle duration of this player ++ */ ++ @NotNull Duration getIdleDuration(); ++ ++ /** ++ * Resets this player's idle duration. ++ *

      ++ * After the idle duration exceeds {@link org.bukkit.Bukkit#getIdleTimeout()}, the ++ * player will be kicked for {@link org.bukkit.event.player.PlayerKickEvent.Cause#IDLING}. ++ * ++ * @see #getIdleDuration() ++ */ ++ void resetIdleDuration(); ++ // Paper end ++ + @NotNull + @Override + Spigot spigot(); diff --git a/patches/api/0420-Add-API-to-get-the-collision-shape-of-a-block-before.patch b/patches/api/0420-Add-API-to-get-the-collision-shape-of-a-block-before.patch new file mode 100644 index 000000000000..3bb30787dc38 --- /dev/null +++ b/patches/api/0420-Add-API-to-get-the-collision-shape-of-a-block-before.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TrollyLoki +Date: Wed, 11 Oct 2023 00:45:54 -0400 +Subject: [PATCH] Add API to get the collision shape of a block before it's + placed + + +diff --git a/src/main/java/org/bukkit/block/data/BlockData.java b/src/main/java/org/bukkit/block/data/BlockData.java +index 54664651f34311e95f6c2dcfd93e58477beda8c2..0ecc54bd810a2805b7209d9433b76743500e45a8 100644 +--- a/src/main/java/org/bukkit/block/data/BlockData.java ++++ b/src/main/java/org/bukkit/block/data/BlockData.java +@@ -205,6 +205,19 @@ public interface BlockData extends Cloneable { + */ + boolean isFaceSturdy(@NotNull BlockFace face, @NotNull BlockSupport support); + ++ // Paper start ++ /** ++ * Calculates the collision shape this block data would have at a particular location. ++ *

      ++ * This does not take into account any block updates that may occur if the block was to be actually placed in the world. ++ * ++ * @param location the location to calculate the collision shape at ++ * ++ * @return a {@link org.bukkit.util.VoxelShape} representing the collision shape of this block data. ++ */ ++ @NotNull org.bukkit.util.VoxelShape getCollisionShape(@NotNull Location location); ++ // Paper end ++ + /** + * Gets the color this block should appear as when rendered on a map. + * diff --git a/patches/api/0421-Add-predicate-for-blocks-when-raytracing.patch b/patches/api/0421-Add-predicate-for-blocks-when-raytracing.patch new file mode 100644 index 000000000000..507244270d25 --- /dev/null +++ b/patches/api/0421-Add-predicate-for-blocks-when-raytracing.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TonytheMacaroni +Date: Wed, 6 Sep 2023 19:24:53 -0400 +Subject: [PATCH] Add predicate for blocks when raytracing + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 8bfa8db3d0fdbe0c26e3b327d134c6c0af6be206..3cb0aecf582b3d1c5195fca9160780ad5e98155a 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -1686,6 +1686,27 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @Nullable + public RayTraceResult rayTraceEntities(@NotNull Location start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); + ++ // Paper start ++ /** ++ * Performs a ray trace that checks for entity collisions. ++ *

      ++ * This may not consider entities in currently unloaded chunks. Some ++ * implementations may impose artificial restrictions on the maximum ++ * distance. ++ * ++ * @param start the start position ++ * @param direction the ray direction ++ * @param maxDistance the maximum distance ++ * @param raySize entity bounding boxes will be uniformly expanded (or ++ * shrinked) by this value before doing collision checks ++ * @param filter only entities that fulfill this predicate are considered, ++ * or null to consider all entities ++ * @return the closest ray trace hit result, or null if there ++ * is no hit ++ */ ++ @Nullable RayTraceResult rayTraceEntities(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate filter); ++ // Paper end ++ + /** + * Performs a ray trace that checks for block collisions using the blocks' + * precise collision shapes. +@@ -1749,6 +1770,34 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @Nullable + public RayTraceResult rayTraceBlocks(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks); + ++ // Paper start ++ /** ++ * Performs a ray trace that checks for block collisions using the blocks' ++ * precise collision shapes. ++ *

      ++ * If collisions with passable blocks are ignored, fluid collisions are ++ * ignored as well regardless of the fluid collision mode. ++ *

      ++ * Portal blocks are only considered passable if the ray starts within ++ * them. Apart from that collisions with portal blocks will be considered ++ * even if collisions with passable blocks are otherwise ignored. ++ *

      ++ * This may cause loading of chunks! Some implementations may impose ++ * artificial restrictions on the maximum distance. ++ * ++ * @param start the start position ++ * @param direction the ray direction ++ * @param maxDistance the maximum distance ++ * @param fluidCollisionMode the fluid collision mode ++ * @param ignorePassableBlocks whether to ignore passable but collidable ++ * blocks (ex. tall grass, signs, fluids, ..) ++ * @param canCollide predicate for blocks the ray can potentially collide ++ * with, or null to consider all blocks ++ * @return the ray trace hit result, or null if there is no hit ++ */ ++ @Nullable RayTraceResult rayTraceBlocks(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, @Nullable Predicate canCollide); ++ // Paper end ++ + /** + * Performs a ray trace that checks for both block and entity collisions. + *

      +@@ -1782,6 +1831,42 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @Nullable + public RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter); + ++ // Paper start ++ /** ++ * Performs a ray trace that checks for both block and entity collisions. ++ *

      ++ * Block collisions use the blocks' precise collision shapes. The ++ * raySize parameter is only taken into account for entity ++ * collision checks. ++ *

      ++ * If collisions with passable blocks are ignored, fluid collisions are ++ * ignored as well regardless of the fluid collision mode. ++ *

      ++ * Portal blocks are only considered passable if the ray starts within them. ++ * Apart from that collisions with portal blocks will be considered even if ++ * collisions with passable blocks are otherwise ignored. ++ *

      ++ * This may cause loading of chunks! Some implementations may impose ++ * artificial restrictions on the maximum distance. ++ * ++ * @param start the start position ++ * @param direction the ray direction ++ * @param maxDistance the maximum distance ++ * @param fluidCollisionMode the fluid collision mode ++ * @param ignorePassableBlocks whether to ignore passable but collidable ++ * blocks (ex. tall grass, signs, fluids, ..) ++ * @param raySize entity bounding boxes will be uniformly expanded (or ++ * shrinked) by this value before doing collision checks ++ * @param filter only entities that fulfill this predicate are considered, ++ * or null to consider all entities ++ * @param canCollide predicate for blocks the ray can potentially collide ++ * with, or null to consider all blocks ++ * @return the closest ray trace hit result with either a block or an ++ * entity, or null if there is no hit ++ */ ++ @Nullable RayTraceResult rayTrace(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate filter, @Nullable Predicate canCollide); ++ // Paper end ++ + /** + * Gets the default spawn {@link Location} of this world + * diff --git a/patches/api/0422-Add-hand-to-fish-event-for-all-player-interactions.patch b/patches/api/0422-Add-hand-to-fish-event-for-all-player-interactions.patch new file mode 100644 index 000000000000..b431332b9a0a --- /dev/null +++ b/patches/api/0422-Add-hand-to-fish-event-for-all-player-interactions.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: booky10 +Date: Mon, 3 Jul 2023 01:55:32 +0200 +Subject: [PATCH] Add hand to fish event for all player interactions + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerFishEvent.java b/src/main/java/org/bukkit/event/player/PlayerFishEvent.java +index 45342030ad0f46632d3ee9a6d0348251f8ee375f..d4001f64a7ee9d5173e9bafd9c45860cbda1fc85 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerFishEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerFishEvent.java +@@ -94,8 +94,9 @@ public class PlayerFishEvent extends PlayerEvent implements Cancellable { + /** + * Get the hand that was used in this event. + *

      +- * The hand used is only present when the event state is {@link State#FISHING}. +- * In all other states, the hand is null. ++ * The hand used is only present for player interactions. ++ * This means it will be null if state is set ++ * to {@link State#BITE} or {@link State#FAILED_ATTEMPT}. + * + * @return the hand + */ diff --git a/patches/api/0423-Attribute-Modifier-API-improvements.patch b/patches/api/0423-Attribute-Modifier-API-improvements.patch new file mode 100644 index 000000000000..7384a7ae3bbb --- /dev/null +++ b/patches/api/0423-Attribute-Modifier-API-improvements.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TonytheMacaroni +Date: Thu, 9 Nov 2023 20:35:35 -0500 +Subject: [PATCH] Attribute Modifier API improvements + +Co-authored-by: Malfrador + +diff --git a/src/main/java/org/bukkit/attribute/AttributeInstance.java b/src/main/java/org/bukkit/attribute/AttributeInstance.java +index f08ee26cc4d479e1bfc5264b8cbe721315de91f2..f1fa86ddf1f50a357c9e94cc61261d8c96a2da6f 100644 +--- a/src/main/java/org/bukkit/attribute/AttributeInstance.java ++++ b/src/main/java/org/bukkit/attribute/AttributeInstance.java +@@ -39,6 +39,42 @@ public interface AttributeInstance { + @NotNull + Collection getModifiers(); + ++ // Paper start ++ /** ++ * Gets the modifier with the corresponding key. ++ * ++ * @param key the jey of the modifier ++ * @return the modifier, if it exists ++ */ ++ @org.jetbrains.annotations.Nullable AttributeModifier getModifier(@NotNull net.kyori.adventure.key.Key key); ++ ++ /** ++ * Remove a modifier with the corresponding key from this instance. ++ * ++ * @param key the key of the modifier ++ */ ++ void removeModifier(@NotNull net.kyori.adventure.key.Key key); ++ ++ /** ++ * Gets the modifier with the corresponding UUID. ++ * ++ * @param uuid the UUID of the modifier ++ * @return the modifier, if it exists ++ * @deprecated use {@link #getModifier(net.kyori.adventure.key.Key)}, modifiers are no longer stored by UUID ++ */ ++ @Deprecated(forRemoval = true, since = "1.21") ++ @org.jetbrains.annotations.Nullable AttributeModifier getModifier(@NotNull java.util.UUID uuid); ++ ++ /** ++ * Remove a modifier with the corresponding UUID from this instance. ++ * ++ * @param uuid the UUID of the modifier ++ * @deprecated use {@link #removeModifier(net.kyori.adventure.key.Key)}, modifiers are no longer stored by UUID ++ */ ++ @Deprecated(forRemoval = true, since = "1.21") ++ void removeModifier(@NotNull java.util.UUID uuid); ++ // Paper end ++ + /** + * Add a modifier to this instance. + * +@@ -46,6 +82,16 @@ public interface AttributeInstance { + */ + void addModifier(@NotNull AttributeModifier modifier); + ++ // Paper start - Transient modifier API ++ /** ++ * Add a transient modifier to this instance. ++ * Transient modifiers are not persisted (saved with the NBT data) ++ * ++ * @param modifier to add ++ */ ++ void addTransientModifier(@NotNull AttributeModifier modifier); ++ // Paper end ++ + /** + * Remove a modifier from this instance. + * +diff --git a/src/main/java/org/bukkit/attribute/AttributeModifier.java b/src/main/java/org/bukkit/attribute/AttributeModifier.java +index b90af00a8eb83d4c1b183fbc4f1e9eae84c9074b..4ad09a2673ce573b63d133635a772197a2062901 100644 +--- a/src/main/java/org/bukkit/attribute/AttributeModifier.java ++++ b/src/main/java/org/bukkit/attribute/AttributeModifier.java +@@ -48,6 +48,12 @@ public class AttributeModifier implements ConfigurationSerializable, Keyed { + this(NamespacedKey.fromString(uuid.toString()), amount, operation, slot); + } + ++ // Paper start - Add constructor without EquipmentSlotGroup ++ public AttributeModifier(@NotNull NamespacedKey key, double amount, @NotNull Operation operation) { ++ this(key, amount, operation, EquipmentSlotGroup.ANY); ++ } ++ // Paper end ++ + public AttributeModifier(@NotNull NamespacedKey key, double amount, @NotNull Operation operation, @NotNull EquipmentSlotGroup slot) { + Preconditions.checkArgument(key != null, "Key cannot be null"); + Preconditions.checkArgument(operation != null, "Operation cannot be null"); diff --git a/patches/api/0424-Expand-LingeringPotion-API.patch b/patches/api/0424-Expand-LingeringPotion-API.patch new file mode 100644 index 000000000000..4fc454cfb4fb --- /dev/null +++ b/patches/api/0424-Expand-LingeringPotion-API.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tamion <70228790+notTamion@users.noreply.github.com> +Date: Sat, 4 Nov 2023 23:56:23 +0100 +Subject: [PATCH] Expand LingeringPotion API + + +diff --git a/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java b/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java +index 581241d066310ba6f59811fee8cb32811b8e0b65..2392885ca6294079b939d25b8cbf23c12d86220d 100644 +--- a/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java ++++ b/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java +@@ -17,6 +17,7 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final AreaEffectCloud entity; ++ private boolean allowEmptyAreaEffectCreation; // Paper + + @Deprecated(since = "1.20.2") + public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final AreaEffectCloud entity) { +@@ -44,6 +45,26 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca + return entity; + } + ++ // Paper start ++ /** ++ * Sets if an Empty AreaEffectCloud may be created ++ * ++ * @param allowEmptyAreaEffectCreation If an Empty AreaEffectCloud may be created ++ */ ++ public void allowsEmptyCreation(boolean allowEmptyAreaEffectCreation) { ++ this.allowEmptyAreaEffectCreation = allowEmptyAreaEffectCreation; ++ } ++ ++ /** ++ * Gets if an empty AreaEffectCloud may be created ++ * ++ * @return if an empty AreaEffectCloud may be created ++ */ ++ public boolean allowsEmptyCreation() { ++ return allowEmptyAreaEffectCreation; ++ } ++ // Paper end ++ + @Override + public boolean isCancelled() { + return cancelled; diff --git a/patches/api/0425-Remove-unnecessary-durability-check-in-ItemStack-isS.patch b/patches/api/0425-Remove-unnecessary-durability-check-in-ItemStack-isS.patch new file mode 100644 index 000000000000..64f385ece019 --- /dev/null +++ b/patches/api/0425-Remove-unnecessary-durability-check-in-ItemStack-isS.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrPowerGamerBR +Date: Sun, 26 Nov 2023 20:00:50 -0300 +Subject: [PATCH] Remove unnecessary durability check in + "ItemStack#isSimilar(...)" + +By removing this check we avoid unnecessarily allocating useless `ItemMeta` objects if we are comparing two items, or one of the two items, that don't have any durability. Don't worry, the durability of the item is checked when it checks if both item metas are equal. + +This is a leftover from when checking for the item's durability was "free" because the durability was stored in the `ItemStack` itself, this [was changed in Minecraft 1.13](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/f8b2086d60942eb2cd7ac25a2a1408cb790c222c#src/main/java/org/bukkit/inventory/ItemStack.java). + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index bcead776776665fc7558ee11f928d842bd2e3da5..c3ae09dc66119cb2873201fb2975ad5e0f8237d2 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -307,7 +307,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + return true; + } + Material comparisonType = (this.type.isLegacy()) ? Bukkit.getUnsafe().fromLegacy(this.getData(), true) : this.type; // This may be called from legacy item stacks, try to get the right material +- return comparisonType == stack.getType() && getDurability() == stack.getDurability() && hasItemMeta() == stack.hasItemMeta() && (hasItemMeta() ? Bukkit.getItemFactory().equals(getItemMeta(), stack.getItemMeta()) : true); ++ return comparisonType == stack.getType() && /* getDurability() == stack.getDurability() && */hasItemMeta() == stack.hasItemMeta() && (hasItemMeta() ? Bukkit.getItemFactory().equals(getItemMeta(), stack.getItemMeta()) : true); // Paper - remove redundant item durability check + } + + @NotNull diff --git a/patches/api/0426-Add-Structure-check-API.patch b/patches/api/0426-Add-Structure-check-API.patch new file mode 100644 index 000000000000..3923a385a323 --- /dev/null +++ b/patches/api/0426-Add-Structure-check-API.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 27 Mar 2023 10:20:06 -0700 +Subject: [PATCH] Add Structure check API + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 3cb0aecf582b3d1c5195fca9160780ad5e98155a..1796615065c8a6d06450d1b9c389804e804c4327 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -78,6 +78,30 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + */ + int getPlayerCount(); + // Paper end ++ // Paper start - structure check API ++ /** ++ * Check if the naturally-generated structure exists at the position. ++ *

      ++ * Note that if the position is not loaded, this may cause chunk loads/generation ++ * to check if a structure is at that position. Use {@link #isPositionLoaded(io.papermc.paper.math.Position)} ++ * to check if a position is loaded ++ * ++ * @param position the position to check at ++ * @param structure the structure to check for ++ * @return true if that structure exists at the position ++ */ ++ boolean hasStructureAt(io.papermc.paper.math.@NotNull Position position, @NotNull Structure structure); ++ ++ /** ++ * Checks if this position is loaded. ++ * ++ * @param position position to check ++ * @return true if loaded ++ */ ++ default boolean isPositionLoaded(io.papermc.paper.math.@NotNull Position position) { ++ return this.isChunkLoaded(position.blockX() >> 4, position.blockZ() >> 4); ++ } ++ // Paper end + + /** + * Gets the {@link Block} at the given coordinates diff --git a/patches/api/0427-Experimental-annotations-change.patch b/patches/api/0427-Experimental-annotations-change.patch new file mode 100644 index 000000000000..52cbc8f45a1f --- /dev/null +++ b/patches/api/0427-Experimental-annotations-change.patch @@ -0,0 +1,201 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 9 Dec 2023 11:47:53 -0800 +Subject: [PATCH] Experimental annotations change + + +diff --git a/src/main/java/org/bukkit/FeatureFlag.java b/src/main/java/org/bukkit/FeatureFlag.java +index 54859fc5d8a14d26f22b57373045408d84766595..dd157b650aa7ac759d156ced30fa7514d34c43ed 100644 +--- a/src/main/java/org/bukkit/FeatureFlag.java ++++ b/src/main/java/org/bukkit/FeatureFlag.java +@@ -29,6 +29,7 @@ public interface FeatureFlag extends Keyed { + @Deprecated(since = "1.20.2") + public static final FeatureFlag UPDATE_1_20 = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("update_1_20")); + ++ @ApiStatus.Experimental // Paper - add missing annotation + public static final FeatureFlag TRADE_REBALANCE = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("trade_rebalance")); + + /** +@@ -47,8 +48,10 @@ public interface FeatureFlag extends Keyed { + @Deprecated(since = "1.21.4") + public static final FeatureFlag WINTER_DROP = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("winter_drop")); + ++ @ApiStatus.Experimental // Paper - add missing annotation + public static final FeatureFlag REDSTONE_EXPERIMENTS = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("redstone_experiments")); + ++ @ApiStatus.Experimental // Paper - add missing annotation + public static final FeatureFlag MINECART_IMPROVEMENTS = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("minecart_improvements")); + + } +diff --git a/src/main/java/org/bukkit/GameRule.java b/src/main/java/org/bukkit/GameRule.java +index 8b6584fae0a9d5cccbe350d889fa8b4a14c78ca3..89f1820ae94c48f51a44df750904bb285013720c 100644 +--- a/src/main/java/org/bukkit/GameRule.java ++++ b/src/main/java/org/bukkit/GameRule.java +@@ -287,6 +287,8 @@ public final class GameRule implements net.kyori.adventure.translation.Transl + * The maximum speed of minecarts (when the new movement algorithm is + * enabled). + */ ++ @MinecraftExperimental(MinecraftExperimental.Requires.MINECART_IMPROVEMENTS) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + public static final GameRule MINECART_MAX_SPEED = new GameRule<>("minecartMaxSpeed", Integer.class); + + /** +diff --git a/src/main/java/org/bukkit/block/Crafter.java b/src/main/java/org/bukkit/block/Crafter.java +index 8d2dd78fc588a6817dfede8040b9909a7d5bde67..f737a2aae3f57a1bfe4cf68ea66f603da4eebd47 100644 +--- a/src/main/java/org/bukkit/block/Crafter.java ++++ b/src/main/java/org/bukkit/block/Crafter.java +@@ -6,7 +6,6 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a captured state of a crafter. + */ +-@ApiStatus.Experimental + public interface Crafter extends Container, com.destroystokyo.paper.loottable.LootableBlockInventory { // Paper - LootTable API + + /** +diff --git a/src/main/java/org/bukkit/block/TrialSpawner.java b/src/main/java/org/bukkit/block/TrialSpawner.java +index 2d46d85aff243e9b3c6764f0de041fff6b766853..6fc7b5fe1152f739663a4715a1c93246c3ee6df2 100644 +--- a/src/main/java/org/bukkit/block/TrialSpawner.java ++++ b/src/main/java/org/bukkit/block/TrialSpawner.java +@@ -10,7 +10,6 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a captured state of a trial spawner. + */ +-@ApiStatus.Experimental + public interface TrialSpawner extends TileState { + + /** +diff --git a/src/main/java/org/bukkit/block/Vault.java b/src/main/java/org/bukkit/block/Vault.java +index f0c5d27f6f1ff56ffe4b88dfdce8d0b7f06d19e1..375f41fe4aebdbf140497b5ba1e54e1c72f0cdfc 100644 +--- a/src/main/java/org/bukkit/block/Vault.java ++++ b/src/main/java/org/bukkit/block/Vault.java +@@ -5,6 +5,5 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a captured state of a trial spawner. + */ +-@ApiStatus.Experimental + public interface Vault extends TileState { + } +diff --git a/src/main/java/org/bukkit/entity/AbstractWindCharge.java b/src/main/java/org/bukkit/entity/AbstractWindCharge.java +index 60fbacee263e55f91ac977f020e390d46024723a..ecff691c3a0878659fb051926ef769ce1e339c48 100644 +--- a/src/main/java/org/bukkit/entity/AbstractWindCharge.java ++++ b/src/main/java/org/bukkit/entity/AbstractWindCharge.java +@@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a Wind Charge. + */ +-@ApiStatus.Experimental + public interface AbstractWindCharge extends Fireball { + + /** +diff --git a/src/main/java/org/bukkit/entity/Bogged.java b/src/main/java/org/bukkit/entity/Bogged.java +index 6093b1dad8ad48708267a83bf4c1ad20467b3cf9..c84ddf808e2062dae7f68d574f05fbbc05273144 100644 +--- a/src/main/java/org/bukkit/entity/Bogged.java ++++ b/src/main/java/org/bukkit/entity/Bogged.java +@@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a Bogged Skeleton. + */ +-@ApiStatus.Experimental + public interface Bogged extends AbstractSkeleton, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API + + /** +diff --git a/src/main/java/org/bukkit/entity/Breeze.java b/src/main/java/org/bukkit/entity/Breeze.java +index a75e725805c193a408683885cba83ca168347165..254bc6e18961a72f471334cc0535e3c7a9d70012 100644 +--- a/src/main/java/org/bukkit/entity/Breeze.java ++++ b/src/main/java/org/bukkit/entity/Breeze.java +@@ -5,6 +5,5 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a Breeze. Whoosh! + */ +-@ApiStatus.Experimental + public interface Breeze extends Monster { + } +diff --git a/src/main/java/org/bukkit/entity/BreezeWindCharge.java b/src/main/java/org/bukkit/entity/BreezeWindCharge.java +index 06ca3dc4b0b69cbaefa96464dce484cea93e0717..748e58eb93c7882e15d9cbdd56d11bb14808698b 100644 +--- a/src/main/java/org/bukkit/entity/BreezeWindCharge.java ++++ b/src/main/java/org/bukkit/entity/BreezeWindCharge.java +@@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a Wind Charge. + */ +-@ApiStatus.Experimental + public interface BreezeWindCharge extends AbstractWindCharge { + + } +diff --git a/src/main/java/org/bukkit/entity/OminousItemSpawner.java b/src/main/java/org/bukkit/entity/OminousItemSpawner.java +index 4aa07d4edb2c81d0ae7999b30ad53ff8bb884ec7..dbd4da4c63b6b1b21c3e638ac4d2c9fdd6716a8e 100644 +--- a/src/main/java/org/bukkit/entity/OminousItemSpawner.java ++++ b/src/main/java/org/bukkit/entity/OminousItemSpawner.java +@@ -7,7 +7,6 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents an ominous item spawner. + */ +-@ApiStatus.Experimental + public interface OminousItemSpawner extends Entity { + + /** +diff --git a/src/main/java/org/bukkit/entity/WindCharge.java b/src/main/java/org/bukkit/entity/WindCharge.java +index 4adc91ba3dff00ab44303778e9d4499f7808ad00..beb62426490a361af793fb530106d8547a83ae03 100644 +--- a/src/main/java/org/bukkit/entity/WindCharge.java ++++ b/src/main/java/org/bukkit/entity/WindCharge.java +@@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Represents a Wind Charge. + */ +-@ApiStatus.Experimental + public interface WindCharge extends AbstractWindCharge { + + } +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java +index 06e037ce94b368b3685ab04ba46c1ab5e5479dbb..e0d73d432cd31da35a72b479c854f2124c63ebe5 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java +@@ -148,7 +148,6 @@ public enum InventoryType { + /** + * A crafter inventory, with 9 CRAFTING slots. + */ +- @ApiStatus.Experimental + CRAFTER(9, "Crafter", MenuType.CRAFTER_3X3), + /** + * The new smithing inventory, with 3 CRAFTING slots and 1 RESULT slot. +diff --git a/src/main/java/org/bukkit/inventory/CrafterInventory.java b/src/main/java/org/bukkit/inventory/CrafterInventory.java +index bb1fb5e0518c6a62ef8b206733ee51d831f1f85b..49d0a37bbeb0b8fa9207164c74245ef05485467c 100644 +--- a/src/main/java/org/bukkit/inventory/CrafterInventory.java ++++ b/src/main/java/org/bukkit/inventory/CrafterInventory.java +@@ -5,5 +5,4 @@ import org.jetbrains.annotations.ApiStatus; + /** + * Interface to the inventory of a Crafter. + */ +-@ApiStatus.Experimental + public interface CrafterInventory extends Inventory { } +diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java +index bd1c0417fbf72731e6301bf79966c6ea4102fc70..8d00f58883222fac4c3bef62eafa7bcbdedc896d 100644 +--- a/src/main/java/org/bukkit/map/MapCursor.java ++++ b/src/main/java/org/bukkit/map/MapCursor.java +@@ -314,12 +314,26 @@ public final class MapCursor { + Type BANNER_RED = getType("banner_red"); + Type BANNER_BLACK = getType("banner_black"); + Type RED_X = getType("red_x"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type VILLAGE_DESERT = getType("village_desert"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type VILLAGE_PLAINS = getType("village_plains"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type VILLAGE_SAVANNA = getType("village_savanna"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type VILLAGE_SNOWY = getType("village_snowy"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type VILLAGE_TAIGA = getType("village_taiga"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type JUNGLE_TEMPLE = getType("jungle_temple"); ++ @org.bukkit.MinecraftExperimental(org.bukkit.MinecraftExperimental.Requires.TRADE_REBALANCE) // Paper - add missing annotation ++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation + Type SWAMP_HUT = getType("swamp_hut"); + Type TRIAL_CHAMBERS = getType("trial_chambers"); + diff --git a/patches/api/0428-Add-more-scoreboard-API.patch b/patches/api/0428-Add-more-scoreboard-API.patch new file mode 100644 index 000000000000..34e12e5b96d6 --- /dev/null +++ b/patches/api/0428-Add-more-scoreboard-API.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 16 Dec 2023 14:45:46 -0800 +Subject: [PATCH] Add more scoreboard API + + +diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java +index d6d52bc9185e8a1581ccfa57df3550bc12d9872a..d8a249bb2dd8ab96962897c2a52f40ea288f7bd6 100644 +--- a/src/main/java/org/bukkit/scoreboard/Objective.java ++++ b/src/main/java/org/bukkit/scoreboard/Objective.java +@@ -175,4 +175,24 @@ public interface Objective { + */ + @NotNull Score getScoreFor(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException, IllegalStateException; + // Paper end - improve scoreboard entries ++ ++ // Paper start - add more score API ++ /** ++ * Gets if this objective will auto update score ++ * displays on changes. ++ * ++ * @return true if auto updating ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ boolean willAutoUpdateDisplay(); ++ ++ /** ++ * Sets if this objective will auto update ++ * score displays on changes. ++ * ++ * @param autoUpdateDisplay true to auto update ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ void setAutoUpdateDisplay(boolean autoUpdateDisplay); ++ // Paper end - add more score API + } +diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java +index 48a1654a2dd8da82cb91bcfa4b3a523f88323568..a3b482e07bb3dceb9b81d66c7208556a0bedd948 100644 +--- a/src/main/java/org/bukkit/scoreboard/Score.java ++++ b/src/main/java/org/bukkit/scoreboard/Score.java +@@ -83,4 +83,50 @@ public interface Score { + */ + void resetScore() throws IllegalStateException; + // Paper end ++ ++ // Paper start - add more score API ++ /** ++ * Gets if this score is triggerable and cannot ++ * be used by the {@code /trigger} command executed ++ * by the owner of this score. ++ * ++ * @return true if triggerable, false if not triggerable, score isn't set, or the objective isn't {@link Criteria#TRIGGER} ++ * @throws IllegalStateException if the associated objective has been unregistered ++ */ ++ boolean isTriggerable(); ++ ++ /** ++ * Sets if this score is triggerable and can ++ * be used by the {@code /trigger} command ++ * executed by the owner of this score. Can ++ * only be set on {@link Criteria#TRIGGER} objectives. ++ *

      ++ * If the score doesn't exist (aka {@link #isScoreSet()} returns false), ++ * this will create the score with a 0 value. ++ * ++ * @param triggerable true to enable trigger, false to disable ++ * @throws IllegalArgumentException if this objective isn't {@link Criteria#TRIGGER} ++ * @throws IllegalStateException if the associated objective has been unregistered ++ */ ++ void setTriggerable(boolean triggerable); ++ ++ /** ++ * Get the custom name for this entry. ++ * ++ * @return the custom name or null if not set (or score isn't set) ++ * @throws IllegalStateException if the associated objective has been unregistered ++ */ ++ @Nullable net.kyori.adventure.text.Component customName(); ++ ++ /** ++ * Sets the custom name for this entry. ++ *

      ++ * If the score doesn't exist (aka {@link #isScoreSet()} returns false), ++ * this will create the score with a 0 value. ++ * ++ * @param customName the custom name or null to reset ++ * @throws IllegalStateException if the associated objective has been unregistered ++ */ ++ void customName(net.kyori.adventure.text.@Nullable Component customName); ++ // Paper end - add more score API + } diff --git a/patches/api/0429-Improve-Registry.patch b/patches/api/0429-Improve-Registry.patch new file mode 100644 index 000000000000..96e3965ecda7 --- /dev/null +++ b/patches/api/0429-Improve-Registry.patch @@ -0,0 +1,320 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 20 Dec 2023 02:03:10 -0800 +Subject: [PATCH] Improve Registry + +Adds Registry#getKey(Object) which should be the +primary way people get the key for an object. Registry +items need to exist without having a key and so +getKey() methods on Keyed objects that have a registry +are marked as Deprecated or Obsolete. + +diff --git a/src/main/java/org/bukkit/Art.java b/src/main/java/org/bukkit/Art.java +index d24bf449f58fd7c1b8ffab8dbc42f9f1fef8c4ef..a53e59e030aea65a99806d5b0375cbb4b7457319 100644 +--- a/src/main/java/org/bukkit/Art.java ++++ b/src/main/java/org/bukkit/Art.java +@@ -97,6 +97,26 @@ public interface Art extends OldEnum, Keyed { + @Deprecated(since = "1.6.2") + int getId(); + ++ // Paper start - deprecate getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#PAINTING_VARIANT}. Painting variants can exist without a key. ++ */ ++ @Deprecated(since = "1.21", forRemoval = true) ++ @Override ++ @NotNull NamespacedKey getKey(); ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#PAINTING_VARIANT}. Painting variants can exist without a key. ++ */ ++ @Deprecated(since = "1.21", forRemoval = true) ++ @Override ++ default net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return Keyed.super.key(); ++ } ++ // Paper end - deprecate getKey ++ + /** + * Get a painting by its numeric ID + * +diff --git a/src/main/java/org/bukkit/MusicInstrument.java b/src/main/java/org/bukkit/MusicInstrument.java +index 3b107e35f006cb1a0745778d99dab0783c67d4d8..d41892af5253623112fb3f8c53958c7914609e30 100644 +--- a/src/main/java/org/bukkit/MusicInstrument.java ++++ b/src/main/java/org/bukkit/MusicInstrument.java +@@ -47,6 +47,27 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran + return Registry.INSTRUMENT.getOrThrow(NamespacedKey.minecraft(key)); + } + ++ // Paper start - deprecate getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT}. MusicInstruments can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.5") ++ @Override ++ public abstract @NotNull NamespacedKey getKey(); ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT}. MusicInstruments can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.5") ++ @Override ++ public net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return Keyed.super.key(); ++ } ++ ++ // Paper end - deprecate getKey ++ + // Paper start - mark translation key as deprecated + /** + * @deprecated this method assumes that the instrument description +diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java +index b2bd12736d08fe72128142af4ca2022da8309f6d..c3d49f9c640eb390f507f9521a389cb7c172983a 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -385,6 +385,79 @@ public interface Registry extends Iterable { + @Nullable + T get(@NotNull NamespacedKey key); + ++ // Paper start - improve Registry ++ /** ++ * Gets the object by its key or throws if it doesn't exist. ++ * ++ * @param key the key to get the object of in this registry ++ * @return the object for the key ++ * @throws java.util.NoSuchElementException if the key doesn't point to an object in the registry ++ */ ++ default @NotNull T getOrThrow(final net.kyori.adventure.key.@NotNull Key key) { ++ final T value = this.get(key); ++ if (value == null) { ++ throw new java.util.NoSuchElementException("No value for " + key + " in " + this); ++ } ++ return value; ++ } ++ ++ /** ++ * Gets the object by its key or throws if it doesn't exist. ++ * ++ * @param key the key to get the object of in this registry ++ * @return the object for the key ++ * @throws java.util.NoSuchElementException if the key doesn't point to an object in the registry ++ */ ++ default @NotNull T getOrThrow(final io.papermc.paper.registry.@NotNull TypedKey key) { ++ final T value = this.get(key); ++ if (value == null) { ++ throw new java.util.NoSuchElementException("No value for " + key + " in " + this); ++ } ++ return value; ++ } ++ ++ /** ++ * Gets the key for this object or throws if it doesn't exist. ++ *

      ++ * Some types can exist without being in a registry ++ * and such will have no key associated with them. This ++ * method throw an exception if it isn't in this registry. ++ * ++ * @param value the value to get the key of in this registry ++ * @return the key for the value ++ * @throws java.util.NoSuchElementException if the value doesn't exist in this registry ++ * @see #getKey(Keyed) ++ */ ++ default @NotNull NamespacedKey getKeyOrThrow(final @NotNull T value) { ++ Preconditions.checkArgument(value != null, "value cannot be null"); ++ final NamespacedKey key = this.getKey(value); ++ if (key == null) { ++ throw new java.util.NoSuchElementException(value + " has no key in " + this); ++ } ++ return key; ++ } ++ ++ /** ++ * Get the key for this object. ++ *

      ++ * Some types can exist without being in a registry ++ * and such will have no key associated with them. This ++ * method will return null. ++ * ++ * @param value the value to get the key of in this registry ++ * @return the key for the value or null if not in the registry ++ * @see #getKeyOrThrow(Keyed) ++ */ ++ default @Nullable NamespacedKey getKey(final @NotNull T value) { ++ Preconditions.checkArgument(value != null, "value cannot be null"); ++ //noinspection ConstantValue (it might not be in the future...) ++ if (value instanceof Keyed) { ++ return value.getKey(); ++ } ++ return null; ++ } ++ // Paper end - improve Registry ++ + /** + * Get the object by its key. + * +@@ -481,5 +554,12 @@ public interface Registry extends Iterable { + public Class getType() { + return this.type; + } ++ ++ // Paper start - improve Registry ++ @Override ++ public @NotNull NamespacedKey getKey(final @NotNull T value) { ++ return value.getKey(); ++ } ++ // Paper end - improve Registry + } + } +diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java +index 779fd6dd572dea41e7e22464c9c6068a0fb71b9d..70d6dedcad934be38ec5dc3807ec946b0fe3b649 100644 +--- a/src/main/java/org/bukkit/Sound.java ++++ b/src/main/java/org/bukkit/Sound.java +@@ -1704,6 +1704,16 @@ public interface Sound extends OldEnum, Keyed, net.kyori.adventure.sound. + return sound; + } + ++ // Paper start - deprecate getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)} and {@link Registry#SOUNDS}. Sounds ++ * can exist without a key. ++ */ ++ @Deprecated(since = "1.20.5", forRemoval = true) ++ @Override ++ @NotNull NamespacedKey getKey(); ++ // Paper end - deprecate getKey ++ + /** + * @return an array of all known sounds. + * @deprecated use {@link Registry#iterator()}. +@@ -1715,6 +1725,11 @@ public interface Sound extends OldEnum, Keyed, net.kyori.adventure.sound. + } + + // Paper start ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)} and {@link Registry#SOUNDS}. Sounds ++ * can exist without a key. ++ */ ++ @Deprecated(since = "1.20.5", forRemoval = true) + @Override + default net.kyori.adventure.key.@NotNull Key key() { + return this.getKey(); +diff --git a/src/main/java/org/bukkit/block/banner/PatternType.java b/src/main/java/org/bukkit/block/banner/PatternType.java +index b6aa112ffcf43c8854e4060a83117cdc311c937d..4620b39b3257a29f964f94a2ddef9c46a365baa1 100644 +--- a/src/main/java/org/bukkit/block/banner/PatternType.java ++++ b/src/main/java/org/bukkit/block/banner/PatternType.java +@@ -56,6 +56,23 @@ public interface PatternType extends OldEnum, Keyed { + PatternType FLOW = getType("flow"); + PatternType GUSTER = getType("guster"); + ++ // Paper start - deprecate getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#BANNER_PATTERN}. PatternTypes can exist without a key. ++ */ ++ @Deprecated(since = "1.20.5", forRemoval = true) ++ @Override ++ default net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return org.bukkit.Keyed.super.key(); ++ } ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#BANNER_PATTERN}. PatternTypes can exist without a key. ++ */ ++ @Deprecated(since = "1.20.5", forRemoval = true) ++ // Paper end - deprecate getKey + @Override + @NotNull + public NamespacedKey getKey(); +diff --git a/src/main/java/org/bukkit/generator/structure/Structure.java b/src/main/java/org/bukkit/generator/structure/Structure.java +index 20a7fd27ba3a029d58dd18ad9b470ffaed8c9578..b6920f834f8f5992214734abd093af54fc01991c 100644 +--- a/src/main/java/org/bukkit/generator/structure/Structure.java ++++ b/src/main/java/org/bukkit/generator/structure/Structure.java +@@ -61,4 +61,24 @@ public abstract class Structure implements Keyed { + */ + @NotNull + public abstract StructureType getStructureType(); ++ // Paper start - deprecate getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#STRUCTURE}. Structures can exist without a key. ++ */ ++ @Override ++ @Deprecated(since = "1.20.4", forRemoval = true) ++ public abstract @NotNull NamespacedKey getKey(); ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#STRUCTURE}. Structures can exist without a key. ++ */ ++ @Override ++ @Deprecated(since = "1.20.4", forRemoval = true) ++ public net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return org.bukkit.Keyed.super.key(); ++ } ++ ++ // Paper end - deprecate getKey + } +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +index cc38bee3c412bef4767f08407c0f5559a113fce5..7e8a4b4ec625072cb4aff1f9e113d9d0c162dc8c 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +@@ -78,4 +78,25 @@ public interface TrimMaterial extends Keyed, Translatable { + @Deprecated(forRemoval = true) + @org.jetbrains.annotations.NotNull String getTranslationKey(); + // Paper end - adventure ++ ++ // Paper start - Registry#getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#TRIM_MATERIAL}. TrimMaterials can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ org.bukkit.@org.jetbrains.annotations.NotNull NamespacedKey getKey(); ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#TRIM_MATERIAL}. TrimMaterials can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ default net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return org.bukkit.Keyed.super.key(); ++ } ++ ++ // Paper end - Registry#getKey + } +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +index 56cfe665daba1754e41f633d7c18172bebf87028..b2fa0d565b2492aa812b0ac036ecd74889f67f76 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +@@ -106,4 +106,24 @@ public interface TrimPattern extends Keyed, Translatable { + @Deprecated(forRemoval = true) + @org.jetbrains.annotations.NotNull String getTranslationKey(); + // Paper end - adventure ++ ++ // Paper start - Registry#getKey ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#TRIM_PATTERN}. TrimPatterns can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ org.bukkit.@org.jetbrains.annotations.NotNull NamespacedKey getKey(); ++ ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, ++ * and {@link io.papermc.paper.registry.RegistryKey#TRIM_PATTERN}. TrimPatterns can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ default net.kyori.adventure.key.@org.jetbrains.annotations.NotNull Key key() { ++ return org.bukkit.Keyed.super.key(); ++ } ++ // Paper end - Registry#getKey + } diff --git a/patches/api/0430-Add-experience-points-API.patch b/patches/api/0430-Add-experience-points-API.patch new file mode 100644 index 000000000000..8951bfce950f --- /dev/null +++ b/patches/api/0430-Add-experience-points-API.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lukas Planz +Date: Tue, 5 Sep 2023 20:33:52 +0200 +Subject: [PATCH] Add experience points API + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index d84fe3e439f3b190b7bbec15f406cc3a393dccfc..a7a4e5423cedb67bcdf02738be62bdf83e748b82 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -1947,6 +1947,45 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @param exp New total experience points + */ + public void setTotalExperience(int exp); ++ // Paper start ++ /** ++ * Gets the players total amount of experience points he collected to reach the current level and level progress. ++ * ++ *

      This method differs from {@link #getTotalExperience()} in that this method always returns an ++ * up-to-date value that reflects the players{@link #getLevel() level} and {@link #getExp() level progress}

      ++ * ++ * @return Current total experience points ++ * @see #getLevel() ++ * @see #getExp() ++ * @see #setExperienceLevelAndProgress(int) ++ */ ++ @org.jetbrains.annotations.Range(from = 0, to = Integer.MAX_VALUE) int calculateTotalExperiencePoints(); ++ ++ /** ++ * Updates the players level and level progress to that what would be reached when the total amount of experience ++ * had been collected. ++ * ++ *

      This method differs from {@link #setTotalExperience(int)} in that this method actually updates the ++ * {@link #getLevel() level} and {@link #getExp() level progress} so that a subsequent call of ++ * {@link #calculateTotalExperiencePoints()} yields the same amount of points that have been set

      ++ * ++ * @param totalExperience New total experience points ++ * @see #setLevel(int) ++ * @see #setExp(float) ++ * @see #calculateTotalExperiencePoints() ++ */ ++ void setExperienceLevelAndProgress(@org.jetbrains.annotations.Range(from = 0, to = Integer.MAX_VALUE) int totalExperience); ++ ++ /** ++ * Gets the total amount of experience points that are needed to reach the next level from zero progress towards it. ++ * ++ *

      Can be used with {@link #getExp()} to calculate the current points for the current level and alike

      ++ * ++ * @return The required experience points ++ * @see #getExp() ++ */ ++ int getExperiencePointsNeededForNextLevel(); ++ // Paper end + + /** + * Send an experience change. diff --git a/patches/api/0431-Add-missing-InventoryType.patch b/patches/api/0431-Add-missing-InventoryType.patch new file mode 100644 index 000000000000..d3d0cd545825 --- /dev/null +++ b/patches/api/0431-Add-missing-InventoryType.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 27 Dec 2023 16:46:13 -0800 +Subject: [PATCH] Add missing InventoryType + +Upstream did not add a DECORATED_POT inventory type + +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java +index e0d73d432cd31da35a72b479c854f2124c63ebe5..81118a91c2e22e02a1f774d1cc4d3e97064087ce 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java +@@ -145,6 +145,12 @@ public enum InventoryType { + * Pseudo jukebox inventory with 1 slot of undefined type. + */ + JUKEBOX(1, "Jukebox", null, false), ++ // Paper start - add missing type ++ /** ++ * Pseudo decorated pot with 1 slot of undefined type. ++ */ ++ DECORATED_POT(1, "Decorated Pot", null, false), ++ // Paper end - add missing type + /** + * A crafter inventory, with 9 CRAFTING slots. + */ diff --git a/patches/api/0432-Add-drops-to-shear-events.patch b/patches/api/0432-Add-drops-to-shear-events.patch new file mode 100644 index 000000000000..abbab7dac401 --- /dev/null +++ b/patches/api/0432-Add-drops-to-shear-events.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 18 May 2021 12:31:54 -0700 +Subject: [PATCH] Add drops to shear events + + +diff --git a/src/main/java/org/bukkit/event/block/BlockShearEntityEvent.java b/src/main/java/org/bukkit/event/block/BlockShearEntityEvent.java +index 71c0af9373069cfaa074e1fbad592eab81025b1c..610768bd329b8612627d361fd9a773a7b91ff108 100644 +--- a/src/main/java/org/bukkit/event/block/BlockShearEntityEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockShearEntityEvent.java +@@ -17,11 +17,14 @@ public class BlockShearEntityEvent extends BlockEvent implements Cancellable { + private final Entity sheared; + private final ItemStack tool; + private boolean cancelled; ++ private java.util.List drops; // Paper + +- public BlockShearEntityEvent(@NotNull Block dispenser, @NotNull Entity sheared, @NotNull ItemStack tool) { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public BlockShearEntityEvent(@NotNull Block dispenser, @NotNull Entity sheared, @NotNull ItemStack tool, final @NotNull java.util.List drops) { // Paper - custom shear drops + super(dispenser); + this.sheared = sheared; + this.tool = tool; ++ this.drops = drops; // Paper + } + + /** +@@ -64,4 +67,24 @@ public class BlockShearEntityEvent extends BlockEvent implements Cancellable { + public static HandlerList getHandlerList() { + return handlers; + } ++ // Paper start - custom shear drops ++ /** ++ * Get an immutable list of drops for this shearing. ++ * ++ * @return the shearing drops ++ * @see #setDrops(java.util.List) ++ */ ++ public java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List getDrops() { ++ return java.util.Collections.unmodifiableList(this.drops); ++ } ++ ++ /** ++ * Sets the drops for the shearing. ++ * ++ * @param drops the shear drops ++ */ ++ public void setDrops(final java.util.@NotNull List drops) { ++ this.drops = java.util.List.copyOf(drops); ++ } ++ // Paper end - custom shear drops + } +diff --git a/src/main/java/org/bukkit/event/player/PlayerShearEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerShearEntityEvent.java +index 2616943d298c523e9fe71926f42b1362c9379853..3a12674e47f3e20a32ac1ea5647105196cf3a1c9 100644 +--- a/src/main/java/org/bukkit/event/player/PlayerShearEntityEvent.java ++++ b/src/main/java/org/bukkit/event/player/PlayerShearEntityEvent.java +@@ -18,17 +18,20 @@ public class PlayerShearEntityEvent extends PlayerEvent implements Cancellable { + private final Entity what; + private final ItemStack item; + private final EquipmentSlot hand; ++ private java.util.List drops; // Paper - custom shear drops + +- public PlayerShearEntityEvent(@NotNull Player who, @NotNull Entity what, @NotNull ItemStack item, @NotNull EquipmentSlot hand) { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public PlayerShearEntityEvent(@NotNull Player who, @NotNull Entity what, @NotNull ItemStack item, @NotNull EquipmentSlot hand, final java.util.@NotNull List drops) { // Paper - custom shear drops + super(who); + this.what = what; + this.item = item; + this.hand = hand; ++ this.drops = drops; // Paper - custom shear drops + } + + @Deprecated(since = "1.15.2") + public PlayerShearEntityEvent(@NotNull final Player who, @NotNull final Entity what) { +- this(who, what, new ItemStack(Material.SHEARS), EquipmentSlot.HAND); ++ this(who, what, new ItemStack(Material.SHEARS), EquipmentSlot.HAND, java.util.Collections.emptyList()); // Paper - custom shear drops + } + + @Override +@@ -82,4 +85,24 @@ public class PlayerShearEntityEvent extends PlayerEvent implements Cancellable { + return handlers; + } + ++ // Paper start - custom shear drops ++ /** ++ * Get an immutable list of drops for this shearing. ++ * ++ * @return the shearing drops ++ * @see #setDrops(java.util.List) ++ */ ++ public java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List getDrops() { ++ return this.drops; ++ } ++ ++ /** ++ * Sets the drops for the shearing. ++ * ++ * @param drops the shear drops ++ */ ++ public void setDrops(final java.util.@NotNull List drops) { ++ this.drops = java.util.List.copyOf(drops); ++ } ++ // Paper end - custom shear drops + } diff --git a/patches/api/0433-Add-HiddenPotionEffect-API.patch b/patches/api/0433-Add-HiddenPotionEffect-API.patch new file mode 100644 index 000000000000..1e0c0ad3671c --- /dev/null +++ b/patches/api/0433-Add-HiddenPotionEffect-API.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tamion <70228790+notTamion@users.noreply.github.com> +Date: Sun, 5 Nov 2023 09:50:48 +0100 +Subject: [PATCH] Add HiddenPotionEffect API + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 7cc29c7a9e2c30feaedaab188024387e12f51c75..ac86962fa3c0fb0c3138e98bd89d73b467a5fb60 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -591,6 +591,9 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + + /** + * Adds the given {@link PotionEffect} to the living entity. ++ *

      ++ * Note: {@link PotionEffect#getHiddenPotionEffect()} is ignored when ++ * adding the effect to the entity. + * + * @param effect PotionEffect to be added + * @return whether the effect could be added +@@ -615,6 +618,9 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + /** + * Attempts to add all of the given {@link PotionEffect} to the living + * entity. ++ *

      ++ * Note: {@link PotionEffect#getHiddenPotionEffect()} is ignored when ++ * adding the effect to the entity. + * + * @param effects the effects to add + * @return whether all of the effects could be added +diff --git a/src/main/java/org/bukkit/potion/PotionEffect.java b/src/main/java/org/bukkit/potion/PotionEffect.java +index 0d60a1b740199783d3fcb775f190ee85bd84696b..ab8f3c089ff50f4414d4c35810e65b2e73e2f678 100644 +--- a/src/main/java/org/bukkit/potion/PotionEffect.java ++++ b/src/main/java/org/bukkit/potion/PotionEffect.java +@@ -28,6 +28,7 @@ public class PotionEffect implements ConfigurationSerializable { + */ + public static final int INFINITE_DURATION = -1; + ++ private static final String HIDDEN_EFFECT = "hidden_effect"; // Paper + private static final String AMPLIFIER = "amplifier"; + private static final String DURATION = "duration"; + private static final String TYPE = "effect"; +@@ -40,6 +41,7 @@ public class PotionEffect implements ConfigurationSerializable { + private final boolean ambient; + private final boolean particles; + private final boolean icon; ++ private final PotionEffect hiddenEffect; // Paper + + /** + * Creates a potion effect. +@@ -50,8 +52,11 @@ public class PotionEffect implements ConfigurationSerializable { + * @param ambient the ambient status, see {@link PotionEffect#isAmbient()} + * @param particles the particle status, see {@link PotionEffect#hasParticles()} + * @param icon the icon status, see {@link PotionEffect#hasIcon()} ++ * @param hiddenEffect the hidden PotionEffect ++ * @hidden Internal-- hidden effects are only shown internally + */ +- public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect) { // Paper + Preconditions.checkArgument(type != null, "effect type cannot be null"); + this.type = type; + this.duration = duration; +@@ -59,6 +64,23 @@ public class PotionEffect implements ConfigurationSerializable { + this.ambient = ambient; + this.particles = particles; + this.icon = icon; ++ // Paper start ++ this.hiddenEffect = hiddenEffect; ++ } ++ ++ /** ++ * Creates a potion effect. ++ * @param type effect type ++ * @param duration measured in ticks, see {@link ++ * PotionEffect#getDuration()} ++ * @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()} ++ * @param ambient the ambient status, see {@link PotionEffect#isAmbient()} ++ * @param particles the particle status, see {@link PotionEffect#hasParticles()} ++ * @param icon the icon status, see {@link PotionEffect#hasIcon()} ++ */ ++ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { ++ this(type, duration, amplifier, ambient, particles, icon, null); ++ // Paper end + } + + /** +@@ -106,7 +128,7 @@ public class PotionEffect implements ConfigurationSerializable { + * @param map the map to deserialize from + */ + public PotionEffect(@NotNull Map map) { +- this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true))); ++ this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT)); // Paper + } + + // Paper start +@@ -134,6 +156,19 @@ public class PotionEffect implements ConfigurationSerializable { + public PotionEffect withIcon(boolean icon) { + return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); + } ++ ++ /** ++ * Returns the PotionEffect that will become active ++ * after the current PotionEffect has run out. ++ *

      ++ * Note: This value is only applicable to type applied to living entities. ++ * ++ * @return The hidden PotionEffect. ++ */ ++ @Nullable ++ public PotionEffect getHiddenPotionEffect() { ++ return hiddenEffect; ++ } + // Paper end + + @NotNull +@@ -170,19 +205,27 @@ public class PotionEffect implements ConfigurationSerializable { + @Override + @NotNull + public Map serialize() { +- return ImmutableMap.builder() ++ ImmutableMap.Builder builder = ImmutableMap.builder() // Paper + .put(TYPE, type.getKey().toString()) + .put(DURATION, duration) + .put(AMPLIFIER, amplifier) + .put(AMBIENT, ambient) + .put(PARTICLES, particles) +- .put(ICON, icon) +- .build(); ++ .put(ICON, icon); ++ // Paper start ++ if (this.hiddenEffect != null) { ++ builder.put(HIDDEN_EFFECT, this.hiddenEffect); ++ } ++ return builder.build(); ++ // Paper end + } + + /** + * Attempts to add the effect represented by this object to the given + * {@link LivingEntity}. ++ *

      ++ * Note: {@link PotionEffect#getHiddenPotionEffect()} is ignored when ++ * adding the effect to the entity. + * + * @param entity The entity to add this effect to + * @return Whether the effect could be added +@@ -201,7 +244,7 @@ public class PotionEffect implements ConfigurationSerializable { + return false; + } + PotionEffect that = (PotionEffect) obj; +- return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon; ++ return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect); // Paper + } + + /** +@@ -306,11 +349,12 @@ public class PotionEffect implements ConfigurationSerializable { + hash ^= 0x22222222 >> (ambient ? 1 : -1); + hash ^= 0x22222222 >> (particles ? 1 : -1); + hash ^= 0x22222222 >> (icon ? 1 : -1); ++ if (hiddenEffect != null) hash = hash * 31 + hiddenEffect.hashCode(); // Paper + return hash; + } + + @Override + public String toString() { +- return type.getName() + (ambient ? ":(" : ":") + duration + "t-x" + amplifier + (ambient ? ")" : ""); ++ return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + '}'; // Paper + } + } diff --git a/patches/api/0434-Add-PlayerShieldDisableEvent.patch b/patches/api/0434-Add-PlayerShieldDisableEvent.patch new file mode 100644 index 000000000000..ddc6deadf570 --- /dev/null +++ b/patches/api/0434-Add-PlayerShieldDisableEvent.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 1 May 2023 16:22:43 -0500 +Subject: [PATCH] Add PlayerShieldDisableEvent + +Called whenever a players shield is disabled. This is mainly caused by +attacking players or monsters that carry axes. + +The event, while similar to the PlayerItemCooldownEvent, offers other +behaviour and can hence not be implemented as a childtype of said event. +Specifically, cancelling the event prevents the game events from being +sent to the player. + +Plugins listening to just the PlayerItemCooldownEvent may not want said +sideeffects, meaning the disable event cannot share a handlerlist with +the cooldown event. + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerShieldDisableEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerShieldDisableEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aa2fb7923b121cda547291d14cff60895361a4dd +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerShieldDisableEvent.java +@@ -0,0 +1,90 @@ ++package io.papermc.paper.event.player; ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called whenever a players shield is disabled due to an attack from another entity that was capable of disabling the ++ * shield. This, most commonly, may be another player attacking with an axe. ++ *

      ++ * Notably, this even is distinct from a {@link PlayerItemCooldownEvent} and will fire prior to the item going on ++ * cooldown. ++ * It follows that, if this event is cancelled, no {@link PlayerItemCooldownEvent} is called as the shield is never ++ * disabled in the first place. ++ */ ++@NullMarked ++public class PlayerShieldDisableEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity damager; ++ private int cooldown; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public PlayerShieldDisableEvent(final Player player, final Entity damager, final int cooldown) { ++ super(player); ++ this.damager = damager; ++ this.cooldown = cooldown; ++ } ++ ++ /** ++ * Provides the damager that disabled the shield. ++ * ++ * @return the entity instance that damaged the player in a way that caused the shield to be disabled. ++ */ ++ public Entity getDamager() { ++ return this.damager; ++ } ++ ++ /** ++ * Gets the cooldown the disabled shield will be disabled for in ticks. ++ *

      ++ * Notably, this value is not final as it might be changed by a {@link PlayerItemCooldownEvent} down the line, ++ * as said event is called if this event is not cancelled. ++ * ++ * @return cooldown in ticks ++ */ ++ public int getCooldown() { ++ return this.cooldown; ++ } ++ ++ /** ++ * Sets the cooldown of the shield in ticks. ++ *

      ++ * Notably, this value is not final as it might be changed by a {@link PlayerItemCooldownEvent} down the line, ++ * as said event is called if this event is not cancelled. ++ * ++ * @param cooldown cooldown in ticks, has to be a positive number ++ */ ++ public void setCooldown(final int cooldown) { ++ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!"); ++ this.cooldown = cooldown; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0435-Return-null-for-empty-String-in-NamespacedKey.fromSt.patch b/patches/api/0435-Return-null-for-empty-String-in-NamespacedKey.fromSt.patch new file mode 100644 index 000000000000..0701be14b5aa --- /dev/null +++ b/patches/api/0435-Return-null-for-empty-String-in-NamespacedKey.fromSt.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Sat, 6 Jan 2024 14:18:58 +0100 +Subject: [PATCH] Return null for empty String in NamespacedKey.fromString + + +diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java +index ceb1009252e25e244baab9208b7494666aebc508..6d266c111bfa2bd51338e03ed740f6ac81ed07c7 100644 +--- a/src/main/java/org/bukkit/NamespacedKey.java ++++ b/src/main/java/org/bukkit/NamespacedKey.java +@@ -90,7 +90,7 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap + this.key = key; + + String string = toString(); +- Preconditions.checkArgument(string.length() < 256, "NamespacedKey must be less than 256 characters", string); ++ Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation + } + + /** +@@ -117,7 +117,7 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap + Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key); + + String string = toString(); +- Preconditions.checkArgument(string.length() < 256, "NamespacedKey must be less than 256 characters (%s)", string); ++ Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation + } + + @NotNull +@@ -205,7 +205,10 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap + */ + @Nullable + public static NamespacedKey fromString(@NotNull String string, @Nullable Plugin defaultNamespace) { +- Preconditions.checkArgument(string != null && !string.isEmpty(), "Input string must not be empty or null"); ++ // Paper - Return null for empty string, check length ++ Preconditions.checkArgument(string != null, "Input string must not be null"); ++ if (string.isEmpty() || string.length() > Short.MAX_VALUE) return null; ++ // Paper end - Return null for empty string, check length + + String[] components = string.split(":", 3); + if (components.length > 2) { +diff --git a/src/test/java/org/bukkit/NamespacedKeyTest.java b/src/test/java/org/bukkit/NamespacedKeyTest.java +index 6317798e43332f34f79970ded0f023beee868fed..d4e9e24b705a7ac3e9f4fc27eefa44ecb16aa35c 100644 +--- a/src/test/java/org/bukkit/NamespacedKeyTest.java ++++ b/src/test/java/org/bukkit/NamespacedKeyTest.java +@@ -29,6 +29,7 @@ public class NamespacedKeyTest { + assertNull(NamespacedKey.fromString("foo:bar:bazz")); + } + ++ @org.junit.jupiter.api.Disabled // Paper - Fixup NamespacedKey handling + @Test + public void testFromStringEmptyInput() { + assertThrows(IllegalArgumentException.class, () -> NamespacedKey.fromString("")); +@@ -75,6 +76,7 @@ public class NamespacedKeyTest { + "loremipsumdolorsitametconsecteturadipiscingelitduisvolutpatvelitsitametmaximusscelerisquemorbiullamcorperexacconsequategestas").toString(); + } + ++ @org.junit.jupiter.api.Disabled // Paper - Fixup NamespacedKey handling + @Test + public void testAboveLength() { + assertThrows(IllegalArgumentException.class, () -> new NamespacedKey("loremipsumdolorsitametconsecteturadipiscingelitduisvolutpatvelitsitametmaximusscelerisquemorbiullamcorperexacconsequategestas", diff --git a/patches/api/0436-Add-BlockStateMeta-clearBlockState.patch b/patches/api/0436-Add-BlockStateMeta-clearBlockState.patch new file mode 100644 index 000000000000..7e8c47a8e2be --- /dev/null +++ b/patches/api/0436-Add-BlockStateMeta-clearBlockState.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 11 Jan 2024 12:41:54 -0800 +Subject: [PATCH] Add BlockStateMeta#clearBlockState + + +diff --git a/src/main/java/org/bukkit/inventory/meta/BlockStateMeta.java b/src/main/java/org/bukkit/inventory/meta/BlockStateMeta.java +index c7d3041221742f6655155f19ef2addcaf2401015..dedb33e3d7f99e12fddba438af0874e6973d9372 100644 +--- a/src/main/java/org/bukkit/inventory/meta/BlockStateMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/BlockStateMeta.java +@@ -14,6 +14,13 @@ public interface BlockStateMeta extends ItemMeta { + */ + boolean hasBlockState(); + ++ // Paper start - add method to clear block state ++ /** ++ * Clears the block state currently attached to this item. ++ */ ++ void clearBlockState(); ++ // Paper end - add method to clear block state ++ + /** + * Returns the currently attached block state for this + * item or creates a new one if one doesn't exist. diff --git a/patches/api/0437-Expose-LootTable-of-DecoratedPot.patch b/patches/api/0437-Expose-LootTable-of-DecoratedPot.patch new file mode 100644 index 000000000000..1004281c9ae3 --- /dev/null +++ b/patches/api/0437-Expose-LootTable-of-DecoratedPot.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: FireInstall +Date: Sat, 20 Jan 2024 16:20:07 +0100 +Subject: [PATCH] Expose LootTable of DecoratedPot + + +diff --git a/src/main/java/org/bukkit/block/DecoratedPot.java b/src/main/java/org/bukkit/block/DecoratedPot.java +index a04df8105a462eac3a4a8eb04eac70fdd979d0e3..8c0e946ead8b7d9e2e6e94b0533564eb26653092 100644 +--- a/src/main/java/org/bukkit/block/DecoratedPot.java ++++ b/src/main/java/org/bukkit/block/DecoratedPot.java +@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a captured state of a decorated pot. + */ +-public interface DecoratedPot extends TileState, BlockInventoryHolder { ++public interface DecoratedPot extends TileState, BlockInventoryHolder , org.bukkit.loot.Lootable { // Paper - expose loot table + + /** + * Set the sherd on the provided side. diff --git a/patches/api/0438-Add-ShulkerDuplicateEvent.patch b/patches/api/0438-Add-ShulkerDuplicateEvent.patch new file mode 100644 index 000000000000..bed71db2554d --- /dev/null +++ b/patches/api/0438-Add-ShulkerDuplicateEvent.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chase Henderson +Date: Fri, 5 Jan 2024 03:50:10 -0500 +Subject: [PATCH] Add ShulkerDuplicateEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/ShulkerDuplicateEvent.java b/src/main/java/io/papermc/paper/event/entity/ShulkerDuplicateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d427a67a5c7e44aee78d21a7b344b8bb19235dc7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/ShulkerDuplicateEvent.java +@@ -0,0 +1,68 @@ ++package io.papermc.paper.event.entity; ++ ++import org.bukkit.entity.Shulker; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.entity.EntityEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired when a shulker duplicates itself by spawning a new shulker. ++ *

      ++ * The event is fired prior to the newly created shulker, accessible via {@link #getEntity()}, being added to the world. ++ */ ++@NullMarked ++public class ShulkerDuplicateEvent extends EntityEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Shulker parent; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public ShulkerDuplicateEvent(final Shulker child, final Shulker parent) { ++ super(child); ++ this.parent = parent; ++ } ++ ++ /** ++ * Provides the newly created shulker, which did not exist prior to the duplication. ++ * At the point of this event, said shulker is not part of the world yet. ++ * ++ * @return the newly duplicated shulker. ++ */ ++ @Override ++ public Shulker getEntity() { ++ return (Shulker) super.getEntity(); ++ } ++ ++ /** ++ * Provides the "parent" of the freshly created shulker. ++ * The parent shulker is the one that initiated the duplication. ++ * ++ * @return the previously existing shulker which duplicated. ++ */ ++ public Shulker getParent() { ++ return this.parent; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0439-Add-api-for-spawn-egg-texture-colors.patch b/patches/api/0439-Add-api-for-spawn-egg-texture-colors.patch new file mode 100644 index 000000000000..cce28b1bfae7 --- /dev/null +++ b/patches/api/0439-Add-api-for-spawn-egg-texture-colors.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Luis +Date: Thu, 11 Jan 2024 19:58:17 +0100 +Subject: [PATCH] Add api for spawn egg texture colors + + +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 8e0877321edb26e1dbdb3570a62814d06c0616af..ffe382002c66d7d3fc539c3269261ca1fab4aa2a 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -258,4 +258,17 @@ public interface UnsafeValues { + // Paper end - namespaced key biome methods + + String getStatisticCriteriaKey(@NotNull org.bukkit.Statistic statistic); // Paper - fix custom stats criteria creation ++ ++ // Paper start - spawn egg color visibility ++ /** ++ * Obtains the underlying color informating for a spawn egg of a given ++ * entity type, or null if the entity passed does not have a spawn egg. ++ * Spawn eggs have two colors - the background layer (0), and the ++ * foreground layer (1) ++ * @param entityType The entity type to get the color for ++ * @param layer The texture layer to get a color for ++ * @return The color of the layer for the entity's spawn egg ++ */ ++ @Nullable org.bukkit.Color getSpawnEggLayerColor(org.bukkit.entity.EntityType entityType, int layer); ++ // Paper end - spawn egg color visibility + } diff --git a/patches/api/0440-Add-Lifecycle-Event-system.patch b/patches/api/0440-Add-Lifecycle-Event-system.patch new file mode 100644 index 000000000000..60bb62f8ce7a --- /dev/null +++ b/patches/api/0440-Add-Lifecycle-Event-system.patch @@ -0,0 +1,646 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Tue, 18 Jul 2023 14:47:02 -0700 +Subject: [PATCH] Add Lifecycle Event system + +This event system is separate from Bukkit's event system and is +meant for managing resources across reloads and from points in the +PluginBootstrap. + +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java +index 4c47414fc08e1183b1e59369bacc4d7f7042f262..577a9d5aeae55a3b8452b6d873b51b30384c1fea 100644 +--- a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java +@@ -1,5 +1,7 @@ + package io.papermc.paper.plugin.bootstrap; + ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; + import org.jetbrains.annotations.ApiStatus; + import org.jspecify.annotations.NullMarked; + +@@ -12,5 +14,13 @@ import org.jspecify.annotations.NullMarked; + @ApiStatus.Experimental + @NullMarked + @ApiStatus.NonExtendable +-public interface BootstrapContext extends PluginProviderContext { ++public interface BootstrapContext extends PluginProviderContext, LifecycleEventOwner { ++ ++ /** ++ * Get the lifecycle event manager for registering handlers ++ * for lifecycle events allowed on the {@link BootstrapContext}. ++ * ++ * @return the lifecycle event manager ++ */ ++ LifecycleEventManager getLifecycleManager(); + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0b8eafd3e79494d4a750cd9182387fbaead24011 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java +@@ -0,0 +1,17 @@ ++package io.papermc.paper.plugin.lifecycle.event; ++ ++import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * Base type for all Lifecycle Events. ++ *

      ++ * Lifecycle events are generally fired when the older ++ * event system is not available, like during early ++ * server initialization. ++ * @see LifecycleEvents ++ */ ++@ApiStatus.Experimental ++@ApiStatus.NonExtendable ++public interface LifecycleEvent { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e05cdb7ab166f92e270ea1b85e75f465878d05f2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java +@@ -0,0 +1,53 @@ ++package io.papermc.paper.plugin.lifecycle.event; ++ ++import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration; ++import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Manages a plugin's lifecycle events. Can be obtained ++ * from {@link org.bukkit.plugin.Plugin} or {@link io.papermc.paper.plugin.bootstrap.BootstrapContext}. ++ * ++ * @param the owning type, {@link org.bukkit.plugin.Plugin} or {@link io.papermc.paper.plugin.bootstrap.BootstrapContext} ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface LifecycleEventManager { ++ ++ /** ++ * Registers an event handler for a specific event type. ++ *

      ++ * This is shorthand for creating a new {@link LifecycleEventHandlerConfiguration} and ++ * just passing in the {@link LifecycleEventHandler}. ++ *

      {@code
      ++     * LifecycleEventHandler> handler = new Handler();
      ++     * manager.registerEventHandler(LifecycleEvents.COMMANDS, handler);
      ++     * }
      ++ * is equivalent to ++ *
      {@code
      ++     * LifecycleEventHandler> handler = new Handler();
      ++     * manager.registerEventHandler(LifecycleEvents.COMMANDS.newHandler(handler));
      ++     * }
      ++ * ++ * @param eventType the event type to listen to ++ * @param eventHandler the handler for that event ++ * @param the type of the event object ++ */ ++ default void registerEventHandler(final LifecycleEventType eventType, final LifecycleEventHandler eventHandler) { ++ this.registerEventHandler(eventType.newHandler(eventHandler)); ++ } ++ ++ /** ++ * Registers an event handler configuration. ++ *

      ++ * Configurations are created via {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. ++ * Event types may have different configurations options available on the builder-like object ++ * returned by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. ++ * ++ * @param handlerConfiguration the handler configuration to register ++ */ ++ void registerEventHandler(LifecycleEventHandlerConfiguration handlerConfiguration); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ce5891eb110464a1c0cd7416712110851d010a1b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.plugin.lifecycle.event; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Implemented by types that are considered owners ++ * of registered handlers for lifecycle events. Generally ++ * the types that implement this interface also provide ++ * a {@link LifecycleEventManager} where you can register ++ * event handlers. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface LifecycleEventOwner { ++ ++ /** ++ * Get the plugin meta for this plugin. ++ * ++ * @return the plugin meta ++ */ ++ PluginMeta getPluginMeta(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3093ef23dd92f86240854065f7a7bb6c11ecf4fe +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java +@@ -0,0 +1,19 @@ ++package io.papermc.paper.plugin.lifecycle.event.handler; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A handler for a specific event. Can be implemented ++ * in a concrete class or as a lambda. ++ * ++ * @param the event ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@FunctionalInterface ++public interface LifecycleEventHandler { ++ ++ void run(E event); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9b9f4655f222597b4e00519cfe128147bc438367 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java +@@ -0,0 +1,20 @@ ++package io.papermc.paper.plugin.lifecycle.event.handler.configuration; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Base type for constructing configured event handlers for ++ * lifecycle events. Usually created via {@link io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType#newHandler(LifecycleEventHandler)} ++ * from event types in {@link io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents} ++ * ++ * @param ++ */ ++@SuppressWarnings("unused") ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface LifecycleEventHandlerConfiguration { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a2acc6e3867d6805c68e4c630aca3d14aa958a1d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java +@@ -0,0 +1,27 @@ ++package io.papermc.paper.plugin.lifecycle.event.handler.configuration; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Handler configuration for event types that allow "monitor" handlers. ++ * ++ * @param the required owner type ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface MonitorLifecycleEventHandlerConfiguration extends LifecycleEventHandlerConfiguration { ++ ++ /** ++ * Sets this handler configuration to be considered a "monitor". ++ * These handlers will run last and should only be used by plugins ++ * to observe changes from previously run handlers. ++ * ++ * @return this configuration for chaining ++ */ ++ @Contract("-> this") ++ MonitorLifecycleEventHandlerConfiguration monitor(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..100e5d169f1f644e54a042c697649f08fff1e6de +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.plugin.lifecycle.event.handler.configuration; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Handler configuration that allows both "monitor" and prioritized handlers. ++ * The default priority is 0. ++ * ++ * @param the required owner type ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface PrioritizedLifecycleEventHandlerConfiguration extends LifecycleEventHandlerConfiguration { ++ ++ /** ++ * Sets the priority for this handler. Resets ++ * all previous calls to {@link #monitor()}. A ++ * lower numeric value correlates to the handler ++ * being run earlier. ++ * ++ * @param priority the numerical priority ++ * @return this configuration for chaining ++ */ ++ @Contract("_ -> this") ++ PrioritizedLifecycleEventHandlerConfiguration priority(int priority); ++ ++ /** ++ * Sets this handler configuration to be considered a "monitor". ++ * These handlers will run last and should only be used by plugins ++ * to observe any changes from previously ran handlers. ++ * ++ * @return this configuration for chaining ++ */ ++ @Contract("-> this") ++ PrioritizedLifecycleEventHandlerConfiguration monitor(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fd9c3605a8f5e6bdd31e42f18a45154d4074eb67 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java +@@ -0,0 +1,12 @@ ++package io.papermc.paper.plugin.lifecycle.event.registrar; ++ ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * To be implemented by types that provide ways to register types ++ * either on server start or during a reload ++ */ ++@ApiStatus.Experimental ++@ApiStatus.NonExtendable ++public interface Registrar { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7dca6be092a8b5deca9c45b152a96ffe72fe2533 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java +@@ -0,0 +1,28 @@ ++package io.papermc.paper.plugin.lifecycle.event.registrar; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A lifecycle event that exposes a {@link Registrar} of some kind ++ * to allow management of various things. Look at implementations of ++ * {@link Registrar} for an idea of what uses this event. ++ * ++ * @param registrar type ++ * @see ReloadableRegistrarEvent ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface RegistrarEvent extends LifecycleEvent { ++ ++ /** ++ * Get the registrar related to this event. ++ * ++ * @return the registrar ++ */ ++ @Contract(pure = true) ++ R registrar(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9bce1c13c8092238939fbbec6b499d1ca85e5b89 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java +@@ -0,0 +1,39 @@ ++package io.papermc.paper.plugin.lifecycle.event.registrar; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A lifecycle event that exposes a {@link Registrar} that is ++ * reloadable. ++ * ++ * @param the registrar type ++ * @see RegistrarEvent ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface ReloadableRegistrarEvent extends RegistrarEvent { ++ ++ /** ++ * Get the cause of this reload. ++ * ++ * @return the cause ++ */ ++ @Contract(pure = true) ++ Cause cause(); ++ ++ @ApiStatus.Experimental ++ enum Cause { ++ /** ++ * The initial load of the server. ++ */ ++ INITIAL, ++ /** ++ * A reload, triggered via one of the various mechanisms like ++ * the bukkit or minecraft reload commands. ++ */ ++ RELOAD ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..75d9e20f53735ead4fa4aec478b4b72b85ca5e1e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java +@@ -0,0 +1,74 @@ ++package io.papermc.paper.plugin.lifecycle.event.types; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfiguration; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Base type for all types of lifecycle events. Differs from ++ * {@link LifecycleEvent} which is the actual event object, whereas ++ * this is an object representing the type of the event. Used ++ * to construct subtypes of {@link LifecycleEventHandlerConfiguration} for ++ * use in {@link LifecycleEventManager} ++ * ++ * @param the required owner type ++ * @param the event object type ++ * @param the configuration type ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface LifecycleEventType> { ++ ++ /** ++ * Gets the name of the lifecycle event. ++ * ++ * @return the name ++ */ ++ @Contract(pure = true) ++ String name(); ++ ++ /** ++ * Create a configuration for this event with the specified ++ * handler. ++ * ++ * @param handler the event handler ++ * @return a new configuration ++ * @see LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration) ++ */ ++ @Contract("_ -> new") ++ C newHandler(LifecycleEventHandler handler); ++ ++ /** ++ * Lifecycle event type that supports separate registration ++ * of handlers as "monitors" that are run last. Useful ++ * if a plugin wants to only observe the changes other handlers ++ * made. ++ * ++ * @param the required owner type ++ * @param the event object type ++ */ ++ @ApiStatus.Experimental ++ @ApiStatus.NonExtendable ++ interface Monitorable extends LifecycleEventType> { ++ } ++ ++ /** ++ * Lifecycle event type that supports both {@link Monitorable "monitors"} and ++ * specific numeric-based priorities. ++ * ++ * @param the required owner type ++ * @param the event object type ++ */ ++ @ApiStatus.Experimental ++ @ApiStatus.NonExtendable ++ interface Prioritizable extends LifecycleEventType> { ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e15e09c2a4d3f43db6a0159fa8af6179362ea8d6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper.plugin.lifecycle.event.types; ++ ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import java.util.Optional; ++import java.util.ServiceLoader; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++interface LifecycleEventTypeProvider { ++ ++ Optional INSTANCE = ServiceLoader.load(LifecycleEventTypeProvider.class) ++ .findFirst(); ++ ++ static LifecycleEventTypeProvider provider() { ++ return INSTANCE.orElseThrow(); ++ } ++ ++ LifecycleEventType.Monitorable monitor(String name, Class ownerType); ++ ++ LifecycleEventType.Prioritizable prioritized(String name, Class ownerType); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f70814de0d6c40b2c1c9921b8abdd1162e1d3995 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java +@@ -0,0 +1,54 @@ ++package io.papermc.paper.plugin.lifecycle.event.types; ++ ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; ++import org.bukkit.plugin.Plugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Holds various types of lifecycle events for ++ * use when creating event handler configurations ++ * in {@link LifecycleEventManager}. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public final class LifecycleEvents { ++ ++ // ++ @ApiStatus.Internal ++ static LifecycleEventType.Monitorable plugin(final String name) { ++ return monitor(name, Plugin.class); ++ } ++ ++ @ApiStatus.Internal ++ static LifecycleEventType.Prioritizable pluginPrioritized(final String name) { ++ return prioritized(name, Plugin.class); ++ } ++ ++ @ApiStatus.Internal ++ static LifecycleEventType.Monitorable bootstrap(final String name) { ++ return monitor(name, BootstrapContext.class); ++ } ++ ++ @ApiStatus.Internal ++ static LifecycleEventType.Prioritizable bootstrapPrioritized(final String name) { ++ return prioritized(name, BootstrapContext.class); ++ } ++ ++ @ApiStatus.Internal ++ static LifecycleEventType.Monitorable monitor(final String name, final Class ownerType) { ++ return LifecycleEventTypeProvider.provider().monitor(name, ownerType); ++ } ++ ++ @ApiStatus.Internal ++ static LifecycleEventType.Prioritizable prioritized(final String name, final Class ownerType) { ++ return LifecycleEventTypeProvider.provider().prioritized(name, ownerType); ++ } ++ // ++ ++ private LifecycleEvents() { ++ } ++} +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index ffe382002c66d7d3fc539c3269261ca1fab4aa2a..159e96b1eedb0c97b624c338fefa1783336483e3 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -271,4 +271,12 @@ public interface UnsafeValues { + */ + @Nullable org.bukkit.Color getSpawnEggLayerColor(org.bukkit.entity.EntityType entityType, int layer); + // Paper end - spawn egg color visibility ++ ++ // Paper start - lifecycle event API ++ /** ++ * @hidden ++ */ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck); ++ // Paper end - lifecycle event API + } +diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java +index 46fc37a36403c8fbc4c0c9f863d4d57eb3896bd4..0ff8b53f900092dc419d61a8ede0a7cd72a2e1e1 100644 +--- a/src/main/java/org/bukkit/plugin/Plugin.java ++++ b/src/main/java/org/bukkit/plugin/Plugin.java +@@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; + *

      + * The use of {@link PluginBase} is recommended for actual Implementation + */ +-public interface Plugin extends TabExecutor { ++public interface Plugin extends TabExecutor, io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner { // Paper + /** + * Returns the folder that the plugin data files are located in. The + * folder may not yet exist. +@@ -224,4 +224,14 @@ public interface Plugin extends TabExecutor { + */ + @NotNull + public String getName(); ++ ++ // Paper start - lifecycle events ++ /** ++ * Get the lifecycle event manager for registering handlers ++ * for lifecycle events allowed on the {@link Plugin}. ++ * ++ * @return the lifecycle event manager ++ */ ++ io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager getLifecycleManager(); ++ // Paper end - lifecycle events + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index 2d64fc065d53dcd8c01d05215c3e63aaf4428177..e0203f199700c397961a0667a79792497da7f796 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -48,6 +48,11 @@ public abstract class JavaPlugin extends PluginBase { + private FileConfiguration newConfig = null; + private File configFile = null; + private Logger logger = null; // Paper - PluginLogger -> Logger ++ // Paper start - lifecycle events ++ @SuppressWarnings("deprecation") ++ private final io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager lifecycleEventManager = org.bukkit.Bukkit.getUnsafe().createPluginLifecycleEventManager(this, () -> this.allowsLifecycleRegistration); ++ private boolean allowsLifecycleRegistration = true; ++ // Paper end + + public JavaPlugin() { + // Paper start +@@ -279,7 +284,9 @@ public abstract class JavaPlugin extends PluginBase { + isEnabled = enabled; + + if (isEnabled) { ++ try { // Paper - lifecycle events + onEnable(); ++ } finally { this.allowsLifecycleRegistration = false; } // Paper - lifecycle events + } else { + onDisable(); + } +@@ -457,4 +464,11 @@ public abstract class JavaPlugin extends PluginBase { + } + return plugin; + } ++ ++ // Paper start - lifecycle events ++ @Override ++ public final io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager getLifecycleManager() { ++ return this.lifecycleEventManager; ++ } ++ // Paper end - lifecycle events + } +diff --git a/src/test/java/org/bukkit/plugin/TestPlugin.java b/src/test/java/org/bukkit/plugin/TestPlugin.java +index 43b58e920e739bb949ac0673e9ef73ba7b500dc9..affe88cf8e98a787e197936f5fc443464a2343c6 100644 +--- a/src/test/java/org/bukkit/plugin/TestPlugin.java ++++ b/src/test/java/org/bukkit/plugin/TestPlugin.java +@@ -133,4 +133,11 @@ public class TestPlugin extends PluginBase { + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + throw new UnsupportedOperationException("Not supported."); + } ++ ++ // Paper start - lifecycle events ++ @Override ++ public io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager getLifecycleManager() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ // Paper end - lifecycle events + } diff --git a/patches/api/0441-ItemStack-Tooltip-API.patch b/patches/api/0441-ItemStack-Tooltip-API.patch new file mode 100644 index 000000000000..d7749819046b --- /dev/null +++ b/patches/api/0441-ItemStack-Tooltip-API.patch @@ -0,0 +1,148 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yannick Lamprecht +Date: Mon, 22 Jan 2024 13:27:18 +0100 +Subject: [PATCH] ItemStack Tooltip API + + +diff --git a/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContext.java b/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7e16f2645e956cbac8d0fc75ba8209f67fd1835c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContext.java +@@ -0,0 +1,76 @@ ++package io.papermc.paper.inventory.tooltip; ++ ++import org.bukkit.entity.Player; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Context for computing itemstack tooltips via ++ * {@link org.bukkit.inventory.ItemStack#computeTooltipLines(TooltipContext, Player)} ++ */ ++@NullMarked ++public interface TooltipContext { ++ ++ /** ++ * Creates a new context with the given advanced and creative ++ * mode settings. ++ * ++ * @param advanced whether the context is for advanced tooltips ++ * @param creative whether the context is for the creative inventory ++ * @return a new context ++ */ ++ @Contract("_, _ -> new") ++ static TooltipContext create(final boolean advanced, final boolean creative) { ++ return new TooltipContextImpl(advanced, creative); ++ } ++ ++ /** ++ * Creates a new context that is neither advanced nor creative. ++ * ++ * @return a new context ++ */ ++ @Contract("-> new") ++ static TooltipContext create() { ++ return new TooltipContextImpl(false, false); ++ } ++ ++ /** ++ * Returns whether the context is for advanced ++ * tooltips. ++ *

      ++ * Advanced tooltips are shown by default ++ * when a player has {@code F3+H} enabled. ++ * ++ * @return true if for advanced tooltips ++ */ ++ boolean isAdvanced(); ++ ++ /** ++ * Returns whether the context is for the creative ++ * mode inventory. ++ *

      ++ * Creative tooltips are shown by default when a player is ++ * in the creative inventory. ++ * ++ * @return true if for creative mode inventory ++ */ ++ boolean isCreative(); ++ ++ /** ++ * Returns a new context with {@link #isAdvanced()} ++ * set to true. ++ * ++ * @return a new context ++ */ ++ @Contract("-> new") ++ TooltipContext asAdvanced(); ++ ++ /** ++ * Returns a new context with {@link #isCreative()} ++ * set to true. ++ * ++ * @return a new context ++ */ ++ @Contract("-> new") ++ TooltipContext asCreative(); ++} +diff --git a/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContextImpl.java b/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContextImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a649b90dfac6000c01579a48234a11383c731439 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/inventory/tooltip/TooltipContextImpl.java +@@ -0,0 +1,17 @@ ++package io.papermc.paper.inventory.tooltip; ++ ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++record TooltipContextImpl(boolean isAdvanced, boolean isCreative) implements TooltipContext { ++ ++ @Override ++ public TooltipContext asCreative() { ++ return new TooltipContextImpl(this.isAdvanced, true); ++ } ++ ++ @Override ++ public TooltipContext asAdvanced() { ++ return new TooltipContextImpl(true, this.isCreative); ++ } ++} +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 159e96b1eedb0c97b624c338fefa1783336483e3..ff155bd22a6ea7f59dbf91c9280a653917b5010f 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -279,4 +279,6 @@ public interface UnsafeValues { + @org.jetbrains.annotations.ApiStatus.Internal + io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck); + // Paper end - lifecycle event API ++ ++ @NotNull java.util.List computeTooltipLines(@NotNull ItemStack itemStack, @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, @Nullable org.bukkit.entity.Player player); // Paper - expose itemstack tooltip lines + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index c3ae09dc66119cb2873201fb2975ad5e0f8237d2..0e6103628673130139363b53d23d3432deff5c50 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -1124,4 +1124,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + return type.isAir() || amount <= 0; + } + // Paper end ++ // Paper start - expose itemstack tooltip lines ++ /** ++ * Computes the tooltip lines for this stack. ++ *

      ++ * Disclaimer: ++ * Tooltip contents are not guaranteed to be consistent across different ++ * Minecraft versions. ++ * ++ * @param tooltipContext the tooltip context ++ * @param player a player for player-specific tooltip lines ++ * @return an immutable list of components (can be empty) ++ */ ++ @SuppressWarnings("deprecation") // abusing unsafe as a bridge ++ public java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List computeTooltipLines(final @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, final @Nullable org.bukkit.entity.Player player) { ++ return Bukkit.getUnsafe().computeTooltipLines(this, tooltipContext, player); ++ } ++ // Paper end - expose itemstack tooltip lines + } diff --git a/patches/api/0442-Add-getChunkSnapshot-includeLightData-parameter.patch b/patches/api/0442-Add-getChunkSnapshot-includeLightData-parameter.patch new file mode 100644 index 000000000000..9b950f949339 --- /dev/null +++ b/patches/api/0442-Add-getChunkSnapshot-includeLightData-parameter.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Warrior <50800980+Warriorrrr@users.noreply.github.com> +Date: Sat, 10 Feb 2024 10:05:59 +0100 +Subject: [PATCH] Add getChunkSnapshot includeLightData parameter + + +diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java +index c2eb2edd87b4087bfcdffd98f0f8904fbfd4e657..bc8b5bc17706250b8535b1b309134843d2ce2bb1 100644 +--- a/src/main/java/org/bukkit/Chunk.java ++++ b/src/main/java/org/bukkit/Chunk.java +@@ -103,6 +103,23 @@ public interface Chunk extends PersistentDataHolder { + @NotNull + ChunkSnapshot getChunkSnapshot(boolean includeMaxblocky, boolean includeBiome, boolean includeBiomeTempRain); + ++ // Paper start - Add getChunkSnapshot includeLightData parameter ++ /** ++ * Capture thread-safe read-only snapshot of chunk data ++ * ++ * @param includeMaxblocky if true, snapshot includes per-coordinate ++ * maximum Y values ++ * @param includeBiome if true, snapshot includes per-coordinate biome ++ * type ++ * @param includeBiomeTempRain if true, snapshot includes per-coordinate ++ * raw biome temperature and rainfall ++ * @param includeLightData Whether to include per-coordinate light emitted by blocks and sky light data ++ * @return ChunkSnapshot ++ */ ++ @NotNull ++ ChunkSnapshot getChunkSnapshot(boolean includeMaxblocky, boolean includeBiome, boolean includeBiomeTempRain, boolean includeLightData); ++ // Paper end - Add getChunkSnapshot includeLightData parameter ++ + /** + * Checks if entities in this chunk are loaded. + * diff --git a/patches/api/0443-Add-FluidState-API.patch b/patches/api/0443-Add-FluidState-API.patch new file mode 100644 index 000000000000..8f786918cbb7 --- /dev/null +++ b/patches/api/0443-Add-FluidState-API.patch @@ -0,0 +1,165 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vicisacat +Date: Fri, 17 Nov 2023 20:21:47 +0100 +Subject: [PATCH] Add FluidState API + + +diff --git a/src/main/java/io/papermc/paper/block/fluid/FluidData.java b/src/main/java/io/papermc/paper/block/fluid/FluidData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0750219fc68261e5c396636967e0b633ae17b72e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/block/fluid/FluidData.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.block.fluid; ++ ++import org.bukkit.Fluid; ++import org.bukkit.Location; ++import org.bukkit.util.Vector; ++import org.jetbrains.annotations.Range; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A representation of a fluid in a specific state of data. ++ * This type is not linked to a specific location and hence mostly resembles a {@link org.bukkit.block.data.BlockData}. ++ */ ++@NullMarked ++public interface FluidData extends Cloneable { ++ ++ /** ++ * Gets the fluid type of this fluid data. ++ * ++ * @return the fluid type ++ */ ++ Fluid getFluidType(); ++ ++ /** ++ * Returns a copy of this FluidData. ++ * ++ * @return a copy of the fluid data ++ */ ++ FluidData clone(); ++ ++ /** ++ * Computes the direction of the flow of the liquid at the given location as a vector. ++ *

      ++ * This method requires the passed location's chunk to be loaded. ++ * If said chunk is not loaded when this method is called, the chunk will first be loaded prior to the computation ++ * which leads to a potentially slow sync chunk load. ++ * ++ * @param location - the location to check the liquid flow ++ * @return the flow direction vector at the given location ++ */ ++ Vector computeFlowDirection(Location location); ++ ++ /** ++ * Returns the level of liquid this fluid data holds. ++ * ++ * @return the amount as an integer, between 0 and 8 ++ */ ++ @Range(from = 0, to = 8) ++ int getLevel(); ++ ++ /** ++ * Computes the height of the fluid in the world. ++ *

      ++ * This method requires the passed location's chunk to be loaded. ++ * If said chunk is not loaded when this method is called, the chunk will first be loaded prior to the computation ++ * which leads to a potentially slow sync chunk load. ++ * ++ * @param location the location at which to check the high of this fluid data. ++ * @return the height as a float value ++ */ ++ @Range(from = 0, to = 1) ++ float computeHeight(Location location); ++ ++ /** ++ * Returns whether this fluid is a source block ++ * ++ * @return true if the fluid is a source block, false otherwise ++ */ ++ boolean isSource(); ++} +diff --git a/src/main/java/io/papermc/paper/block/fluid/type/FallingFluidData.java b/src/main/java/io/papermc/paper/block/fluid/type/FallingFluidData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7bd9f28ba646f09080b5c29b9d3be5af676c912e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/block/fluid/type/FallingFluidData.java +@@ -0,0 +1,16 @@ ++package io.papermc.paper.block.fluid.type; ++ ++import io.papermc.paper.block.fluid.FluidData; ++ ++/** ++ * A specific subtype of {@link FluidData} that is returned by the API for fluid data of potentially falling fluids. ++ */ ++public interface FallingFluidData extends FluidData { ++ ++ /** ++ * Get if this liquid is falling. ++ * ++ * @return true if falling ++ */ ++ boolean isFalling(); ++} +diff --git a/src/main/java/io/papermc/paper/block/fluid/type/FlowingFluidData.java b/src/main/java/io/papermc/paper/block/fluid/type/FlowingFluidData.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fbccdffe8d73e517204081c73bca9154f8c7d69f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/block/fluid/type/FlowingFluidData.java +@@ -0,0 +1,10 @@ ++package io.papermc.paper.block.fluid.type; ++ ++import io.papermc.paper.block.fluid.FluidData; ++ ++/** ++ * A specific subtype of {@link FluidData} that is returned by the API for fluid data of potentially falling fluids. ++ */ ++public interface FlowingFluidData extends FallingFluidData { ++ ++} +diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bukkit/RegionAccessor.java +index 43dd6c59cceba12f27e6b265acc3ad97eea37abd..eb33e8e671972aa308ad75a7ce9aa9ac526f470f 100644 +--- a/src/main/java/org/bukkit/RegionAccessor.java ++++ b/src/main/java/org/bukkit/RegionAccessor.java +@@ -102,6 +102,41 @@ public interface RegionAccessor extends Keyed { // Paper + @NotNull + BlockState getBlockState(int x, int y, int z); + ++ // Paper start - FluidState API ++ /** ++ * Gets the {@link io.papermc.paper.block.fluid.FluidData} at the specified position. ++ * ++ * @param x The x-coordinate of the position ++ * @param y The y-coordinate of the position ++ * @param z The z-coordinate of the position ++ * @return The {@link io.papermc.paper.block.fluid.FluidData} at the specified position ++ */ ++ @NotNull ++ io.papermc.paper.block.fluid.FluidData getFluidData(int x, int y, int z); ++ ++ /** ++ * Gets the {@link io.papermc.paper.block.fluid.FluidData} at the given position ++ * ++ * @param position The position of the fluid ++ * @return The fluid data at the given position ++ */ ++ @NotNull ++ default io.papermc.paper.block.fluid.FluidData getFluidData(@NotNull io.papermc.paper.math.Position position) { ++ return getFluidData(position.blockX(), position.blockY(), position.blockZ()); ++ } ++ ++ /** ++ * Gets the {@link io.papermc.paper.block.fluid.FluidData} at the given position ++ * ++ * @param location The location of the fluid ++ * @return The fluid data at the given position ++ */ ++ @NotNull ++ default io.papermc.paper.block.fluid.FluidData getFluidData(@NotNull Location location) { ++ return getFluidData(location.blockX(), location.blockY(), location.blockZ()); ++ } ++ // Paper end ++ + /** + * Gets the {@link BlockData} at the given {@link Location}. + * diff --git a/patches/api/0444-add-number-format-api.patch b/patches/api/0444-add-number-format-api.patch new file mode 100644 index 000000000000..ac3ce0b6babe --- /dev/null +++ b/patches/api/0444-add-number-format-api.patch @@ -0,0 +1,234 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Mayr +Date: Sat, 16 Dec 2023 10:40:29 +0100 +Subject: [PATCH] add number format api + +Signed-off-by: David Mayr + +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/BlankFormatImpl.java b/src/main/java/io/papermc/paper/scoreboard/numbers/BlankFormatImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..486da6ebe0137bb3280e8b33c8e35e309507f118 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/BlankFormatImpl.java +@@ -0,0 +1,5 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++record BlankFormatImpl() implements NumberFormat { ++ public static final BlankFormatImpl INSTANCE = new BlankFormatImpl(); ++} +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormat.java b/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormat.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3ef4595b692a13566c5c738050b83b0462094e9b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormat.java +@@ -0,0 +1,20 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.ComponentLike; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A scoreboard number format that replaces the score number with a chat component. ++ */ ++@NullMarked ++public interface FixedFormat extends NumberFormat, ComponentLike { ++ ++ /** ++ * The component shown instead of the number for a score ++ * ++ * @return the chat component ++ */ ++ Component component(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormatImpl.java b/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormatImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..be47bf438805f9ab84b241e564281ea9c287aa6e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/FixedFormatImpl.java +@@ -0,0 +1,13 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++import net.kyori.adventure.text.Component; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++record FixedFormatImpl(Component component) implements FixedFormat { ++ ++ @Override ++ public Component asComponent() { ++ return this.component(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/NumberFormat.java b/src/main/java/io/papermc/paper/scoreboard/numbers/NumberFormat.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7c093e4e9a2a67021da9025631a3c6fa7ac3ef35 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/NumberFormat.java +@@ -0,0 +1,61 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++import net.kyori.adventure.text.ComponentLike; ++import net.kyori.adventure.text.format.Style; ++import net.kyori.adventure.text.format.StyleBuilderApplicable; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Describes a scoreboard number format that applies custom formatting to scoreboard scores. ++ */ ++@NullMarked ++public interface NumberFormat { ++ ++ /** ++ * Creates a blank scoreboard number format that removes the score number entirely. ++ * ++ * @return a blank number format ++ */ ++ static NumberFormat blank() { ++ return BlankFormatImpl.INSTANCE; ++ } ++ ++ /** ++ * Gets an un-styled number format. ++ * ++ * @return an un-styled number format ++ */ ++ static StyledFormat noStyle() { ++ return StyledFormatImpl.NO_STYLE; ++ } ++ ++ /** ++ * Creates a scoreboard number format that applies a custom formatting to the score number. ++ * ++ * @param style the style to apply on the number ++ * @return a styled number format ++ */ ++ static StyledFormat styled(final Style style) { ++ return new StyledFormatImpl(style); ++ } ++ ++ /** ++ * Creates a scoreboard number format that applies a custom formatting to the score number. ++ * ++ * @param styleBuilderApplicables the style to apply on the number ++ * @return a styled number format ++ */ ++ static StyledFormat styled(final StyleBuilderApplicable... styleBuilderApplicables) { ++ return styled(Style.style(styleBuilderApplicables)); ++ } ++ ++ /** ++ * Creates a scoreboard number format that replaces the score number with a chat component. ++ * ++ * @param component the component to replace the number with ++ * @return a fixed number format ++ */ ++ static FixedFormat fixed(final ComponentLike component) { ++ return new FixedFormatImpl(component.asComponent()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormat.java b/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormat.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cfb14bb1b338727a5d9eeaa7a73c40540b04dbed +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormat.java +@@ -0,0 +1,20 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++import net.kyori.adventure.text.format.Style; ++import net.kyori.adventure.text.format.StyleBuilderApplicable; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A scoreboard number format that applies a custom formatting to the score number. ++ */ ++@NullMarked ++public interface StyledFormat extends NumberFormat, StyleBuilderApplicable { ++ ++ /** ++ * The style that is being applied to the number in the score ++ * ++ * @return the style to apply ++ */ ++ Style style(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormatImpl.java b/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormatImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e288beb1596f2d4e7e602364955da4e8bc0de21c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/scoreboard/numbers/StyledFormatImpl.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.scoreboard.numbers; ++ ++import net.kyori.adventure.text.format.Style; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++record StyledFormatImpl(Style style) implements StyledFormat { ++ static final StyledFormat NO_STYLE = new StyledFormatImpl(Style.empty()); ++ ++ @Override ++ public void styleApply(final Style.Builder style) { ++ style.merge(this.style); ++ } ++} +diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java +index d8a249bb2dd8ab96962897c2a52f40ea288f7bd6..d1016ee4282321d99734a251edfd93facb9b903f 100644 +--- a/src/main/java/org/bukkit/scoreboard/Objective.java ++++ b/src/main/java/org/bukkit/scoreboard/Objective.java +@@ -195,4 +195,22 @@ public interface Objective { + */ + void setAutoUpdateDisplay(boolean autoUpdateDisplay); + // Paper end - add more score API ++ ++ // Paper start - number format api ++ /** ++ * Gets the number format for this objective's scores or null if the client default is used. ++ * ++ * @return this objective's number format, or null if the client default is used ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ @Nullable io.papermc.paper.scoreboard.numbers.NumberFormat numberFormat(); ++ ++ /** ++ * Sets the number format for this objective's scores. ++ * ++ * @param format the number format to set, pass null to reset format to default ++ * @throws IllegalStateException if this objective has been unregistered ++ */ ++ void numberFormat(@Nullable io.papermc.paper.scoreboard.numbers.NumberFormat format); ++ // Paper end - number format api + } +diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java +index a3b482e07bb3dceb9b81d66c7208556a0bedd948..3600804874843975eb12b84b71b6848c68b2a244 100644 +--- a/src/main/java/org/bukkit/scoreboard/Score.java ++++ b/src/main/java/org/bukkit/scoreboard/Score.java +@@ -129,4 +129,26 @@ public interface Score { + */ + void customName(net.kyori.adventure.text.@Nullable Component customName); + // Paper end - add more score API ++ ++ // Paper start - number format api ++ /** ++ * Gets the number format for this score or null if the score has not been set yet ++ * or the objective's default is being used. ++ * ++ * @return this score's number format, or null if the objective's default is used or the score doesn't exist ++ * @throws IllegalStateException if the associated objective has been ++ * unregistered ++ */ ++ @Nullable io.papermc.paper.scoreboard.numbers.NumberFormat numberFormat(); ++ ++ /** ++ * Sets the number format for this score. If this score has not been set yet {@link #isScoreSet()}, it will be created ++ * ++ * @param format the number format to set, pass null to reset format to default ++ * @throws IllegalStateException if the associated objective has been ++ * unregistered ++ */ ++ void numberFormat(@Nullable io.papermc.paper.scoreboard.numbers.NumberFormat format); ++ // Paper end - number format api ++ + } diff --git a/patches/api/0445-improve-BanList-types.patch b/patches/api/0445-improve-BanList-types.patch new file mode 100644 index 000000000000..70d8b83c87ff --- /dev/null +++ b/patches/api/0445-improve-BanList-types.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Yannick Lamprecht +Date: Sat, 10 Feb 2024 20:49:47 +0100 +Subject: [PATCH] improve BanList types + + +diff --git a/src/main/java/io/papermc/paper/ban/BanListType.java b/src/main/java/io/papermc/paper/ban/BanListType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fdd5cfdc8c2c2ba97a3ac3db57be5a0e13dc327d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/ban/BanListType.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.ban; ++ ++import org.bukkit.BanList; ++import org.bukkit.ban.IpBanList; ++import org.bukkit.ban.ProfileBanList; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents a ban-type that a {@link BanList} may track. ++ * It enforces the correct return value at compile time. ++ */ ++@NullMarked ++public interface BanListType { ++ ++ /** ++ * Banned IP addresses ++ */ ++ BanListType IP = new BanListTypeImpl<>(IpBanList.class); ++ /** ++ * Banned player profiles ++ */ ++ BanListType PROFILE = new BanListTypeImpl<>(ProfileBanList.class); ++ ++ /** ++ * Returns the type class of the ban list used generically ++ * ++ * @return the type class ++ */ ++ Class typeClass(); ++} +diff --git a/src/main/java/io/papermc/paper/ban/BanListTypeImpl.java b/src/main/java/io/papermc/paper/ban/BanListTypeImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..26d4df3cbf8d31790218095bb7fb1a1762e2b322 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/ban/BanListTypeImpl.java +@@ -0,0 +1,9 @@ ++package io.papermc.paper.ban; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++record BanListTypeImpl(Class typeClass) implements BanListType { ++} +diff --git a/src/main/java/org/bukkit/BanList.java b/src/main/java/org/bukkit/BanList.java +index 60aea29d51a8ad499401f94a7c326d9b415b6a3a..bd06fe7cb5bf3268feae52d37357dca82206b991 100644 +--- a/src/main/java/org/bukkit/BanList.java ++++ b/src/main/java/org/bukkit/BanList.java +@@ -16,7 +16,9 @@ public interface BanList { + + /** + * Represents a ban-type that a {@link BanList} may track. ++ * @deprecated use {@link io.papermc.paper.ban.BanListType} to enforce the correct return value at compile time. + */ ++ @Deprecated(since = "1.20.4") // Paper - BanList Type Improvements + public enum Type { + /** + * Banned player names +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index c3c76dd82b209f6720afc51622aeb3fd92f1c0c2..8ab94f8189ebd9d4158231871abdebec399deb2c 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1663,11 +1663,27 @@ public final class Bukkit { + * @param The ban target + * + * @return a ban list of the specified type ++ * @deprecated use {@link #getBanList(io.papermc.paper.ban.BanListType)} to enforce the correct return value at compile time. + */ + @NotNull ++ @Deprecated(since = "1.20.4") // Paper - add BanListType (which has a generic) + public static > T getBanList(@NotNull BanList.Type type) { + return server.getBanList(type); + } ++ // Paper start - add BanListType (which has a generic) ++ /** ++ * Gets a ban list for the supplied type. ++ * ++ * @param type the type of list to fetch, cannot be null ++ * @param The ban target ++ * ++ * @return a ban list of the specified type ++ */ ++ @NotNull ++ public static , E> B getBanList(final io.papermc.paper.ban.@NotNull BanListType type) { ++ return server.getBanList(type); ++ } ++ // Paper end - add BanListType (which has a generic) + + /** + * Gets a set containing all player operators. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 1b968953fdf470bff32122bd06c4f83f27b97383..e187bb03006e84f08ca09c33ea182a76ae2d9d39 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1425,10 +1425,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @param The ban target + * + * @return a ban list of the specified type ++ * @deprecated use {@link #getBanList(io.papermc.paper.ban.BanListType)} to enforce the correct return value at compile time. + */ ++ @Deprecated // Paper - add BanListType (which has a generic) + @NotNull + public > T getBanList(@NotNull BanList.Type type); + ++ // Paper start - add BanListType (which has a generic) ++ /** ++ * Gets a ban list for the supplied type. ++ * ++ * @param type the type of list to fetch, cannot be null ++ * @param The ban target ++ * ++ * @return a ban list of the specified type ++ */ ++ @NotNull ++ , E> B getBanList(@NotNull io.papermc.paper.ban.BanListType type); ++ // Paper end - add BanListType (which has a generic) ++ + /** + * Gets a set containing all player operators. + * diff --git a/patches/api/0446-Suspicious-Effect-Entry-API.patch b/patches/api/0446-Suspicious-Effect-Entry-API.patch new file mode 100644 index 000000000000..d591d57ce9d1 --- /dev/null +++ b/patches/api/0446-Suspicious-Effect-Entry-API.patch @@ -0,0 +1,220 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Sun, 3 Mar 2024 19:45:52 +0100 +Subject: [PATCH] Suspicious Effect Entry API + +Exposes a new suspicious effect entry type that properly represents +storable effects in the context of suspicious effects as they only +define the potion effect type and duration. + +This differentiates them from the existing PotionEffect API found in +bukkit and hence clarifies that storable values in the parts of the API +in which it replaces PotionEffect. + +Co-authored-by: Yannick Lamprecht + +diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6311ede3e3812da2ccdbcb19522facd7b2e3bd5c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java +@@ -0,0 +1,39 @@ ++package io.papermc.paper.potion; ++ ++import org.bukkit.potion.PotionEffect; ++import org.bukkit.potion.PotionEffectType; ++import org.jetbrains.annotations.Contract; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Represents a {@link PotionEffectType} paired with a duration. ++ */ ++@NullMarked ++public sealed interface SuspiciousEffectEntry permits SuspiciousEffectEntryImpl { ++ ++ /** ++ * Gets the effect type. ++ * ++ * @return effect type ++ */ ++ PotionEffectType effect(); ++ ++ /** ++ * Gets the duration for this effect instance. ++ * ++ * @return duration (in ticks) or {@link PotionEffect#INFINITE_DURATION} ++ */ ++ int duration(); ++ ++ /** ++ * Creates a new instance of SuspiciousEffectEntry. ++ * ++ * @param effectType effect type ++ * @param duration duration (in ticks) or {@link PotionEffect#INFINITE_DURATION} ++ * @return new instance of an entry ++ */ ++ @Contract(value = "_, _ -> new", pure = true) ++ static SuspiciousEffectEntry create(final PotionEffectType effectType, final int duration) { ++ return new SuspiciousEffectEntryImpl(effectType, duration); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a91d37ee450944ea779bd6b61d416467948bb55f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java +@@ -0,0 +1,10 @@ ++package io.papermc.paper.potion; ++ ++import org.bukkit.potion.PotionEffectType; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++@ApiStatus.Internal ++@NullMarked ++record SuspiciousEffectEntryImpl(PotionEffectType effect, int duration) implements SuspiciousEffectEntry { ++} +diff --git a/src/main/java/org/bukkit/entity/MushroomCow.java b/src/main/java/org/bukkit/entity/MushroomCow.java +index 86c0043ef4e1288b6fe2f68a9b6d01c3de2c3454..3677f19ef1c05b76d946b1b2b491a6c3cec76140 100644 +--- a/src/main/java/org/bukkit/entity/MushroomCow.java ++++ b/src/main/java/org/bukkit/entity/MushroomCow.java +@@ -34,14 +34,30 @@ public interface MushroomCow extends Cow, io.papermc.paper.entity.Shearable { // + * Adds a custom potion effect to be applied to the next suspicious stew + * received from milking this {@link MushroomCow}. + * ++ * @deprecated use {@link #addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry, boolean)} as PotionEffect suggests that all attributes are used. In fact, only the PotionEffectType and the duration are used. + * @param effect the potion effect to add + * @param overwrite true if any existing effect of the same type should be + * overwritten + * @return true if the effects to be applied to the suspicious stew changed + * as a result of this call + */ ++ @Deprecated(forRemoval = true, since = "1.20.2") // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta + boolean addEffectToNextStew(@NotNull PotionEffect effect, boolean overwrite); + ++ // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta ++ /** ++ * Adds a suspicious effect entry to be applied to the next suspicious stew ++ * received from milking this {@link MushroomCow}. ++ * ++ * @param suspiciousEffectEntry the suspicious effect entry to add ++ * @param overwrite true if any existing effect of the same type should be ++ * overwritten ++ * @return true if the effects to be applied to the suspicious stew changed ++ * as a result of this call ++ */ ++ boolean addEffectToNextStew(@NotNull io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite); ++ // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta ++ + /** + * Removes a custom potion effect from being applied to the next suspicious + * stew received from milking this {@link MushroomCow}. +@@ -95,4 +111,75 @@ public interface MushroomCow extends Cow, io.papermc.paper.entity.Shearable { // + */ + BROWN; + } ++ // Paper start ++ /** ++ * Gets how long the effect applied to stew ++ * from this mushroom cow is. ++ * ++ * @return duration of the effect (in ticks) ++ * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()} ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.2") ++ @org.jetbrains.annotations.Contract("-> fail") ++ default int getStewEffectDuration() { ++ throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects"); ++ } ++ ++ /** ++ * Sets how long the effect applied to stew ++ * from this mushroom cow is. ++ * ++ * @param duration duration of the effect (in ticks) ++ * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)} ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.2") ++ @org.jetbrains.annotations.Contract("_ -> fail") ++ default void setStewEffectDuration(int duration) { ++ throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects"); ++ } ++ ++ /** ++ * Gets the type of effect applied to stew ++ * from this mushroom cow is. ++ * ++ * @return effect type, or null if an effect is currently not set ++ * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()} ++ * @throws UnsupportedOperationException ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.2") ++ @org.jetbrains.annotations.Contract("-> fail") ++ default org.bukkit.potion.PotionEffectType getStewEffectType() { ++ throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects"); ++ } ++ ++ /** ++ * Sets the type of effect applied to stew ++ * from this mushroom cow is. ++ * ++ * @param type new effect type ++ * or null if this cow does not give effects ++ * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)} ++ * @throws UnsupportedOperationException ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.2") ++ @org.jetbrains.annotations.Contract("_ -> fail") ++ default void setStewEffect(@org.jetbrains.annotations.Nullable org.bukkit.potion.PotionEffectType type) { ++ throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects"); ++ } ++ ++ /** ++ * Returns an immutable collection of the effects applied to stew ++ * items for this mushroom cow. ++ * ++ * @return immutable effect entry collection ++ */ ++ java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List getStewEffects(); ++ ++ /** ++ * Sets effects applied to stew items for this mushroom cow. ++ * ++ * @param effects effect entry list ++ */ ++ void setStewEffects(java.util.@NotNull List effects); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java b/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java +index c2f4282c188e7d8041459cb3acaad674443ba147..c5bfc062fcca56495f44039d83356fc1fd7568d0 100644 +--- a/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java +@@ -32,13 +32,28 @@ public interface SuspiciousStewMeta extends ItemMeta { + /** + * Adds a custom potion effect to this suspicious stew. + * ++ * @deprecated use {@link #addCustomEffect(io.papermc.paper.potion.SuspiciousEffectEntry, boolean)} as PotionEffect suggests that all attributes are used. In fact, only the PotionEffectType and the duration are used. + * @param effect the potion effect to add + * @param overwrite true if any existing effect of the same type should be + * overwritten + * @return true if the suspicious stew meta changed as a result of this call + */ ++ @Deprecated // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta + boolean addCustomEffect(@NotNull PotionEffect effect, boolean overwrite); + ++ // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta ++ /** ++ * Adds a custom potion effect to this suspicious stew. ++ * ++ * @param suspiciousEffectEntry the suspicious effect entry to add ++ * @param overwrite true if any existing effect of the same type should be ++ * overwritten ++ * @return true if the suspicious stew meta changed as a result of this call ++ * as a result of this call ++ */ ++ boolean addCustomEffect(@NotNull io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite); ++ // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta ++ + /** + * Removes a custom potion effect from this suspicious stew. + * diff --git a/patches/api/0447-Fix-DamageSource-API.patch b/patches/api/0447-Fix-DamageSource-API.patch new file mode 100644 index 000000000000..eec753daa546 --- /dev/null +++ b/patches/api/0447-Fix-DamageSource-API.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 16 Mar 2024 11:21:14 -0700 +Subject: [PATCH] Fix DamageSource API + + +diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java +index 341f99550d077c60306e8a246a254b768ebbeb48..31a36ed3baf44c961173c6dd10d69055e3597897 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java +@@ -60,6 +60,20 @@ public class EntityDamageByEntityEvent extends EntityDamageEvent { + } + // Paper end + ++ // Paper start ++ /** ++ * {@inheritDoc} ++ *

      ++ * The {@link DamageSource#getDirectEntity()} may be different from the {@link #getDamager()} ++ * if the Minecraft damage source did not originally include an damager entity, but one was included ++ * for this event {@link #getDamager()}. ++ */ ++ @Override ++ public @NotNull DamageSource getDamageSource() { ++ return super.getDamageSource(); ++ } ++ // Paper end ++ + /** + * Returns the entity that damaged the defender. + * diff --git a/patches/api/0448-Expanded-Hopper-API.patch b/patches/api/0448-Expanded-Hopper-API.patch new file mode 100644 index 000000000000..51cb6dfee2a9 --- /dev/null +++ b/patches/api/0448-Expanded-Hopper-API.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: vicisacat +Date: Fri, 15 Mar 2024 17:35:18 +0100 +Subject: [PATCH] Expanded Hopper API + + +diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java +index 7ade312f180b7e30871d3a3240c76325cc369c26..61ea33c1f2dbb546a66f945a01feae437b1381e0 100644 +--- a/src/main/java/org/bukkit/block/Hopper.java ++++ b/src/main/java/org/bukkit/block/Hopper.java +@@ -6,4 +6,20 @@ import org.bukkit.loot.Lootable; + /** + * Represents a captured state of a hopper. + */ +-public interface Hopper extends Container, LootableBlockInventory { } // Paper ++public interface Hopper extends Container, LootableBlockInventory { // Paper ++ // Paper start - Expanded Hopper API ++ /** ++ * Sets the cooldown before the hopper transfers or sucks in another item ++ * @param cooldown the cooldown in ticks ++ * @throws IllegalArgumentException if the passed cooldown value is negative. ++ */ ++ void setTransferCooldown(@org.jetbrains.annotations.Range(from = 0, to = Integer.MAX_VALUE) int cooldown); ++ ++ /** ++ * Returns the cooldown before the hopper transfers or sucks in another item ++ * @return the cooldown in ticks ++ */ ++ int getTransferCooldown(); ++ // Paper end - Expanded Hopper API ++} ++ diff --git a/patches/api/0449-Clone-mutables-to-prevent-unexpected-issues.patch b/patches/api/0449-Clone-mutables-to-prevent-unexpected-issues.patch new file mode 100644 index 000000000000..50f9f8e25dcd --- /dev/null +++ b/patches/api/0449-Clone-mutables-to-prevent-unexpected-issues.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 16 Mar 2024 11:10:48 -0700 +Subject: [PATCH] Clone mutables to prevent unexpected issues + +There are lots of locations in the API where mutable +types are not cloned, either on return or when passed +as a parameter and assigned to a field, which can cause +unexpected behaviors. Let this be a lesson to use +immutable types for simple things Location, Vector, and +others. + +diff --git a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +index 31fd64187fc5bd50a5ba36b3b68001ce6ff2211c..f5923049bfd0478938dafa76287db76f8a4c29f9 100644 +--- a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java ++++ b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java +@@ -102,7 +102,7 @@ public class BlockCanBuildEvent extends BlockEvent { + */ + @NotNull + public BlockData getBlockData() { +- return blockData; ++ return blockData.clone(); // Paper - clone because mutation isn't used + } + + /** +diff --git a/src/main/java/org/bukkit/event/entity/EntityChangeBlockEvent.java b/src/main/java/org/bukkit/event/entity/EntityChangeBlockEvent.java +index 1a9575ad4c81aefa5ef0b927f6ac8f7064b55c49..24e1a49e48dd8f9eb2515b2ffe472a0c4d2bc09b 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityChangeBlockEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityChangeBlockEvent.java +@@ -61,7 +61,7 @@ public class EntityChangeBlockEvent extends EntityEvent implements Cancellable { + */ + @NotNull + public BlockData getBlockData() { +- return to; ++ return to.clone(); // Paper - clone because mutation isn't used + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +index 50161d313cfcc9e61441589685c3d0e1f057dd86..e468e55d426b8f81f87c0a08451d02b3866c226f 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityExplodeEvent.java +@@ -72,7 +72,7 @@ public class EntityExplodeEvent extends EntityEvent implements Cancellable { + */ + @NotNull + public Location getLocation() { +- return location; ++ return location.clone(); // Paper - clone to avoid changes + } + + /** +diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +index d3724db0a5a67cde15b05fecd32b2ca370cca998..8b2caf665b9e829ceefc89bf41b192f53f3d5773 100644 +--- a/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java ++++ b/src/main/java/org/bukkit/event/entity/EntityPortalEnterEvent.java +@@ -35,7 +35,7 @@ public class EntityPortalEnterEvent extends EntityEvent implements org.bukkit.ev + */ + @NotNull + public Location getLocation() { +- return location; ++ return location.clone(); // Paper - clone to avoid changes + } + + // Paper start +diff --git a/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java b/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java +index 6fc66197eb2c5d59c70d8d028b7963748371edbe..2bb29fa449cd6c90b52d2786ed15b6154d591607 100644 +--- a/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java ++++ b/src/main/java/org/bukkit/event/entity/ItemDespawnEvent.java +@@ -46,7 +46,7 @@ public class ItemDespawnEvent extends EntityEvent implements Cancellable { + */ + @NotNull + public Location getLocation() { +- return location; ++ return location.clone(); // Paper - clone to avoid changes + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java +index d0a437bd8aeec18f800893f51ece06deb0c8972c..50fad23cf4d9f591b12a9eaebeb4e26f18e8528d 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java +@@ -31,7 +31,7 @@ public class VehicleBlockCollisionEvent extends VehicleCollisionEvent { + */ + @NotNull + public org.bukkit.util.Vector getVelocity() { +- return velocity; ++ return velocity.clone(); + } + // Paper end + +diff --git a/src/main/java/org/bukkit/event/vehicle/VehicleMoveEvent.java b/src/main/java/org/bukkit/event/vehicle/VehicleMoveEvent.java +index 7bfb84d3948c773e943374316ea25a19288ec7d0..fc4cf7b21b24fe38617fa150f697bc29da76754e 100644 +--- a/src/main/java/org/bukkit/event/vehicle/VehicleMoveEvent.java ++++ b/src/main/java/org/bukkit/event/vehicle/VehicleMoveEvent.java +@@ -27,7 +27,7 @@ public class VehicleMoveEvent extends VehicleEvent { + */ + @NotNull + public Location getFrom() { +- return from; ++ return from.clone(); // Paper - clone to avoid changes + } + + /** +@@ -37,7 +37,7 @@ public class VehicleMoveEvent extends VehicleEvent { + */ + @NotNull + public Location getTo() { +- return to; ++ return to.clone(); // Paper - clone to avoid changes + } + + +diff --git a/src/main/java/org/bukkit/event/world/GenericGameEvent.java b/src/main/java/org/bukkit/event/world/GenericGameEvent.java +index 2a2a329877d8da45c2d6afecf78ce88d52635cad..fb975fefc74d8c9746cab4c02860f55654cf92f7 100644 +--- a/src/main/java/org/bukkit/event/world/GenericGameEvent.java ++++ b/src/main/java/org/bukkit/event/world/GenericGameEvent.java +@@ -49,7 +49,7 @@ public class GenericGameEvent extends WorldEvent implements Cancellable { + */ + @NotNull + public Location getLocation() { +- return location; ++ return location.clone(); // Paper - clone to avoid changes + } + + /** +diff --git a/src/main/java/org/bukkit/event/world/SpawnChangeEvent.java b/src/main/java/org/bukkit/event/world/SpawnChangeEvent.java +index 9ce93d00935446589cb2bb970cb540d109616e85..73997ae04ff39ac3984c59de32aaced9eb72ce16 100644 +--- a/src/main/java/org/bukkit/event/world/SpawnChangeEvent.java ++++ b/src/main/java/org/bukkit/event/world/SpawnChangeEvent.java +@@ -25,7 +25,7 @@ public class SpawnChangeEvent extends WorldEvent { + */ + @NotNull + public Location getPreviousLocation() { +- return previousLocation; ++ return previousLocation.clone(); // Paper - clone to avoid changes + } + + @NotNull +diff --git a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java +index 7af8d6e51c824cf0592b722b834f1d4986e3cc08..783e74bc382f0f6d24203fde7b811f588a674731 100644 +--- a/src/main/java/org/bukkit/event/world/StructureGrowEvent.java ++++ b/src/main/java/org/bukkit/event/world/StructureGrowEvent.java +@@ -39,7 +39,7 @@ public class StructureGrowEvent extends WorldEvent implements Cancellable { + */ + @NotNull + public Location getLocation() { +- return location; ++ return location.clone(); // Paper - clone to avoid changes + } + + /** diff --git a/patches/api/0450-Add-BlockBreakProgressUpdateEvent.patch b/patches/api/0450-Add-BlockBreakProgressUpdateEvent.patch new file mode 100644 index 000000000000..9a1913895ba4 --- /dev/null +++ b/patches/api/0450-Add-BlockBreakProgressUpdateEvent.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Badbird5907 <50347938+Badbird5907@users.noreply.github.com> +Date: Mon, 4 Mar 2024 22:18:33 -0500 +Subject: [PATCH] Add BlockBreakProgressUpdateEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/BlockBreakProgressUpdateEvent.java b/src/main/java/io/papermc/paper/event/block/BlockBreakProgressUpdateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1820e9b12141f3798dac499e19f8337c6f89d671 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BlockBreakProgressUpdateEvent.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when the progress of a block break is updated. ++ */ ++@NullMarked ++public class BlockBreakProgressUpdateEvent extends BlockEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final float progress; ++ private final Entity entity; ++ ++ @ApiStatus.Internal ++ public BlockBreakProgressUpdateEvent(final Block block, final float progress, final Entity entity) { ++ super(block); ++ this.progress = progress; ++ this.entity = entity; ++ } ++ ++ /** ++ * The progress of the block break ++ *

      ++ * The progress ranges from 0.0 - 1.0, where 0 is no damage and ++ * 1.0 is the most damaged ++ * ++ * @return The progress of the block break ++ */ ++ public float getProgress() { ++ return this.progress; ++ } ++ ++ /** ++ * The entity breaking the block. ++ * ++ * @return The entity breaking the block ++ */ ++ public Entity getEntity() { ++ return this.entity; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} diff --git a/patches/api/0451-Deprecate-ItemStack-setType.patch b/patches/api/0451-Deprecate-ItemStack-setType.patch new file mode 100644 index 000000000000..edfbdb9d0a52 --- /dev/null +++ b/patches/api/0451-Deprecate-ItemStack-setType.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Thu, 29 Feb 2024 17:54:26 -0500 +Subject: [PATCH] Deprecate ItemStack#setType + + +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 0e6103628673130139363b53d23d3432deff5c50..4bb051af04d7e76853309386eb4ee43a00813c58 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -143,8 +143,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + * {@link Material#isItem()} returns false. + * + * @param type New type to set the items in this stack to ++ * @deprecated Setting the material type of ItemStacks is no longer supported. ++ *

      ++ * This method is deprecated due to potential illegal behavior that may occur ++ * during the context of which this ItemStack is being used, allowing for certain item validation to be bypassed. ++ * It is recommended to instead create a new ItemStack object with the desired ++ * Material type, and if possible, set it in the appropriate context. ++ * ++ * Using this method in ItemStacks passed in events will result in undefined behavior. ++ * @see ItemStack#withType(Material) + */ + @Utility ++ @Deprecated // Paper + public void setType(@NotNull Material type) { + Preconditions.checkArgument(type != null, "Material cannot be null"); + this.type = type; +@@ -157,6 +167,24 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + this.data = null; + } + } ++ // Paper start ++ /** ++ * Creates a new ItemStack with the specified Material type, where the item count and item meta is preserved. ++ * ++ * @param type The Material type of the new ItemStack. ++ * @return A new ItemStack instance with the specified Material type. ++ */ ++ @NotNull ++ @org.jetbrains.annotations.Contract(value = "_ -> new", pure = true) ++ public ItemStack withType(@NotNull Material type) { ++ ItemStack itemStack = new ItemStack(type, this.amount); ++ if (this.hasItemMeta()) { ++ itemStack.setItemMeta(this.getItemMeta()); ++ } ++ ++ return itemStack; ++ } ++ // Paper end + + /** + * Gets the amount of items in this stack diff --git a/patches/api/0452-Item-Mutation-Fixes.patch b/patches/api/0452-Item-Mutation-Fixes.patch new file mode 100644 index 000000000000..ccd77b7fbc62 --- /dev/null +++ b/patches/api/0452-Item-Mutation-Fixes.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 20 Mar 2024 20:42:31 -0400 +Subject: [PATCH] Item Mutation Fixes + + +diff --git a/src/main/java/org/bukkit/event/block/InventoryBlockStartEvent.java b/src/main/java/org/bukkit/event/block/InventoryBlockStartEvent.java +index 1ebd45295a29fbc990a1311a7f0fe7f42ac79275..b70450919e78e869c9f158c4e3e25944bcaa73f2 100644 +--- a/src/main/java/org/bukkit/event/block/InventoryBlockStartEvent.java ++++ b/src/main/java/org/bukkit/event/block/InventoryBlockStartEvent.java +@@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull; + public class InventoryBlockStartEvent extends BlockEvent { + + private static final HandlerList handlers = new HandlerList(); +- private final ItemStack source; ++ protected ItemStack source; // Paper + + public InventoryBlockStartEvent(@NotNull final Block block, @NotNull ItemStack source) { + super(block); +diff --git a/src/main/java/org/bukkit/event/enchantment/EnchantItemEvent.java b/src/main/java/org/bukkit/event/enchantment/EnchantItemEvent.java +index 1829529c9915937dcdd0e6d1ceba9e64819fb93f..e7c243038b70ca13b7eabdf88ce518b6198c6db9 100644 +--- a/src/main/java/org/bukkit/event/enchantment/EnchantItemEvent.java ++++ b/src/main/java/org/bukkit/event/enchantment/EnchantItemEvent.java +@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; + public class EnchantItemEvent extends InventoryEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private final Block table; +- private final ItemStack item; ++ private ItemStack item; // Paper + private int level; + private boolean cancelled; + private final Map enchants; +@@ -72,6 +72,17 @@ public class EnchantItemEvent extends InventoryEvent implements Cancellable { + return item; + } + ++ // Paper start ++ /** ++ * Sets the item to be enchanted ++ * ++ * @param item item ++ */ ++ public void setItem(@NotNull final ItemStack item) { ++ this.item = item; ++ } ++ // Paper end ++ + /** + * Gets the cost (minimum level) which is displayed as a number on the right + * hand side of the enchantment offer. diff --git a/patches/api/0453-API-for-checking-sent-chunks.patch b/patches/api/0453-API-for-checking-sent-chunks.patch new file mode 100644 index 000000000000..ce630de11f4e --- /dev/null +++ b/patches/api/0453-API-for-checking-sent-chunks.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Flo0 +Date: Mon, 8 Apr 2024 16:22:07 +0200 +Subject: [PATCH] API for checking sent chunks + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index a7a4e5423cedb67bcdf02738be62bdf83e748b82..f007c82bb8cab84856930e654d77610242501589 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3844,6 +3844,47 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + void resetIdleDuration(); + // Paper end + ++ // Paper start - Add chunk view API ++ /** ++ * Gets the a set of chunk keys for all chunks that have been sent to the player. ++ * ++ * @return an immutable set of chunk keys ++ * @apiNote currently marked as experimental to gather feedback regarding the returned set being an immutable copy ++ * vs it potentially being an unmodifiable view of the set chunks. ++ */ ++ @ApiStatus.Experimental ++ java.util.@NotNull @org.jetbrains.annotations.Unmodifiable Set getSentChunkKeys(); ++ ++ /** ++ * Gets the set of chunks that have been sent to the player. ++ * ++ * @return an immutable set of chunks ++ * @apiNote currently marked as experimental to gather feedback regarding the returned set being an immutable copy ++ * vs it potentially being an unmodifiable view of the set chunks. ++ */ ++ @ApiStatus.Experimental ++ java.util.@NotNull @org.jetbrains.annotations.Unmodifiable Set getSentChunks(); ++ ++ /** ++ * Checks if the player has been sent a specific chunk. ++ * ++ * @param chunk the chunk to check ++ * @return true if the player has been sent the chunk, false otherwise ++ */ ++ default boolean isChunkSent(@NotNull org.bukkit.Chunk chunk) { ++ return this.isChunkSent(chunk.getChunkKey()); ++ } ++ ++ /** ++ * Checks if the player has been sent a specific chunk. ++ * ++ * @param chunkKey the chunk key to check ++ * @return true if the player has been sent the chunk, false otherwise ++ * @see org.bukkit.Chunk#getChunkKey() ++ */ ++ boolean isChunkSent(long chunkKey); ++ // Paper end ++ + @NotNull + @Override + Spigot spigot(); diff --git a/patches/api/0454-Add-CartographyItemEvent.patch b/patches/api/0454-Add-CartographyItemEvent.patch new file mode 100644 index 000000000000..8bfd237e0ccf --- /dev/null +++ b/patches/api/0454-Add-CartographyItemEvent.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Janet Blackquill +Date: Sun, 7 Apr 2024 16:51:04 -0400 +Subject: [PATCH] Add CartographyItemEvent + +Similar to SmithItemEvent, but for cartography tables. + +diff --git a/src/main/java/io/papermc/paper/event/player/CartographyItemEvent.java b/src/main/java/io/papermc/paper/event/player/CartographyItemEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d5c67f5462b9011683ce742a197959f9c4380d40 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/CartographyItemEvent.java +@@ -0,0 +1,32 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.CartographyInventory; ++import org.bukkit.inventory.InventoryView; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when the recipe of an Item is completed inside a cartography table. ++ */ ++@NullMarked ++public class CartographyItemEvent extends InventoryClickEvent { ++ ++ @ApiStatus.Internal ++ public CartographyItemEvent(final InventoryView view, final InventoryType.SlotType type, final int slot, final ClickType click, final InventoryAction action) { ++ super(view, type, slot, click, action); ++ } ++ ++ @ApiStatus.Internal ++ public CartographyItemEvent(final InventoryView view, final InventoryType.SlotType type, final int slot, final ClickType click, final InventoryAction action, final int key) { ++ super(view, type, slot, click, action, key); ++ } ++ ++ @Override ++ public CartographyInventory getInventory() { ++ return (CartographyInventory) super.getInventory(); ++ } ++} diff --git a/patches/api/0455-More-Raid-API.patch b/patches/api/0455-More-Raid-API.patch new file mode 100644 index 000000000000..ac5714cfba75 --- /dev/null +++ b/patches/api/0455-More-Raid-API.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 4 Mar 2022 09:46:40 -0800 +Subject: [PATCH] More Raid API + + +diff --git a/src/main/java/org/bukkit/Raid.java b/src/main/java/org/bukkit/Raid.java +index 983a8c20a06d2b509602b27f49c090598b8ecc42..fa98599e3eee37bf68f0e9813497c718f457485c 100644 +--- a/src/main/java/org/bukkit/Raid.java ++++ b/src/main/java/org/bukkit/Raid.java +@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents a raid event. + */ +-public interface Raid { ++public interface Raid extends org.bukkit.persistence.PersistentDataHolder { // Paper + + /** + * Get whether this raid started. +@@ -131,4 +131,20 @@ public interface Raid { + */ + STOPPED; + } ++ ++ // Paper start ++ /** ++ * Gets the id of this raid. ++ * ++ * @return the raid id ++ */ ++ int getId(); ++ ++ /** ++ * Get the boss bar to be displayed for this raid. ++ * ++ * @return the boss bar ++ */ ++ org.bukkit.boss.@NotNull BossBar getBossBar(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 1796615065c8a6d06450d1b9c389804e804c4327..e2573ede859a536dfbb487b3f237caff742b0b30 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -4164,6 +4164,17 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + @Nullable + public Raid locateNearestRaid(@NotNull Location location, int radius); + ++ // Paper start - more Raid API ++ /** ++ * Get a raid with the specific id from {@link Raid#getId} ++ * from this world. ++ * ++ * @param id the id of the raid ++ * @return the raid or null if none with that id ++ */ ++ @Nullable Raid getRaid(int id); ++ // Paper end - more Raid API ++ + /** + * Gets all raids that are going on over this world. + * diff --git a/patches/api/0456-Fix-SpawnerEntry-Equipment-API.patch b/patches/api/0456-Fix-SpawnerEntry-Equipment-API.patch new file mode 100644 index 000000000000..e170eabd170e --- /dev/null +++ b/patches/api/0456-Fix-SpawnerEntry-Equipment-API.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 26 Apr 2024 17:00:00 -0700 +Subject: [PATCH] Fix SpawnerEntry$Equipment API + + +diff --git a/src/main/java/org/bukkit/block/spawner/SpawnerEntry.java b/src/main/java/org/bukkit/block/spawner/SpawnerEntry.java +index fc1c0435dfea121923eb1fe0182880752f321143..bc8ccd139df6072f9744cfb85ad0070369600aa1 100644 +--- a/src/main/java/org/bukkit/block/spawner/SpawnerEntry.java ++++ b/src/main/java/org/bukkit/block/spawner/SpawnerEntry.java +@@ -120,27 +120,29 @@ public class SpawnerEntry { + private final Map dropChances; + + public Equipment(@NotNull LootTable equipmentLootTable, @NotNull Map dropChances) { ++ Preconditions.checkArgument(equipmentLootTable != null, "table cannot be null"); // Paper + this.equipmentLootTable = equipmentLootTable; + this.dropChances = dropChances; + } + + /** +- * Set the loot table for the entity. ++ * Set the loot table for the spawned entity's equipment slots. + *
      +- * To remove a loot table use null. ++ * To remove a loot table use the empty loot table. + * + * @param table this {@link org.bukkit.entity.Mob} will have. + */ + public void setEquipmentLootTable(@NotNull LootTable table) { ++ Preconditions.checkArgument(table != null, "table cannot be null"); // Paper + this.equipmentLootTable = table; + } + + /** +- * Gets the loot table for the entity. ++ * Gets the loot table for the spawned entity's equipment. + *
      + * +- * If an entity does not have a loot table, this will return null, NOT +- * an empty loot table. ++ * If an entity does not have a loot table, this will return an ++ * empty loot table. + * + * @return the loot table for this entity. + */ diff --git a/patches/api/0457-Fix-ItemFlags.patch b/patches/api/0457-Fix-ItemFlags.patch new file mode 100644 index 000000000000..75f8c497f26d --- /dev/null +++ b/patches/api/0457-Fix-ItemFlags.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 27 Apr 2024 13:28:17 -0700 +Subject: [PATCH] Fix ItemFlags + +Adds new flag in HIDE_STORED_ENCHANTS which was split +from HIDE_ADDITIONAL_INFO. Adds a migration to account for +this, adding the new flag if the itemstack is old and had the +old flag. + +diff --git a/src/main/java/org/bukkit/inventory/ItemFlag.java b/src/main/java/org/bukkit/inventory/ItemFlag.java +index 5b8dac777bb1640dc00bbe98feb6460c36eebb98..1af15fd327e0613cd1a179bd7fef1e83cbe31761 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFlag.java ++++ b/src/main/java/org/bukkit/inventory/ItemFlag.java +@@ -2,6 +2,8 @@ package org.bukkit.inventory; + + /** + * A ItemFlag can hide some Attributes from ItemStacks ++ * @apiNote Setting these without also setting the data they are hiding ++ * may not result in the item flag being persisted in the ItemMeta/ItemStack. + */ + public enum ItemFlag { + +@@ -27,7 +29,8 @@ public enum ItemFlag { + HIDE_PLACED_ON, + /** + * Setting to show/hide potion effects, book and firework information, map +- * tooltips, patterns of banners, and enchantments of enchanted books. ++ * tooltips, patterns of banners. ++ * @see #HIDE_STORED_ENCHANTS HIDE_STORED_ENCHANTS for hiding stored enchants (like on enchanted books) + */ + HIDE_ADDITIONAL_TOOLTIP, + /** +@@ -37,7 +40,13 @@ public enum ItemFlag { + /** + * Setting to show/hide armor trim from armor. + */ +- HIDE_ARMOR_TRIM; ++ HIDE_ARMOR_TRIM, ++ /** ++ * Setting to show/hide stored enchants on an item, such as enchantments ++ * on an enchanted book. ++ */ ++ HIDE_STORED_ENCHANTS, ++ ; + // Paper start + /** + * Setting to show/hide item-specific information, including, but not limited to: +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 4bb051af04d7e76853309386eb4ee43a00813c58..10b913490eaba71849f896754dfcb62b4b114e2c 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -588,6 +588,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + Object raw = args.get("meta"); + if (raw instanceof ItemMeta) { + ((ItemMeta) raw).setVersion(version); ++ // Paper start - for pre 1.20.5 itemstacks, add HIDE_STORED_ENCHANTS flag if HIDE_ADDITIONAL_TOOLTIP is set ++ if (version < 3837) { // 1.20.5 ++ if (((ItemMeta) raw).hasItemFlag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP)) { ++ ((ItemMeta) raw).addItemFlags(ItemFlag.HIDE_STORED_ENCHANTS); ++ } ++ } ++ // Paper end + result.setItemMeta((ItemMeta) raw); + } + } diff --git a/patches/api/0458-Allow-modifying-library-loader-jars-bytecode.patch b/patches/api/0458-Allow-modifying-library-loader-jars-bytecode.patch new file mode 100644 index 000000000000..0c0311e790ef --- /dev/null +++ b/patches/api/0458-Allow-modifying-library-loader-jars-bytecode.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Sun, 28 Apr 2024 11:11:26 -0700 +Subject: [PATCH] Allow modifying library loader jars bytecode + + +diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +index f4d655a158410039305ac68cebe0d79000f73df8..5b0203e908f84c531886b8ea8faeb591eb045636 100644 +--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +@@ -46,6 +46,7 @@ public class LibraryLoader + private final RepositorySystem repository; + private final DefaultRepositorySystemSession session; + private final List repositories; ++ public static java.util.function.BiFunction LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries + + public LibraryLoader(@NotNull Logger logger) + { +@@ -130,7 +131,14 @@ public class LibraryLoader + } ); + } + +- URLClassLoader loader = new URLClassLoader( jarFiles.toArray( new URL[ jarFiles.size() ] ), getClass().getClassLoader() ); ++ // Paper start - rewrite reflection in libraries ++ URLClassLoader loader; ++ if (LIBRARY_LOADER_FACTORY == null) { ++ loader = new URLClassLoader( jarFiles.toArray( new URL[ jarFiles.size() ] ), getClass().getClassLoader() ); ++ } else { ++ loader = LIBRARY_LOADER_FACTORY.apply(jarFiles.toArray( new URL[ jarFiles.size() ] ), getClass().getClassLoader()); ++ } ++ // Paper end - rewrite reflection in libraries + + return loader; + } diff --git a/patches/api/0459-Add-hook-to-remap-library-jars.patch b/patches/api/0459-Add-hook-to-remap-library-jars.patch new file mode 100644 index 000000000000..fe1609629e8e --- /dev/null +++ b/patches/api/0459-Add-hook-to-remap-library-jars.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Sun, 28 Apr 2024 13:51:08 -0700 +Subject: [PATCH] Add hook to remap library jars + + +diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +index 5b0203e908f84c531886b8ea8faeb591eb045636..8e1b6be2462aaa692efa1f72986921a6dc357196 100644 +--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +@@ -47,6 +47,7 @@ public class LibraryLoader + private final DefaultRepositorySystemSession session; + private final List repositories; + public static java.util.function.BiFunction LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries ++ public static java.util.function.Function, List> REMAPPER; // Paper - remap libraries + + public LibraryLoader(@NotNull Logger logger) + { +@@ -111,9 +112,18 @@ public class LibraryLoader + } + + List jarFiles = new ArrayList<>(); ++ List jarPaths = new ArrayList<>(); // Paper - remap libraries + for ( ArtifactResult artifact : result.getArtifactResults() ) + { +- File file = artifact.getArtifact().getFile(); ++ // Paper start - remap libraries ++ jarPaths.add(artifact.getArtifact().getFile().toPath()); ++ } ++ if (REMAPPER != null) { ++ jarPaths = REMAPPER.apply(jarPaths); ++ } ++ for (java.nio.file.Path path : jarPaths) { ++ File file = path.toFile(); ++ // Paper end - remap libraries + + URL url; + try diff --git a/patches/api/0460-Add-GameMode-isInvulnerable.patch b/patches/api/0460-Add-GameMode-isInvulnerable.patch new file mode 100644 index 000000000000..b4b81c5f523f --- /dev/null +++ b/patches/api/0460-Add-GameMode-isInvulnerable.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Wed, 1 May 2024 06:56:21 +0300 +Subject: [PATCH] Add GameMode#isInvulnerable + + +diff --git a/src/main/java/org/bukkit/GameMode.java b/src/main/java/org/bukkit/GameMode.java +index fdc42a79c5af30fdade41ee99245e6641f353571..ddc56524b3bd2bdebba81c61a5600e6f46a4aaa4 100644 +--- a/src/main/java/org/bukkit/GameMode.java ++++ b/src/main/java/org/bukkit/GameMode.java +@@ -79,4 +79,16 @@ public enum GameMode implements net.kyori.adventure.translation.Translatable { / + BY_ID.put(mode.getValue(), mode); + } + } ++ ++ // Paper start - Add GameMode#isInvulnerable ++ /** ++ * Checks whether this game mode is invulnerable ++ * (i.e. is either {@link #CREATIVE} or {@link #SPECTATOR}) ++ * ++ * @return whether this game mode is invulnerable ++ */ ++ public boolean isInvulnerable() { ++ return this == CREATIVE || this == SPECTATOR; ++ } ++ // Paper end - Add GameMode#isInvulnerable + } diff --git a/patches/api/0461-Expose-hasColor-to-leather-armor.patch b/patches/api/0461-Expose-hasColor-to-leather-armor.patch new file mode 100644 index 000000000000..e2c609b4f0fc --- /dev/null +++ b/patches/api/0461-Expose-hasColor-to-leather-armor.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Wed, 1 May 2024 10:58:50 +0300 +Subject: [PATCH] Expose #hasColor to leather armor + + +diff --git a/src/main/java/org/bukkit/inventory/meta/LeatherArmorMeta.java b/src/main/java/org/bukkit/inventory/meta/LeatherArmorMeta.java +index c701d5fbc5fef503f18a3a46fa54c983bf96e895..2d68f93c371e4a40638f56e5cd4d39472d4e462b 100644 +--- a/src/main/java/org/bukkit/inventory/meta/LeatherArmorMeta.java ++++ b/src/main/java/org/bukkit/inventory/meta/LeatherArmorMeta.java +@@ -36,4 +36,13 @@ public interface LeatherArmorMeta extends ItemMeta { + @Override + @NotNull + LeatherArmorMeta clone(); ++ ++ // Paper start - Expose #hasColor to leather armor ++ /** ++ * Checks whether this leather armor is dyed. ++ * ++ * @return whether this leather armor is dyed ++ */ ++ boolean isDyed(); ++ // Paper end - Expose #hasColor to leather armor + } diff --git a/patches/api/0462-Added-API-to-get-player-ha-proxy-address.patch b/patches/api/0462-Added-API-to-get-player-ha-proxy-address.patch new file mode 100644 index 000000000000..d1e0188a7bb1 --- /dev/null +++ b/patches/api/0462-Added-API-to-get-player-ha-proxy-address.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nostalfinals +Date: Mon, 8 Apr 2024 23:24:38 +0800 +Subject: [PATCH] Added API to get player ha proxy address + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index f007c82bb8cab84856930e654d77610242501589..0387eb02575cd2f20061f92c2ba5432f16b014b2 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -267,6 +267,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + @Nullable + public InetSocketAddress getAddress(); + ++ // Paper start - Add API to get player's proxy address ++ /** ++ * Gets the socket address of this player's proxy ++ * ++ * @return the player's proxy address, null if the server doesn't have Proxy Protocol enabled, or the player didn't connect to an HAProxy instance ++ */ ++ @Nullable ++ public InetSocketAddress getHAProxyAddress(); ++ // Paper end - Add API to get player's proxy address ++ + /** + * Gets if this connection has been transferred from another server. + * diff --git a/patches/api/0463-More-Chest-Block-API.patch b/patches/api/0463-More-Chest-Block-API.patch new file mode 100644 index 000000000000..1fc3614c74c8 --- /dev/null +++ b/patches/api/0463-More-Chest-Block-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SoSeDiK +Date: Wed, 1 May 2024 08:22:13 +0300 +Subject: [PATCH] More Chest Block API + + +diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java +index db6affbc78106b2d93b41953b624a0bca0ca1d72..5d02f9c938d0d7d0f4e491ccfaf6beb0a7a61aa4 100644 +--- a/src/main/java/org/bukkit/block/Chest.java ++++ b/src/main/java/org/bukkit/block/Chest.java +@@ -27,4 +27,14 @@ public interface Chest extends Container, LootableBlockInventory, Lidded { // Pa + */ + @NotNull + Inventory getBlockInventory(); ++ ++ // Paper start - More Chest Block API ++ /** ++ * Checks whether this chest is blocked ++ * by either a block above or a sitting cat ++ * ++ * @return whether this chest is blocked ++ */ ++ boolean isBlocked(); ++ // Paper end - More Chest Block API + } +diff --git a/src/main/java/org/bukkit/block/EnderChest.java b/src/main/java/org/bukkit/block/EnderChest.java +index 1150b449a3f5c40fe10136779c2ccc65ab4d884c..6b66f38e5509f90aad5ee1fffca01003dcbe9896 100644 +--- a/src/main/java/org/bukkit/block/EnderChest.java ++++ b/src/main/java/org/bukkit/block/EnderChest.java +@@ -3,4 +3,13 @@ package org.bukkit.block; + /** + * Represents a captured state of an ender chest. + */ +-public interface EnderChest extends Lidded, TileState { } ++public interface EnderChest extends Lidded, TileState { ++ // Paper start - More Chest Block API ++ /** ++ * Checks whether this ender chest is blocked by a block above ++ * ++ * @return whether this ender chest is blocked ++ */ ++ boolean isBlocked(); ++ // Paper end - More Chest Block API ++} diff --git a/patches/api/0464-Brigadier-based-command-API.patch b/patches/api/0464-Brigadier-based-command-API.patch new file mode 100644 index 000000000000..894baf9ad80b --- /dev/null +++ b/patches/api/0464-Brigadier-based-command-API.patch @@ -0,0 +1,2073 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Mon, 1 Aug 2022 22:50:29 -0400 +Subject: [PATCH] Brigadier based command API + +Co-authored-by: Jake Potrebic + +diff --git a/build.gradle.kts b/build.gradle.kts +index 2b489adc50d45facd347f79c34224d347dc20a75..571534b42cd9c33d6a7bb6fe3bf3a28e33f8e5de 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -39,6 +39,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider { + // Paper end - configure mockito agent that is needed in newer java versions + + dependencies { ++ api("com.mojang:brigadier:1.2.9") // Paper - Brigadier command api + // api dependencies are listed transitively to API consumers + api("com.google.guava:guava:33.3.1-jre") + api("com.google.code.gson:gson:2.11.0") +@@ -108,9 +109,33 @@ sourceSets { + } + } + // Paper end ++// Paper start - brigadier API ++val outgoingVariants = arrayOf("runtimeElements", "apiElements", "sourcesElements", "javadocElements") ++val mainCapability = "${project.group}:${project.name}:${project.version}" ++configurations { ++ val outgoing = outgoingVariants.map { named(it) } ++ for (config in outgoing) { ++ config { ++ attributes { ++ attribute(io.papermc.paperweight.util.mainCapabilityAttribute, mainCapability) ++ } ++ outgoing { ++ capability(mainCapability) ++ capability("io.papermc.paper:paper-mojangapi:${project.version}") ++ capability("com.destroystokyo.paper:paper-mojangapi:${project.version}") ++ } ++ } ++ } ++} ++// Paper end + + configure { + publications.create("maven") { ++ // Paper start - brigadier API ++ outgoingVariants.forEach { ++ suppressPomMetadataWarningsFor(it) ++ } ++ // Paper end + from(components["java"]) + } + } +diff --git a/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java b/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..03a1078446f84b998cd7fe8d64abecb2e36bab0a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommand.java +@@ -0,0 +1,16 @@ ++package com.destroystokyo.paper.brigadier; ++ ++import com.mojang.brigadier.Command; ++import com.mojang.brigadier.suggestion.SuggestionProvider; ++ ++import java.util.function.Predicate; ++ ++/** ++ * Brigadier {@link Command}, {@link SuggestionProvider}, and permission checker for Bukkit {@link Command}s. ++ * ++ * @param command source type ++ * @deprecated For removal, see {@link io.papermc.paper.command.brigadier.Commands} on how to use the new Brigadier API. ++ */ ++@Deprecated(forRemoval = true, since = "1.20.6") ++public interface BukkitBrigadierCommand extends Command, Predicate, SuggestionProvider { ++} +diff --git a/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java b/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..28b44789e3be586c4b680fff56e5d2ff095f9ac2 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/brigadier/BukkitBrigadierCommandSource.java +@@ -0,0 +1,25 @@ ++package com.destroystokyo.paper.brigadier; ++ ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.command.CommandSender; ++import org.bukkit.entity.Entity; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * @deprecated For removal, see {@link io.papermc.paper.command.brigadier.Commands} on how to use the new Brigadier API. ++ */ ++@Deprecated(forRemoval = true) ++public interface BukkitBrigadierCommandSource { ++ ++ @Nullable ++ Entity getBukkitEntity(); ++ ++ @Nullable ++ World getBukkitWorld(); ++ ++ @Nullable ++ Location getBukkitLocation(); ++ ++ CommandSender getBukkitSender(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java b/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9e1b70d438c4341ec944503b5bbe6b1f08bc0478 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.java +@@ -0,0 +1,73 @@ ++package com.destroystokyo.paper.event.brigadier; ++ ++import com.mojang.brigadier.tree.RootCommandNode; ++import io.papermc.paper.command.brigadier.CommandSourceStack; ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Fired any time a Brigadier RootCommandNode is generated for a player to inform the client of commands. ++ * You may manipulate this CommandNode to change what the client sees. ++ * ++ *

      This event may fire on login, world change, and permission rebuilds, by plugin request, and potentially future means.

      ++ * ++ *

      This event will fire before {@link org.bukkit.event.player.PlayerCommandSendEvent}, so no filtering has been done by ++ * other plugins yet.

      ++ * ++ *

      WARNING: This event will potentially (and most likely) fire twice! Once for Async, and once again for Sync. ++ * It is important that you check event.isAsynchronous() and event.hasFiredAsync() to ensure you only act once. ++ * If for some reason we are unable to send this asynchronously in the future, only the sync method will fire.

      ++ * ++ *

      Your logic should look like this: ++ * {@code if (event.isAsynchronous() || !event.hasFiredAsync()) { // do stuff }}

      ++ * ++ *

      If your logic is not safe to run asynchronously, only react to the synchronous version.

      ++ * ++ *

      This is a draft/experimental API and is subject to change.

      ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public class AsyncPlayerSendCommandsEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ private final RootCommandNode node; ++ private final boolean hasFiredAsync; ++ ++ @ApiStatus.Internal ++ public AsyncPlayerSendCommandsEvent(final Player player, final RootCommandNode node, final boolean hasFiredAsync) { ++ super(player, !Bukkit.isPrimaryThread()); ++ this.node = node; ++ this.hasFiredAsync = hasFiredAsync; ++ } ++ ++ /** ++ * Gets the full Root Command Node being sent to the client, which is mutable. ++ * ++ * @return the root command node ++ */ ++ public RootCommandNode getCommandNode() { ++ return this.node; ++ } ++ ++ /** ++ * Gets if this event has already fired asynchronously. ++ * ++ * @return whether this event has already fired asynchronously ++ */ ++ public boolean hasFiredAsync() { ++ return this.hasFiredAsync; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java b/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..faade9d35514687f21a0e8b62fa2e392d4ad238a +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendSuggestionsEvent.java +@@ -0,0 +1,85 @@ ++package com.destroystokyo.paper.event.brigadier; ++ ++import com.mojang.brigadier.suggestion.Suggestions; ++import org.bukkit.Bukkit; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * Called when sending {@link Suggestions} to the client. Will be called asynchronously if a plugin ++ * marks the {@link com.destroystokyo.paper.event.server.AsyncTabCompleteEvent} event handled asynchronously, ++ * otherwise called synchronously. ++ */ ++@NullMarked ++public class AsyncPlayerSendSuggestionsEvent extends PlayerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ private boolean cancelled = false; ++ ++ private Suggestions suggestions; ++ private final String buffer; ++ ++ @ApiStatus.Internal ++ public AsyncPlayerSendSuggestionsEvent(final Player player, final Suggestions suggestions, final String buffer) { ++ super(player, !Bukkit.isPrimaryThread()); ++ this.suggestions = suggestions; ++ this.buffer = buffer; ++ } ++ ++ /** ++ * Gets the input buffer sent to request these suggestions. ++ * ++ * @return the input buffer ++ */ ++ public String getBuffer() { ++ return this.buffer; ++ } ++ ++ /** ++ * Gets the suggestions to be sent to client. ++ * ++ * @return the suggestions ++ */ ++ public Suggestions getSuggestions() { ++ return this.suggestions; ++ } ++ ++ /** ++ * Sets the suggestions to be sent to client. ++ * ++ * @param suggestions suggestions ++ */ ++ public void setSuggestions(final Suggestions suggestions) { ++ this.suggestions = suggestions; ++ } ++ ++ /** ++ * {@inheritDoc} ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Cancels sending suggestions to the client. ++ * {@inheritDoc} ++ */ ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java b/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..acc2bd2ec56e64b9d4bd8677d99448a97ecb5201 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/brigadier/CommandRegisteredEvent.java +@@ -0,0 +1,171 @@ ++package com.destroystokyo.paper.event.brigadier; ++ ++import com.destroystokyo.paper.brigadier.BukkitBrigadierCommand; ++import com.mojang.brigadier.tree.ArgumentCommandNode; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import com.mojang.brigadier.tree.RootCommandNode; ++import org.bukkit.Warning; ++import org.bukkit.command.Command; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.server.ServerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Fired anytime the server synchronizes Bukkit commands to Brigadier. ++ * ++ *

      Allows a plugin to control the command node structure for its commands. ++ * This is done at Plugin Enable time after commands have been registered, but may also ++ * run at a later point in the server lifetime due to plugins, a server reload, etc.

      ++ * ++ *

      This is a draft/experimental API and is subject to change.

      ++ * @deprecated For removal, use the new brigadier api. ++ */ ++@ApiStatus.Experimental ++@Deprecated(since = "1.20.6") ++@Warning(reason = "This event has been superseded by the Commands API and will be removed in a future release. Listen to LifecycleEvents.COMMANDS instead.", value = true) ++public class CommandRegisteredEvent extends ServerEvent implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final String commandLabel; ++ private final Command command; ++ private final com.destroystokyo.paper.brigadier.BukkitBrigadierCommand brigadierCommand; ++ private final RootCommandNode root; ++ private final ArgumentCommandNode defaultArgs; ++ private LiteralCommandNode literal; ++ private boolean rawCommand = false; ++ private boolean cancelled = false; ++ ++ public CommandRegisteredEvent(String commandLabel, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand brigadierCommand, Command command, RootCommandNode root, LiteralCommandNode literal, ArgumentCommandNode defaultArgs) { ++ this.commandLabel = commandLabel; ++ this.brigadierCommand = brigadierCommand; ++ this.command = command; ++ this.root = root; ++ this.literal = literal; ++ this.defaultArgs = defaultArgs; ++ } ++ ++ /** ++ * Gets the command label of the {@link Command} being registered. ++ * ++ * @return the command label ++ */ ++ public String getCommandLabel() { ++ return this.commandLabel; ++ } ++ ++ /** ++ * Gets the {@link BukkitBrigadierCommand} for the {@link Command} being registered. This can be used ++ * as the {@link com.mojang.brigadier.Command command executor} or ++ * {@link com.mojang.brigadier.suggestion.SuggestionProvider} of a {@link com.mojang.brigadier.tree.CommandNode} ++ * to delegate to the {@link Command} being registered. ++ * ++ * @return the {@link BukkitBrigadierCommand} ++ */ ++ public BukkitBrigadierCommand getBrigadierCommand() { ++ return this.brigadierCommand; ++ } ++ ++ /** ++ * Gets the {@link Command} being registered. ++ * ++ * @return the {@link Command} ++ */ ++ public Command getCommand() { ++ return this.command; ++ } ++ ++ /** ++ * Gets the {@link RootCommandNode} which is being registered to. ++ * ++ * @return the {@link RootCommandNode} ++ */ ++ public RootCommandNode getRoot() { ++ return this.root; ++ } ++ ++ /** ++ * Gets the Bukkit APIs default arguments node (greedy string), for if ++ * you wish to reuse it. ++ * ++ * @return default arguments node ++ */ ++ public ArgumentCommandNode getDefaultArgs() { ++ return this.defaultArgs; ++ } ++ ++ /** ++ * Gets the {@link LiteralCommandNode} to be registered for the {@link Command}. ++ * ++ * @return the {@link LiteralCommandNode} ++ */ ++ public LiteralCommandNode getLiteral() { ++ return this.literal; ++ } ++ ++ /** ++ * Sets the {@link LiteralCommandNode} used to register this command. The default literal is mutable, so ++ * this is primarily if you want to completely replace the object. ++ * ++ * @param literal new node ++ */ ++ public void setLiteral(LiteralCommandNode literal) { ++ this.literal = literal; ++ } ++ ++ /** ++ * Gets whether this command should is treated as "raw". ++ * ++ * @see #setRawCommand(boolean) ++ * @return whether this command is treated as "raw" ++ */ ++ public boolean isRawCommand() { ++ return this.rawCommand; ++ } ++ ++ /** ++ * Sets whether this command should be treated as "raw". ++ * ++ *

      A "raw" command will only use the node provided by this event for ++ * sending the command tree to the client. For execution purposes, the default ++ * greedy string execution of a standard Bukkit {@link Command} is used.

      ++ * ++ *

      On older versions of Paper, this was the default and only behavior of this ++ * event.

      ++ * ++ * @param rawCommand whether this command should be treated as "raw" ++ */ ++ public void setRawCommand(final boolean rawCommand) { ++ this.rawCommand = rawCommand; ++ } ++ ++ /** ++ * {@inheritDoc} ++ */ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * Cancels registering this command to Brigadier, but will remain in Bukkit Command Map. Can be used to hide a ++ * command from all players. ++ * ++ * {@inheritDoc} ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9df87708206e26167a2c4934deff7fc6f1657106 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java +@@ -0,0 +1,47 @@ ++package io.papermc.paper.brigadier; ++ ++import com.mojang.brigadier.Message; ++import io.papermc.paper.command.brigadier.MessageComponentSerializer; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.ComponentLike; ++import net.kyori.adventure.text.TextComponent; ++import org.checkerframework.checker.nullness.qual.NonNull; ++ ++/** ++ * Helper methods to bridge the gaps between Brigadier and Paper-MojangAPI. ++ * @deprecated for removal. See {@link MessageComponentSerializer} for a direct replacement of functionality found in ++ * this class. ++ * As a general entrypoint to brigadier on paper, see {@link io.papermc.paper.command.brigadier.Commands}. ++ */ ++@Deprecated(forRemoval = true, since = "1.20.6") ++public final class PaperBrigadier { ++ private PaperBrigadier() { ++ throw new RuntimeException("PaperBrigadier is not to be instantiated!"); ++ } ++ ++ /** ++ * Create a new Brigadier {@link Message} from a {@link ComponentLike}. ++ * ++ *

      Mostly useful for creating rich suggestion tooltips in combination with other Paper-MojangAPI APIs.

      ++ * ++ * @param componentLike The {@link ComponentLike} to use for the {@link Message} contents ++ * @return A new Brigadier {@link Message} ++ */ ++ public static @NonNull Message message(final @NonNull ComponentLike componentLike) { ++ return MessageComponentSerializer.message().serialize(componentLike.asComponent()); ++ } ++ ++ /** ++ * Create a new {@link Component} from a Brigadier {@link Message}. ++ * ++ *

      If the {@link Message} was created from a {@link Component}, it will simply be ++ * converted back, otherwise a new {@link TextComponent} will be created with the ++ * content of {@link Message#getString()}

      ++ * ++ * @param message The {@link Message} to create a {@link Component} from ++ * @return The created {@link Component} ++ */ ++ public static @NonNull Component componentFromMessage(final @NonNull Message message) { ++ return MessageComponentSerializer.message().deserialize(message); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/BasicCommand.java b/src/main/java/io/papermc/paper/command/brigadier/BasicCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c89d6c4c38e2390cb11ffba182f8741d3726cfd1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/BasicCommand.java +@@ -0,0 +1,62 @@ ++package io.papermc.paper.command.brigadier; ++ ++import java.util.Collection; ++import java.util.Collections; ++import org.bukkit.command.CommandSender; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * Implementing this interface allows for easily creating "Bukkit-style" {@code String[] args} commands. ++ * The implementation handles converting the command to a representation compatible with Brigadier on registration, usually in the form of {@literal /commandlabel }. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@FunctionalInterface ++public interface BasicCommand { ++ ++ /** ++ * Executes the command with the given {@link CommandSourceStack} and arguments. ++ * ++ * @param commandSourceStack the commandSourceStack of the command ++ * @param args the arguments of the command ignoring repeated spaces ++ */ ++ @ApiStatus.OverrideOnly ++ void execute(CommandSourceStack commandSourceStack, String[] args); ++ ++ /** ++ * Suggests possible completions for the given command {@link CommandSourceStack} and arguments. ++ * ++ * @param commandSourceStack the commandSourceStack of the command ++ * @param args the arguments of the command including repeated spaces ++ * @return a collection of suggestions ++ */ ++ @ApiStatus.OverrideOnly ++ default Collection suggest(final CommandSourceStack commandSourceStack, final String[] args) { ++ return Collections.emptyList(); ++ } ++ ++ /** ++ * Checks whether a command sender can receive and run the root command. ++ * ++ * @param sender the command sender trying to execute the command ++ * @return whether the command sender fulfills the root command requirement ++ * @see #permission() ++ */ ++ @ApiStatus.OverrideOnly ++ default boolean canUse(final CommandSender sender) { ++ final String permission = this.permission(); ++ return permission == null || sender.hasPermission(permission); ++ } ++ ++ /** ++ * Returns the permission for the root command used in {@link #canUse(CommandSender)} by default. ++ * ++ * @return the permission for the root command used in {@link #canUse(CommandSender)} ++ */ ++ @ApiStatus.OverrideOnly ++ default @Nullable String permission() { ++ return null; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java b/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7e24babf746de474c8deec4b147e22031e8dadb2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.command.brigadier; ++ ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * A {@link CommandRegistrationFlag} is used in {@link Commands} registration for internal purposes. ++ *

      ++ * A command library may use this to achieve more specific customization on how their commands are registered. ++ * @apiNote Stability of these flags is not promised! This api is not intended for public use. ++ */ ++@ApiStatus.Internal ++public enum CommandRegistrationFlag { ++ FLATTEN_ALIASES ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java b/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ac6f5b754a15e85ce09de4ed4cdee2044b45022c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/CommandSourceStack.java +@@ -0,0 +1,51 @@ ++package io.papermc.paper.command.brigadier; ++ ++import org.bukkit.Location; ++import org.bukkit.command.CommandSender; ++import org.bukkit.entity.Entity; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * The command source type for Brigadier commands registered using Paper API. ++ *

      ++ * While the general use case for CommandSourceStack is similar to that of {@link CommandSender}, it provides access to ++ * important additional context for the command execution. ++ * Specifically, commands such as {@literal /execute} may alter the location or executor of the source stack before ++ * passing it to another command. ++ *

      The {@link CommandSender} returned by {@link #getSender()} may be a "no-op" ++ * instance of {@link CommandSender} in cases where the server either doesn't ++ * exist yet, or no specific sender is available. Methods on such a {@link CommandSender} ++ * will either have no effect or throw an {@link UnsupportedOperationException}.

      ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface CommandSourceStack { ++ ++ /** ++ * Gets the location that this command is being executed at. ++ * ++ * @return a cloned location instance. ++ */ ++ Location getLocation(); ++ ++ /** ++ * Gets the command sender that executed this command. ++ * The sender of a command source stack is the one that initiated/triggered the execution of a command. ++ * It differs to {@link #getExecutor()} as the executor can be changed by a command, e.g. {@literal /execute}. ++ * ++ * @return the command sender instance ++ */ ++ CommandSender getSender(); ++ ++ /** ++ * Gets the entity that executes this command. ++ * May not always be {@link #getSender()} as the executor of a command can be changed to a different entity ++ * than the one that triggered the command. ++ * ++ * @return entity that executes this command ++ */ ++ @Nullable Entity getExecutor(); ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/Commands.java b/src/main/java/io/papermc/paper/command/brigadier/Commands.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e32559772a39af781d89de101b3f7483a339e317 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/Commands.java +@@ -0,0 +1,267 @@ ++package io.papermc.paper.command.brigadier; ++ ++import com.mojang.brigadier.CommandDispatcher; ++import com.mojang.brigadier.arguments.ArgumentType; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.bootstrap.PluginBootstrap; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; ++import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.Set; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Unmodifiable; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * The registrar for custom commands. Supports Brigadier commands and {@link BasicCommand}. ++ *

      ++ * An example of a command being registered is below ++ *

      {@code
      ++ * class YourPluginClass extends JavaPlugin {
      ++ *
      ++ *     @Override
      ++ *     public void onEnable() {
      ++ *         LifecycleEventManager manager = this.getLifecycleManager();
      ++ *         manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
      ++ *             final Commands commands = event.registrar();
      ++ *             commands.register(
      ++ *                 Commands.literal("new-command")
      ++ *                     .executes(ctx -> {
      ++ *                         ctx.getSource().getSender().sendPlainMessage("some message");
      ++ *                         return Command.SINGLE_SUCCESS;
      ++ *                     })
      ++ *                     .build(),
      ++ *                 "some bukkit help description string",
      ++ *                 List.of("an-alias")
      ++ *             );
      ++ *         });
      ++ *     }
      ++ * }
      ++ * }
      ++ *

      ++ * You can also register commands in {@link PluginBootstrap} by getting the {@link LifecycleEventManager} from ++ * {@link BootstrapContext}. ++ * Commands registered in the {@link PluginBootstrap} will be available for datapack's ++ * command function parsing. ++ * Note that commands registered via {@link PluginBootstrap} with the same literals as a vanilla command will override ++ * that command within all loaded datapacks. ++ *

      ++ *

      The {@code register} methods that do not have {@link PluginMeta} as a parameter will ++ * implicitly use the {@link PluginMeta} for the plugin that the {@link io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler} ++ * was registered with.

      ++ * ++ * @see io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents#COMMANDS ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface Commands extends Registrar { ++ ++ /** ++ * Utility to create a literal command node builder with the correct generic. ++ * ++ * @param literal literal name ++ * @return a new builder instance ++ */ ++ static LiteralArgumentBuilder literal(final String literal) { ++ return LiteralArgumentBuilder.literal(literal); ++ } ++ ++ /** ++ * Utility to create a required argument builder with the correct generic. ++ * ++ * @param name the name of the argument ++ * @param argumentType the type of the argument ++ * @param the generic type of the argument value ++ * @return a new required argument builder ++ */ ++ static RequiredArgumentBuilder argument(final String name, final ArgumentType argumentType) { ++ return RequiredArgumentBuilder.argument(name, argumentType); ++ } ++ ++ /** ++ * Gets the underlying {@link CommandDispatcher}. ++ * ++ *

      Note: This is a delicate API that must be used with care to ensure a consistent user experience.

      ++ * ++ *

      When registering commands, it should be preferred to use the {@link #register(PluginMeta, LiteralCommandNode, String, Collection) register methods} ++ * over directly registering to the dispatcher wherever possible. ++ * {@link #register(PluginMeta, LiteralCommandNode, String, Collection) Register methods} automatically handle ++ * command namespacing, command help, plugin association with commands, and more.

      ++ * ++ *

      Example use cases for this method may include: ++ *

        ++ *
      • Implementing integration between an external command framework and Paper (although {@link #register(PluginMeta, LiteralCommandNode, String, Collection) register methods} should still be preferred where possible)
      • ++ *
      • Registering new child nodes to an existing plugin command (for example an "addon" plugin to another plugin may want to do this)
      • ++ *
      • Retrieving existing command nodes to build redirects
      • ++ *
      ++ * ++ * @return the dispatcher instance ++ */ ++ @ApiStatus.Experimental ++ CommandDispatcher getDispatcher(); ++ ++ /** ++ * Registers a command for the current plugin context. ++ * ++ *

      Commands have certain overriding behavior: ++ *

        ++ *
      • Aliases will not override already existing commands (excluding namespaced ones)
      • ++ *
      • The main command/namespaced label will override already existing commands
      • ++ *
      ++ * ++ * @param node the built literal command node ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final LiteralCommandNode node) { ++ return this.register(node, null, Collections.emptyList()); ++ } ++ ++ /** ++ * Registers a command for the current plugin context. ++ * ++ *

      Commands have certain overriding behavior: ++ *

        ++ *
      • Aliases will not override already existing commands (excluding namespaced ones)
      • ++ *
      • The main command/namespaced label will override already existing commands
      • ++ *
      ++ * ++ * @param node the built literal command node ++ * @param description the help description for the root literal node ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final LiteralCommandNode node, final @Nullable String description) { ++ return this.register(node, description, Collections.emptyList()); ++ } ++ ++ /** ++ * Registers a command for the current plugin context. ++ * ++ *

      Commands have certain overriding behavior: ++ *

        ++ *
      • Aliases will not override already existing commands (excluding namespaced ones)
      • ++ *
      • The main command/namespaced label will override already existing commands
      • ++ *
      ++ * ++ * @param node the built literal command node ++ * @param aliases a collection of aliases to register the literal node's command to ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final LiteralCommandNode node, final Collection aliases) { ++ return this.register(node, null, aliases); ++ } ++ ++ /** ++ * Registers a command for the current plugin context. ++ * ++ *

      Commands have certain overriding behavior: ++ *

        ++ *
      • Aliases will not override already existing commands (excluding namespaced ones)
      • ++ *
      • The main command/namespaced label will override already existing commands
      • ++ *
      ++ * ++ * @param node the built literal command node ++ * @param description the help description for the root literal node ++ * @param aliases a collection of aliases to register the literal node's command to ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ @Unmodifiable Set register(LiteralCommandNode node, @Nullable String description, Collection aliases); ++ ++ /** ++ * Registers a command for a plugin. ++ * ++ *

      Commands have certain overriding behavior: ++ *

        ++ *
      • Aliases will not override already existing commands (excluding namespaced ones)
      • ++ *
      • The main command/namespaced label will override already existing commands
      • ++ *
      ++ * ++ * @param pluginMeta the owning plugin's meta ++ * @param node the built literal command node ++ * @param description the help description for the root literal node ++ * @param aliases a collection of aliases to register the literal node's command to ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ @Unmodifiable Set register(PluginMeta pluginMeta, LiteralCommandNode node, @Nullable String description, Collection aliases); ++ ++ /** ++ * This allows configuring the registration of your command, which is not intended for public use. ++ * See {@link Commands#register(PluginMeta, LiteralCommandNode, String, Collection)} for more information. ++ * ++ * @param pluginMeta the owning plugin's meta ++ * @param node the built literal command node ++ * @param description the help description for the root literal node ++ * @param aliases a collection of aliases to register the literal node's command to ++ * @param flags a collection of registration flags that control registration behaviour. ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ * ++ * @apiNote This method is not guaranteed to be stable as it is not intended for public use. ++ * See {@link CommandRegistrationFlag} for a more indepth explanation of this method's use-case. ++ */ ++ @ApiStatus.Internal ++ @Unmodifiable Set registerWithFlags(PluginMeta pluginMeta, LiteralCommandNode node, @Nullable String description, Collection aliases, Set flags); ++ ++ /** ++ * Registers a command under the same logic as {@link Commands#register(LiteralCommandNode, String, Collection)}. ++ * ++ * @param label the label of the to-be-registered command ++ * @param basicCommand the basic command instance to register ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final String label, final BasicCommand basicCommand) { ++ return this.register(label, null, Collections.emptyList(), basicCommand); ++ } ++ ++ /** ++ * Registers a command under the same logic as {@link Commands#register(LiteralCommandNode, String, Collection)}. ++ * ++ * @param label the label of the to-be-registered command ++ * @param description the help description for the root literal node ++ * @param basicCommand the basic command instance to register ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final String label, final @Nullable String description, final BasicCommand basicCommand) { ++ return this.register(label, description, Collections.emptyList(), basicCommand); ++ } ++ ++ /** ++ * Registers a command under the same logic as {@link Commands#register(LiteralCommandNode, String, Collection)}. ++ * ++ * @param label the label of the to-be-registered command ++ * @param aliases a collection of aliases to register the basic command under. ++ * @param basicCommand the basic command instance to register ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ default @Unmodifiable Set register(final String label, final Collection aliases, final BasicCommand basicCommand) { ++ return this.register(label, null, aliases, basicCommand); ++ } ++ ++ /** ++ * Registers a command under the same logic as {@link Commands#register(LiteralCommandNode, String, Collection)}. ++ * ++ * @param label the label of the to-be-registered command ++ * @param description the help description for the root literal node ++ * @param aliases a collection of aliases to register the basic command under. ++ * @param basicCommand the basic command instance to register ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ @Unmodifiable Set register(String label, @Nullable String description, Collection aliases, BasicCommand basicCommand); ++ ++ /** ++ * Registers a command under the same logic as {@link Commands#register(PluginMeta, LiteralCommandNode, String, Collection)}. ++ * ++ * @param pluginMeta the owning plugin's meta ++ * @param label the label of the to-be-registered command ++ * @param description the help description for the root literal node ++ * @param aliases a collection of aliases to register the basic command under. ++ * @param basicCommand the basic command instance to register ++ * @return successfully registered root command labels (including aliases and namespaced variants) ++ */ ++ @Unmodifiable Set register(PluginMeta pluginMeta, String label, @Nullable String description, Collection aliases, BasicCommand basicCommand); ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializer.java b/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..19f3dc12426be09613a13b5889f77627a81305f4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializer.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.command.brigadier; ++ ++import com.mojang.brigadier.Message; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.serializer.ComponentSerializer; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A component serializer for converting between {@link Message} and {@link Component}. ++ */ ++@ApiStatus.Experimental ++@NullMarked ++@ApiStatus.NonExtendable ++public interface MessageComponentSerializer extends ComponentSerializer { ++ ++ /** ++ * A component serializer for converting between {@link Message} and {@link Component}. ++ * ++ * @return serializer instance ++ */ ++ static MessageComponentSerializer message() { ++ return MessageComponentSerializerHolder.PROVIDER.orElseThrow(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializerHolder.java b/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializerHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2db12952461c92a64505d6646f6f49f824e83050 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/MessageComponentSerializerHolder.java +@@ -0,0 +1,12 @@ ++package io.papermc.paper.command.brigadier; ++ ++import java.util.Optional; ++import java.util.ServiceLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++@ApiStatus.Internal ++final class MessageComponentSerializerHolder { ++ ++ static final Optional PROVIDER = ServiceLoader.load(MessageComponentSerializer.class) ++ .findFirst(); ++} +diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java b/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9abb9ff33672036bb548c688c5661dc8f237aae2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java +@@ -0,0 +1,371 @@ ++package io.papermc.paper.command.brigadier.argument; ++ ++import com.mojang.brigadier.arguments.ArgumentType; ++import io.papermc.paper.command.brigadier.argument.predicate.ItemStackPredicate; ++import io.papermc.paper.command.brigadier.argument.range.DoubleRangeProvider; ++import io.papermc.paper.command.brigadier.argument.range.IntegerRangeProvider; ++import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver; ++import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; ++import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver; ++import io.papermc.paper.command.brigadier.argument.resolvers.selector.EntitySelectorArgumentResolver; ++import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; ++import io.papermc.paper.entity.LookAnchor; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.TypedKey; ++import java.util.UUID; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.Style; ++import org.bukkit.GameMode; ++import org.bukkit.HeightMap; ++import org.bukkit.NamespacedKey; ++import org.bukkit.World; ++import org.bukkit.block.BlockState; ++import org.bukkit.block.structure.Mirror; ++import org.bukkit.block.structure.StructureRotation; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.scoreboard.Criteria; ++import org.bukkit.scoreboard.DisplaySlot; ++import org.jetbrains.annotations.ApiStatus; ++import org.jspecify.annotations.NullMarked; ++ ++import static io.papermc.paper.command.brigadier.argument.VanillaArgumentProvider.provider; ++ ++/** ++ * Vanilla Minecraft includes several custom {@link ArgumentType}s that are recognized by the client. ++ * Many of these argument types include client-side completions and validation, and some include command signing context. ++ * ++ *

      This class allows creating instances of these types for use in plugin commands, with friendly API result types.

      ++ * ++ *

      {@link CustomArgumentType} is provided for customizing parsing or result types server-side, while sending the vanilla argument type to the client.

      ++ */ ++@ApiStatus.Experimental ++@NullMarked ++public final class ArgumentTypes { ++ ++ /** ++ * Represents a selector that can capture any ++ * single entity. ++ * ++ * @return argument that takes one entity ++ */ ++ public static ArgumentType entity() { ++ return provider().entity(); ++ } ++ ++ /** ++ * Represents a selector that can capture multiple ++ * entities. ++ * ++ * @return argument that takes multiple entities ++ */ ++ public static ArgumentType entities() { ++ return provider().entities(); ++ } ++ ++ /** ++ * Represents a selector that can capture a ++ * singular player entity. ++ * ++ * @return argument that takes one player ++ */ ++ public static ArgumentType player() { ++ return provider().player(); ++ } ++ ++ /** ++ * Represents a selector that can capture multiple ++ * player entities. ++ * ++ * @return argument that takes multiple players ++ */ ++ public static ArgumentType players() { ++ return provider().players(); ++ } ++ ++ /** ++ * A selector argument that provides a list ++ * of player profiles. ++ * ++ * @return player profile argument ++ */ ++ public static ArgumentType playerProfiles() { ++ return provider().playerProfiles(); ++ } ++ ++ /** ++ * A block position argument. ++ * ++ * @return block position argument ++ */ ++ public static ArgumentType blockPosition() { ++ return provider().blockPosition(); ++ } ++ ++ /** ++ * A fine position argument. ++ * ++ * @return fine position argument ++ * @see #finePosition(boolean) to center whole numbers ++ */ ++ public static ArgumentType finePosition() { ++ return finePosition(false); ++ } ++ ++ /** ++ * A fine position argument. ++ * ++ * @param centerIntegers if whole numbers should be centered (+0.5) ++ * @return fine position argument ++ */ ++ public static ArgumentType finePosition(final boolean centerIntegers) { ++ return provider().finePosition(centerIntegers); ++ } ++ ++ /** ++ * A blockstate argument which will provide rich parsing for specifying ++ * the specific block variant and then the block entity NBT if applicable. ++ * ++ * @return argument ++ */ ++ public static ArgumentType blockState() { ++ return provider().blockState(); ++ } ++ ++ /** ++ * An ItemStack argument which provides rich parsing for ++ * specifying item material and item NBT information. ++ * ++ * @return argument ++ */ ++ public static ArgumentType itemStack() { ++ return provider().itemStack(); ++ } ++ ++ /** ++ * An item predicate argument. ++ * ++ * @return argument ++ */ ++ public static ArgumentType itemPredicate() { ++ return provider().itemStackPredicate(); ++ } ++ ++ /** ++ * An argument for parsing {@link NamedTextColor}s. ++ * ++ * @return argument ++ */ ++ public static ArgumentType namedColor() { ++ return provider().namedColor(); ++ } ++ ++ /** ++ * A component argument. ++ * ++ * @return argument ++ */ ++ public static ArgumentType component() { ++ return provider().component(); ++ } ++ ++ /** ++ * A style argument. ++ * ++ * @return argument ++ */ ++ public static ArgumentType
  • ++ * This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component, ++ * java.lang.String)} with the {@link Server#BROADCAST_CHANNEL_USERS} permission. ++ * ++ * @param message the message ++ * @return the number of players ++ */ ++ public static int broadcast(net.kyori.adventure.text.@NotNull Component message) { ++ return server.broadcast(message); ++ } + /** + * Broadcasts the specified message to every user with the given + * permission name. +@@ -1236,6 +1251,21 @@ public final class Bukkit { + * permissibles} must have to receive the broadcast + * @return number of message recipients + */ ++ public static int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission) { ++ return server.broadcast(message, permission); ++ } ++ // Paper end ++ /** ++ * Broadcasts the specified message to every user with the given ++ * permission name. ++ * ++ * @param message message to broadcast ++ * @param permission the required permission {@link Permissible ++ * permissibles} must have to receive the broadcast ++ * @return number of message recipients ++ * @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)} ++ */ ++ @Deprecated // Paper + public static int broadcast(@NotNull String message, @NotNull String permission) { + return server.broadcast(message, permission); + } +@@ -1497,6 +1527,7 @@ public final class Bukkit { + return server.createInventory(owner, type); + } + ++ // Paper start + /** + * Creates an empty inventory with the specified type and title. If the type + * is {@link InventoryType#CHEST}, the new inventory has a size of 27; +@@ -1522,6 +1553,38 @@ public final class Bukkit { + * @see InventoryType#isCreatable() + */ + @NotNull ++ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title) { ++ return server.createInventory(owner, type, title); ++ } ++ // Paper end ++ ++ /** ++ * Creates an empty inventory with the specified type and title. If the type ++ * is {@link InventoryType#CHEST}, the new inventory has a size of 27; ++ * otherwise the new inventory has the normal size for its type.
    ++ * It should be noted that some inventory types do not support titles and ++ * may not render with said titles on the Minecraft client. ++ *
    ++ * {@link InventoryType#WORKBENCH} will not process crafting recipes if ++ * created with this method. Use ++ * {@link Player#openWorkbench(Location, boolean)} instead. ++ *
    ++ * {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s ++ * for possible enchanting results. Use ++ * {@link Player#openEnchanting(Location, boolean)} instead. ++ * ++ * @param owner The holder of the inventory; can be null if there's no holder. ++ * @param type The type of inventory to create. ++ * @param title The title of the inventory, to be displayed when it is viewed. ++ * @return The new inventory. ++ * @throws IllegalArgumentException if the {@link InventoryType} cannot be ++ * viewed. ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} ++ * ++ * @see InventoryType#isCreatable() ++ */ ++ @Deprecated // Paper ++ @NotNull + public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { + return server.createInventory(owner, type, title); + } +@@ -1540,6 +1603,7 @@ public final class Bukkit { + return server.createInventory(owner, size); + } + ++ // Paper start + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. +@@ -1552,10 +1616,30 @@ public final class Bukkit { + * @throws IllegalArgumentException if the size is not a multiple of 9 + */ + @NotNull ++ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException { ++ return server.createInventory(owner, size, title); ++ } ++ // Paper end ++ ++ /** ++ * Creates an empty inventory of type {@link InventoryType#CHEST} with the ++ * specified size and title. ++ * ++ * @param owner the holder of the inventory, or null to indicate no holder ++ * @param size a multiple of 9 as the size of inventory to create ++ * @param title the title of the inventory, displayed when inventory is ++ * viewed ++ * @return a new inventory ++ * @throws IllegalArgumentException if the size is not a multiple of 9 ++ * @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ @NotNull + public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException { + return server.createInventory(owner, size, title); + } + ++ // Paper start + /** + * Creates an empty merchant. + * +@@ -1563,7 +1647,20 @@ public final class Bukkit { + * when the merchant inventory is viewed + * @return a new merchant + */ ++ public static @NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title) { ++ return server.createMerchant(title); ++ } ++ // Paper start ++ /** ++ * Creates an empty merchant. ++ * ++ * @param title the title of the corresponding merchant inventory, displayed ++ * when the merchant inventory is viewed ++ * @return a new merchant ++ * @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)} ++ */ + @NotNull ++ @Deprecated // Paper + public static Merchant createMerchant(@Nullable String title) { + return server.createMerchant(title); + } +@@ -1680,12 +1777,43 @@ public final class Bukkit { + return server.isPrimaryThread(); + } + ++ // Paper start ++ /** ++ * Gets the message that is displayed on the server list. ++ * ++ * @return the server's MOTD ++ */ ++ @NotNull public static net.kyori.adventure.text.Component motd() { ++ return server.motd(); ++ } ++ ++ /** ++ * Set the message that is displayed on the server list. ++ * ++ * @param motd The message to be displayed ++ */ ++ public static void motd(final net.kyori.adventure.text.@NotNull Component motd) { ++ server.motd(motd); ++ } ++ ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ */ ++ public static net.kyori.adventure.text.@Nullable Component shutdownMessage() { ++ return server.shutdownMessage(); ++ } ++ // Paper end ++ + /** + * Gets the message that is displayed on the server list. + * + * @return the servers MOTD ++ * @deprecated in favour of {@link #motd()} + */ + @NotNull ++ @Deprecated // Paper + public static String getMotd() { + return server.getMotd(); + } +@@ -1694,7 +1822,9 @@ public final class Bukkit { + * Set the message that is displayed on the server list. + * + * @param motd The message to be displayed ++ * @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)} + */ ++ @Deprecated // Paper + public static void setMotd(@NotNull String motd) { + server.setMotd(motd); + } +@@ -1714,8 +1844,10 @@ public final class Bukkit { + * Gets the default message that is displayed when the server is stopped. + * + * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} + */ + @Nullable ++ @Deprecated // Paper + public static String getShutdownMessage() { + return server.getShutdownMessage(); + } +diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java +index e3f185dc982d1c38195a4e01ddd485c13ffa58c0..918a045165cdcde264bc24082b7afebb407271de 100644 +--- a/src/main/java/org/bukkit/ChatColor.java ++++ b/src/main/java/org/bukkit/ChatColor.java +@@ -10,7 +10,9 @@ import org.jetbrains.annotations.Nullable; + + /** + * All supported color values for chat ++ * @deprecated ChatColor has been deprecated in favor of
    Adventure API. See {@link net.kyori.adventure.text.format.NamedTextColor} for the adventure equivalent of pre-defined text colors + */ ++@Deprecated // Paper + public enum ChatColor { + /** + * Represents black +diff --git a/src/main/java/org/bukkit/JukeboxSong.java b/src/main/java/org/bukkit/JukeboxSong.java +index 5872188c2f3c610ab220a30cf60f45c1eba1b372..c6feb13c735fabbd08676fa8828ce0b9fd54da32 100644 +--- a/src/main/java/org/bukkit/JukeboxSong.java ++++ b/src/main/java/org/bukkit/JukeboxSong.java +@@ -33,4 +33,14 @@ public interface JukeboxSong extends Keyed, Translatable { + private static JukeboxSong get(@NotNull String key) { + return Registry.JUKEBOX_SONG.getOrThrow(NamespacedKey.minecraft(key)); + } ++ ++ // Paper start - adventure ++ /** ++ * @deprecated this method assumes that jukebox song description will ++ * always be a translatable component which is not guaranteed. ++ */ ++ @Override ++ @Deprecated(forRemoval = true) ++ @org.jetbrains.annotations.NotNull String getTranslationKey(); ++ // Paper end - adventure + } +diff --git a/src/main/java/org/bukkit/Keyed.java b/src/main/java/org/bukkit/Keyed.java +index 32c92621c2c15eec14c50965f5ecda00c46e6c80..e076d447da62445764a9776ee2554c077637d270 100644 +--- a/src/main/java/org/bukkit/Keyed.java ++++ b/src/main/java/org/bukkit/Keyed.java +@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; + /** + * Represents an object which has a {@link NamespacedKey} attached to it. + */ +-public interface Keyed { ++public interface Keyed extends net.kyori.adventure.key.Keyed { // Paper -- extend Adventure Keyed + + /** + * Return the namespaced identifier for this object. +@@ -14,4 +14,16 @@ public interface Keyed { + */ + @NotNull + NamespacedKey getKey(); ++ ++ // Paper start ++ /** ++ * Returns the unique identifier for this object. ++ * ++ * @return this object's key ++ */ ++ @Override ++ default net.kyori.adventure.key.@NotNull Key key() { ++ return this.getKey(); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/Nameable.java b/src/main/java/org/bukkit/Nameable.java +index b79daa857fc686f00ac06b8851e0ab68d83ae949..45d996878ba8d314a47078589b6da59dc84d589e 100644 +--- a/src/main/java/org/bukkit/Nameable.java ++++ b/src/main/java/org/bukkit/Nameable.java +@@ -7,6 +7,30 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Nameable { + ++ // Paper start ++ /** ++ * Gets the custom name. ++ * ++ *