Compare commits

..
Author SHA1 Message Date
Nassim Jahnke 1e8f878304 Mark publish fill as incompatible with config cache 2026-09-27 20:51:15 +02:00
Nassim Jahnke 28007ff9ca revert build.yaml for now 2026-09-27 20:42:36 +02:00
Nassim Jahnke 8075884fb2 Manually pre-define initial build number 2026-09-27 20:38:10 +02:00
Nassim Jahnke 2e1d2f2f11 Fetch git history for release workflow 2026-09-27 18:20:40 +02:00
Nassim Jahnke 0173bf2600 Small fixes
todo: maybe use different runner for PR
2026-09-27 17:54:52 +02:00
Riley Park 908605f2ce work 2026-09-26 21:27:12 -07:00
Riley Park e37089f835 work 2026-09-26 14:57:34 -07:00
Riley Park 14c0f269b5 chore: build on github actions 2026-09-25 17:12:21 -07:00
Jason Penilla a15fed9c16 Update Gradle to 9.8 and paperweight to beta.24 2026-09-24 20:24:50 -07:00
Wouter Gritter beac08f83f Don't pre-cancel AsyncPlayerSendSuggestionsEvent on empty suggestions (#14294) 2026-09-24 08:17:28 +02:00
Pedro f8a210f1d7 Fix exception when Cushion is in fluids (#14296) 2026-09-24 08:15:51 +02:00
HPnetwork d5cc7d4af8 Fix yaw wraparound in movement event checks (#14262) 2026-09-23 20:15:01 +02:00
Owen1212055 217fb92a10 Check target container in transport behavior 2026-09-23 20:11:17 +02:00
Creeam 327052edf4 Fix pathfinder comparator being inverted (#14292) 2026-09-23 18:23:31 +02:00
Nassim Jahnke e1f150a5eb Add back missing suggestions event call 2026-09-23 17:14:46 +02:00
Pedroandmastermc05 dd9d1031f0 Add Post Effect API (#14267)
Co-authored-by: mastermc05 <63639746+mastermc05@users.noreply.github.com>
2026-09-22 16:18:05 -03:00
Spottedleaf dfbf6f4183 Rebase fixups 2026-09-22 09:19:43 -07:00
Spottedleaf e863872fab Avoid copying LevelChunkSection data when unloading chunks
See https://github.com/Tuinity/Moonrise/commit/9516c499fd5e78eb5682180e7ba6b073c5a0c989
2026-09-22 08:57:10 -07:00
Spottedleaf 298732599a Remove unloaded chunk holders from broadcast set
See https://github.com/Tuinity/Moonrise/commit/d57318284619023ed5d1568cd286dd91ffe3eeae
2026-09-22 08:57:09 -07:00
Spottedleaf be3fe45d6e Do not copy NBT data in RegionFile I/O when not needed
See https://github.com/Tuinity/Moonrise/commit/e8def77d12fa2ef7b549acc5e1c37021c2781533
2026-09-22 08:57:09 -07:00
Spottedleaf f759838b85 Reduce allocations from PalettedContainer#pack
See https://github.com/Tuinity/Moonrise/commit/f22e132c84aae06cdf1bd5fea0aad65eb4c306cf
2026-09-22 08:57:09 -07:00
PedroandPantera 18f05bb815 Fix weather clear desync on player respawn (#14291)
Co-authored-by: Pantera <89838384+pantera07@users.noreply.github.com>
2026-09-22 15:22:43 +02:00
Nassim Jahnke 0c803ba1fa Fix missing is_tempted memory removal 2026-09-21 19:04:29 +02:00
Nassim Jahnke 6db70e070a Length checks 2026-09-21 18:56:19 +02:00
Doc a22040d53c Fix Player#applyMending for custom items using max_damage (#14276) 2026-09-21 10:51:53 -03:00
Nassim Jahnke c13e3c9f0a oops 2026-09-21 09:43:15 +02:00
Nassim Jahnke baa0d82f7c Call EntityPlaceEvent for cushions 2026-09-21 09:42:02 +02:00
Nassim Jahnke 93c9b2ab1f Fix inlined block state conversion 2026-09-20 21:02:19 +02:00
Wouter GritterandNassim Jahnke e6e9780e32 Initialize lagCompensationTick correctly (#14285)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-09-20 20:49:46 +02:00
Doc a255185980 Call EntityCollideWithEntityEvent for Sulfur Cube pushed by Player (#14157) 2026-09-19 23:42:40 -03:00
Lulu13022002 98e0678512 tweaks deprecated warnings behavior on event 2026-09-19 21:44:35 +02:00
Strokkur24 9838b40808 Add SulfurCube#swallow (#14062) 2026-09-19 15:05:29 -03:00
103 changed files with 1238 additions and 978 deletions

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ indent_style = tab
[*.bat]
end_of_line = crlf
[*.yml]
[{*.yaml,*.yml}]
indent_size = 2
[{*.patch,*.md}]
@@ -107,7 +107,7 @@ jobs:
if: always()
uses: actions/upload-artifact@v7
with:
name: Test Results
name: test-results
path: |
**/build/test-results/test/TEST-*.xml
@@ -137,12 +137,12 @@ jobs:
publishing-task: ":paper-api:publishAllPublicationsTo_githubPackages_PRsRepository publishDevBundlePublicationTo_githubPackages_PRsRepository -PpublishDevBundle"
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 }}
needs: build
if: ${{ !cancelled() && needs.build.result != 'skipped' }}
runs-on: ubuntu-latest
steps:
- name: Upload
uses: actions/upload-artifact@v7
with:
name: Event File
name: event-data
path: ${{ github.event_path }}
+6 -2
View File
@@ -2,7 +2,11 @@ name: Close invalid PRs
on:
pull_request_target:
types: [ opened ]
types:
- opened
permissions:
pull-requests: write
jobs:
run:
@@ -12,7 +16,7 @@ jobs:
github.head_ref == 'main' ||
github.event.pull_request.head.repo.owner.type != 'User'
)
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- uses: superbrothers/close-pull-request@v3
id: "main_branch"
+1 -1
View File
@@ -9,6 +9,6 @@ permissions: {}
jobs:
signal:
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- run: echo "A PR review was submitted"
+2 -2
View File
@@ -22,7 +22,7 @@ jobs:
concurrency:
group: pr-review-status-${{ github.event.workflow_run.head_sha }}
cancel-in-progress: false
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- name: "authenticate"
id: "authenticate"
@@ -48,7 +48,7 @@ jobs:
concurrency:
group: pr-review-status-promote
cancel-in-progress: false
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- name: "authenticate"
id: "authenticate"
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
concurrency:
group: update-bugs-project-${{ github.event.issue.number }}
cancel-in-progress: true
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- name: "authenticate"
id: "authenticate"
+1 -1
View File
@@ -15,7 +15,7 @@ permissions:
jobs:
publish:
runs-on: ubuntu-latest
runs-on: namespace-profile-linux-small
steps:
- name: Generate an Application repository access token
id: gen_repo_token
+43
View File
@@ -0,0 +1,43 @@
name: Release 26.3
on:
push:
branches:
- main
permissions:
contents: read
concurrency:
group: release-26.3
cancel-in-progress: false
jobs:
release:
runs-on: namespace-profile-linux-default
timeout-minutes: 30
#env:
# BUILD_NUMBER: ${{ github.run_number }}
steps:
- name: "git / checkout"
uses: namespacelabs/nscloud-checkout-action@66f2dc6f6c42a8ac6c4e53473c4840006822831e # v9.0.1
with:
fetch-depth: 0
- uses: papermc/ci/setup-gradle@main
- name: "build number"
run: echo "BUILD_NUMBER=$((129 + GITHUB_RUN_NUMBER))" >> "$GITHUB_ENV"
- uses: papermc/ci/build-paper@main
- if: ${{ !cancelled() }}
uses: papermc/ci/upload-test-results@main
- uses: papermc/ci/publish-paper@main
with:
fill_api_url: ${{ secrets.FILL_API_URL }}
fill_api_key: ${{ secrets.FILL_API_KEY }}
maven_username: ${{ secrets.ARTIFACTORY_USERNAME }}
maven_password: ${{ secrets.ARTIFACTORY_PASSWORD }}
maven_tasks: :paper-api:publish publishDevBundlePublicationToPaperReleasesRepository
+24
View File
@@ -0,0 +1,24 @@
name: Test Results
on:
workflow_run:
workflows: [ "Build Paper" ]
types:
- completed
permissions:
actions: read
checks: write
jobs:
test-results:
name: Test Results
if: github.event.workflow_run.conclusion != 'skipped'
runs-on: namespace-profile-linux-small
steps:
- uses: papermc/ci/publish-test-results@main
with:
event: ${{ github.event.workflow_run.event }}
commit: ${{ github.event.workflow_run.head_sha }}
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ github.event.workflow_run.id }}
-34
View File
@@ -1,34 +0,0 @@
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@v21
with:
run_id: ${{ github.event.workflow_run.id }}
path: test_artifacts
name: "Test Results|Event File"
name_is_regexp: true
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
commit: ${{ github.event.workflow_run.head_sha }}
event_file: test_artifacts/Event File/event.json
event_name: ${{ github.event.workflow_run.event }}
files: "test_artifacts/**/*.xml"
comment_mode: off
+1 -1
View File
@@ -4,7 +4,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins {
id("io.papermc.paperweight.core") version "2.0.0-beta.23" apply false
id("io.papermc.paperweight.core") version "2.0.0-beta.24" apply false
}
subprojects {
Binary file not shown.
+3 -1
View File
@@ -1,7 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.0-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+3 -3
View File
@@ -20,7 +20,7 @@
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
# gradlew start up script for POSIX generated by Gradle.
#
# Important for running:
#
@@ -29,7 +29,7 @@
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
# ksh gradlew
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/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/.
Vendored
+52 -33
View File
@@ -19,12 +19,39 @@
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem gradlew startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
@rem Catch executions from older scripts and ensure they exit cleanly.
@rem This can be removed once we can be reasonably confident that few people
@rem will be migrating directly to this new wrapper.
goto afterSafetyNet
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto exitWithErrorLevel
:afterSafetyNet
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@@ -45,13 +72,14 @@ 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
1>&2 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.
goto fail
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,35 +87,26 @@ 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
1>&2 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.
goto fail
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:execute
@rem Setup the command line
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
@rem Execute gradlew
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
: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
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
+3 -3
View File
@@ -28,11 +28,11 @@ val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21"
val slf4jVersion = "2.0.17"
val log4jVersion = "2.26.0"
val apiAndDocs: Configuration by configurations.creating
val apiAndDocs: Configuration = configurations.create("apiAndDocs")
configurations.api {
extendsFrom(apiAndDocs)
}
val javadocSourcepath: Configuration by configurations.creating {
val javadocSourcepath: Configuration = configurations.create("javadocSourcepath") {
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
@@ -251,7 +251,7 @@ tasks.compileTestJava {
options.compilerArgs.add("-parameters")
}
val scanJarForBadCalls by tasks.registering(io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
val scanJarForBadCalls = tasks.register<io.papermc.paperweight.tasks.ScanJarForBadCalls>("scanJarForBadCalls") {
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
classpath.from(configurations.compileClasspath)
@@ -1,6 +1,7 @@
package com.destroystokyo.paper.event.block;
import org.bukkit.Material;
import org.bukkit.Warning;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
@@ -23,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated use {@link org.bukkit.event.block.TNTPrimeEvent}
*/
@Deprecated(forRemoval = true, since = "1.19.4")
@Warning(propagate = false)
public class TNTPrimeEvent extends BlockEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -13,6 +13,8 @@ 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.
* <p>
* If the suggestions are empty after this event has been called, nothing will be sent to the client.
*/
@NullMarked
public class AsyncPlayerSendSuggestionsEvent extends PlayerEvent implements Cancellable {
@@ -51,6 +53,8 @@ public class AsyncPlayerSendSuggestionsEvent extends PlayerEvent implements Canc
/**
* Sets the suggestions to be sent to client.
* <p>
* Empty suggestions are never sent to the client.
*
* @param suggestions suggestions
*/
@@ -18,10 +18,11 @@ import org.jetbrains.annotations.NotNull;
* 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.</p>
*
* @deprecated For removal, use the new brigadier api.
* @deprecated this event has been superseded by the Commands API and will be removed in a future release.
* Listen to {@link io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents#COMMANDS} instead
*/
@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)
@Warning(value = true, propagate = false)
public class CommandRegisteredEvent<S extends com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource> extends ServerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -1,5 +1,6 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Warning;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Cancellable;
@@ -17,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated Deprecated, use {@link org.bukkit.event.entity.ProjectileHitEvent} and check if there is a hit entity
*/
@Deprecated(since = "1.19.3")
@Warning(propagate = false)
public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated use {@link org.bukkit.event.inventory.PrepareGrindstoneEvent}
*/
@Deprecated(since = "1.16.1")
@Warning
@Warning(propagate = false)
public class PrepareGrindstoneEvent extends PrepareResultEvent {
@ApiStatus.Internal
@@ -1,5 +1,6 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Warning;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
@@ -11,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated Not used
*/
@Deprecated(since = "1.16.4", forRemoval = true)
@Warning(value = true, propagate = false)
public class IllegalPacketEvent extends PlayerEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -1,5 +1,6 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Warning;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
@@ -19,6 +20,7 @@ import org.jspecify.annotations.NullMarked;
*/
@NullMarked
@Deprecated(since = "26.1", forRemoval = true)
@Warning(value = true, propagate = false)
public class PlayerAttackEntityCooldownResetEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -6,11 +6,9 @@ import io.papermc.paper.datacomponent.item.AttackRange;
import io.papermc.paper.datacomponent.item.BannerPatternLayers;
import io.papermc.paper.datacomponent.item.BlockItemDataProperties;
import io.papermc.paper.datacomponent.item.BlocksAttacks;
import io.papermc.paper.datacomponent.item.BrewingFuel;
import io.papermc.paper.datacomponent.item.BundleContents;
import io.papermc.paper.datacomponent.item.ChargedProjectiles;
import io.papermc.paper.datacomponent.item.Consumable;
import io.papermc.paper.datacomponent.item.CookingFuel;
import io.papermc.paper.datacomponent.item.CustomModelData;
import io.papermc.paper.datacomponent.item.DamageResistant;
import io.papermc.paper.datacomponent.item.DeathProtection;
@@ -403,14 +401,6 @@ public final class DataComponentTypes {
public static final DataComponentType.Valued<SignText> SIGN_TEXT_BACK = valued("sign_text_back");
public static final DataComponentType.NonValued WAXED = unvalued("waxed");
public static final DataComponentType.Valued<DyeColor> CUSHION_COLOR = valued("cushion/color");
/**
* Describes an item that can be used as fuel for a furnace, smoker or blast furnace.
*/
public static final DataComponentType.Valued<CookingFuel> COOKING_FUEL = valued("cooking_fuel");
/**
* Describes an item that can be used as fuel for a brewing stand.
*/
public static final DataComponentType.Valued<BrewingFuel> BREWING_FUEL = valued("brewing_fuel");
private static DataComponentType.NonValued unvalued(@KeyPattern.Value final String key) {
final DataComponentType dataComponentType = Registry.DATA_COMPONENT_TYPE.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
@@ -1,56 +0,0 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.loot.number.ResolvableFloat;
import io.papermc.paper.loot.number.ResolvableInt;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* Describes an item that can be used as fuel for a brewing stand.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BREWING_FUEL
*/
@ApiStatus.NonExtendable
public interface BrewingFuel {
@Contract(value = "-> new", pure = true)
static BrewingFuel.Builder brewingFuel() {
return ItemComponentTypesBridge.bridge().brewingFuel();
}
/**
* @return the number of times this fuel will brew before being consumed
*/
@Contract(pure = true)
ResolvableInt uses();
/**
* @return the speed of the brewing
*/
@Contract(pure = true)
ResolvableFloat speedMultiplier();
/**
* Builder for {@link BrewingFuel}.
*/
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<BrewingFuel> {
/**
* @param uses the number of times this fuel will brew before being consumed
* @return the builder for chaining
* @see #uses()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder uses(int uses);
/**
* @param speedMultiplier the speed of the brewing
* @return the builder for chaining
* @see #speedMultiplier()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder speedMultiplier(float speedMultiplier);
}
}
@@ -1,56 +0,0 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.loot.number.ResolvableFloat;
import io.papermc.paper.loot.number.ResolvableInt;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* Describes an item that can be used as fuel for a furnace, smoker or blast furnace.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#COOKING_FUEL
*/
@ApiStatus.NonExtendable
public interface CookingFuel {
@Contract(value = "-> new", pure = true)
static CookingFuel.Builder cookingFuel() {
return ItemComponentTypesBridge.bridge().cookingFuel();
}
/**
* @return the time, in ticks, for which this fuel will burn
*/
@Contract(pure = true)
ResolvableInt burnTime();
/**
* @return the speed of the cooking/smelting
*/
@Contract(pure = true)
ResolvableFloat speedMultiplier();
/**
* Builder for {@link CookingFuel}.
*/
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<CookingFuel> {
/**
* @param speedMultiplier the speed of the cooking/smelting
* @return the builder for chaining
* @see #speedMultiplier()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder speedMultiplier(float speedMultiplier);
/**
* @param burnTime the time, in ticks, for which this fuel will burn
* @return the builder for chaining
* @see #speedMultiplier()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder burnTime(int burnTime);
}
}
@@ -131,8 +131,4 @@ interface ItemComponentTypesBridge {
VillagerFood villagerFood(int nutrition);
SignText.Builder signText();
BrewingFuel.Builder brewingFuel();
CookingFuel.Builder cookingFuel();
}
@@ -0,0 +1,55 @@
package io.papermc.paper.entity;
import java.util.List;
import java.util.SequencedCollection;
import net.kyori.adventure.key.Key;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
/**
* Represents the post-effects that can be applied to a player.
* @see <a href="https://minecraft.wiki/w/Shader#Post-processing_effects">Post-Effects - Minecraft Wiki</a>
*/
@NullMarked
public interface PlayerPostEffects {
/**
* Gets the list of post-effects that are currently applied to the player.
*
* @return an unmodifiable list of post-effects
*/
@Unmodifiable
List<Key> values();
/**
* Sets the list of post-effects that are currently applied to the player.
*
* @param postEffects the list of post-effects to set
* @return true if the post-effects were changed, false if they were the same
*/
boolean set(SequencedCollection<Key> postEffects);
/**
* Adds a post-effect to the player.
*
* @param effect the key post-effect to add
* @return true if the post-effect was added, false if it was already present
*/
boolean add(Key effect);
/**
* Removes a post-effect from the player.
*
* @param effect the key post-effect to remove
* @return true if the post-effect was removed, false if it was not present
*/
boolean remove(Key effect);
/**
* Clears all post-effects from the player.
*
* @return true if any post-effects were cleared, false if there were none
*/
boolean clear();
}
@@ -1,5 +1,6 @@
package io.papermc.paper.event.block;
import org.bukkit.Warning;
import org.bukkit.block.Block;
import org.bukkit.entity.Raider;
import org.bukkit.event.Cancellable;
@@ -14,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link org.bukkit.event.block.BellResonateEvent}
*/
@Deprecated(since = "1.19.4")
@Warning(propagate = false)
public class BellRevealRaiderEvent extends BlockEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -1,5 +1,6 @@
package io.papermc.paper.event.block;
import org.bukkit.Warning;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
@@ -13,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated use {@link org.bukkit.event.block.BellRingEvent}
*/
@Deprecated(since = "1.19.4")
@Warning(propagate = false)
public class BellRingEvent extends org.bukkit.event.block.BellRingEvent {
@ApiStatus.Internal
@@ -1,12 +1,12 @@
package io.papermc.paper.event.entity;
import java.util.List;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import org.jspecify.annotations.NullMarked;
/**
* Fired when two entities collide with each other.
@@ -15,6 +15,7 @@ import java.util.List;
* Note that even if cancelled, the client may still run its own collision unless
* disabled via player teams.
*/
@NullMarked
public class EntityCollideWithEntityEvent extends Event implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -22,8 +23,8 @@ public class EntityCollideWithEntityEvent extends Event implements Cancellable {
private final List<Entity> entities;
@ApiStatus.Internal
public EntityCollideWithEntityEvent(@NotNull Entity entity1, @NotNull Entity entity2) {
entities = List.of(entity1, entity2);
public EntityCollideWithEntityEvent(final Entity entity1, final Entity entity2) {
this.entities = List.of(entity1, entity2);
}
/**
@@ -31,23 +32,22 @@ public class EntityCollideWithEntityEvent extends Event implements Cancellable {
*
* @return entities that are involved in this event
*/
public @NotNull List<Entity> getEntities() {
return entities;
public List<Entity> getEntities() {
return this.entities;
}
@Override
public @NotNull HandlerList getHandlers() {
public HandlerList getHandlers() {
return HANDLER_LIST;
}
@NotNull
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
@Override
public boolean isCancelled() {
return cancelled;
return this.cancelled;
}
@Override
@@ -18,7 +18,7 @@ import org.jspecify.annotations.NullMarked;
* 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.")
@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.", propagate = false)
@NullMarked
public final class ChatEvent extends AbstractChatEvent {
@@ -1,37 +0,0 @@
package io.papermc.paper.loot.number;
import org.bukkit.loot.LootContext;
/**
* Represents a floating point number that can be resolved against a {@link LootContext}.
*/
public interface ResolvableFloat {
/**
* Resolves this floating point number against the given loot context.
*
* @param context the loot context to resolve against.
* @param defaultValue the default value
* @return the resolved number
*/
float resolve(LootContext context, float defaultValue);
/**
* Represents a constant {@link ResolvableFloat}.
*/
interface Constant extends ResolvableFloat {
/**
* @return the constant value
*/
float getValue();
/**
* {@inheritDoc}
*/
@Override
default float resolve(LootContext context, float defaultValue) {
return this.getValue();
}
}
}
@@ -1,37 +0,0 @@
package io.papermc.paper.loot.number;
import org.bukkit.loot.LootContext;
/**
* Represents an integer number that can be resolved against a {@link LootContext}.
*/
public interface ResolvableInt {
/**
* Resolves this integer number against the given loot context.
*
* @param context the loot context to resolve against.
* @param defaultValue the default value
* @return the resolved number
*/
int resolve(LootContext context, int defaultValue);
/**
* Represents a constant {@link ResolvableInt}.
*/
interface Constant extends ResolvableInt {
/**
* @return the constant value
*/
int getValue();
/**
* {@inheritDoc}
*/
@Override
default int resolve(LootContext context, int defaultValue) {
return this.getValue();
}
}
}
@@ -1,9 +0,0 @@
/**
* Package containing maths-related API, including position API.
*/
@NullMarked
@ApiStatus.Experimental
package io.papermc.paper.loot.number;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@@ -23,7 +23,7 @@ public @interface Warning {
/**
* This represents the states that server verbose for warnings may be.
*/
public enum WarningState {
enum WarningState {
/**
* Indicates all warnings should be printed for deprecated items.
@@ -100,14 +100,23 @@ public @interface Warning {
* This sets if the deprecation warnings when registering events gets
* printed when the setting is in the default state.
*
* @return false normally, or true to encourage warning printout
* @return {@code false} normally, or {@code true} to encourage warning printout
*/
boolean value() default false;
/**
* This can provide detailed information on why the event is deprecated.
*
* @return The reason an event is deprecated
* @return the reason an event is deprecated
*/
String reason() default "";
/**
* This indicate if the deprecation warnings should propagate to sub events or not.
* The default is {@code true} only to maintains compatibility but it's recommended
* to use {@code false} for more explicit behavior.
*
* @return whether to propagate the deprecation warnings
*/
boolean propagate() default true;
}
@@ -5,6 +5,7 @@ import com.google.common.base.Preconditions;
import io.papermc.paper.connection.PlayerGameConnection;
import io.papermc.paper.entity.LookAnchor;
import io.papermc.paper.entity.PlayerGiveResult;
import io.papermc.paper.entity.PlayerPostEffects;
import io.papermc.paper.math.Angle;
import io.papermc.paper.math.Position;
import java.net.InetAddress;
@@ -4076,4 +4077,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* clearing any fixed pose in the process.
*/
void unsetFixedPose();
/**
* Gets the post-effects that can be applied to this player.
*
* @return the post-effects
*/
PlayerPostEffects postEffects();
}
@@ -1,12 +1,17 @@
package org.bukkit.entity;
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
import io.papermc.paper.entity.Bucketable;
import io.papermc.paper.entity.Shearable;
import io.papermc.paper.event.entity.EntityEquipmentChangedEvent;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.keys.tags.ItemTypeTagKeys;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.KeyPattern;
import org.bukkit.Keyed;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jspecify.annotations.NullMarked;
/**
@@ -73,6 +78,58 @@ public interface SulfurCube extends AbstractCubeMob, Shearable, Bucketable, Agea
return this.ignite(false);
}
/**
* Makes this sulfur cube swallow the provided item, following any Vanilla logic.
* <p>
* This method will:
* <ul>
* <li>not equip the item to a baby sulfur cube,</li>
* <li>if present, drop a previously swallowed item, and</li>
* <li>play the swallow sound.</li>
* </ul>
* <p>
* If the currently swallowed item is changed, a {@link EntityEquipmentChangedEvent} is called.
* May also call a {@link EntityAddToWorldEvent} for the newly dropped {@link Item} entity.
*
* @param itemStack the item to swallow. Use {@link ItemStack#empty()} to unset the item.
* Items not in the {@link ItemTypeTagKeys#SULFUR_CUBE_SWALLOWABLE} tag
* will not be properly rendered inside the sulfur cube
* @return whether the sulfur cube's absorbed item was updated
* @see #setEquipped(ItemStack) set the swallowed item, skipping any Vanilla swallow logic
*/
boolean swallow(ItemStack itemStack);
/**
* Sets the swallowed item stack for this sulfur cube.
* <p>
* This method acts as a simple utility method to set the {@link EquipmentSlot#BODY}
* equipment slot of this sulfur cube, which holds the sulfur cube's swallowed item.
* <p>
* Different to {@link #swallow(ItemStack)}, this method does not play a sound or
* drop the previously equipped item on the ground.
* <p>
* This method will call a {@link EntityEquipmentChangedEvent}.
*
* @param itemStack the item stack to be equipped, use {@link ItemStack#empty()} to unset the item
* @see #swallow(ItemStack) set the swallowed item, following any Vanilla swallow logic
*/
default void setEquipped(final ItemStack itemStack) {
this.getEquipment().setItem(EquipmentSlot.BODY, itemStack);
}
/**
* Retrieves the item stack currently swallowed by this sulfur cube.
* <p>
* This method acts as a simple utility method to get the {@link EquipmentSlot#BODY}
* equipment slot of this sulfur cube, which holds the sulfur cube's swallowed item.
*
* @return the item stack in the {@link EquipmentSlot#BODY} equipment slot, returns {@link ItemStack#empty()}
* if no item is present
*/
default ItemStack getEquipped() {
return this.getEquipment().getItem(EquipmentSlot.BODY);
}
/**
* Represents the archetype of a sulfur cube
* which define a lot of possible behavior and interaction
@@ -2,6 +2,7 @@ package org.bukkit.event.entity;
import java.util.List;
import org.bukkit.PortalType;
import org.bukkit.Warning;
import org.bukkit.block.BlockState;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Cancellable;
@@ -16,6 +17,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated Use {@link PortalCreateEvent}
*/
@Deprecated(since = "1.14.1")
@Warning(propagate = false)
public class EntityCreatePortalEvent extends EntityEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -1,5 +1,6 @@
package org.bukkit.event.entity;
import org.bukkit.Warning;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
@@ -12,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent}
*/
@Deprecated(forRemoval = true) // Paper
@Warning(propagate = false)
public class EntityKnockbackByEntityEvent extends EntityKnockbackEvent {
private final Entity source;
@@ -1,6 +1,7 @@
package org.bukkit.event.entity;
import com.google.common.base.Preconditions;
import org.bukkit.Warning;
import org.bukkit.attribute.Attribute;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
@@ -16,6 +17,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link io.papermc.paper.event.entity.EntityKnockbackEvent}
*/
@Deprecated(forRemoval = true) // Paper
@Warning(propagate = false)
public class EntityKnockbackEvent extends EntityEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link EntityZapEvent}
*/
@Deprecated(since = "26.2")
@Warning(reason = "This event has become obsolete, the more generic EntityZapEvent should be used instead.")
@Warning(propagate = false)
public class PigZapEvent extends EntityZapEvent {
@ApiStatus.Internal
@@ -13,7 +13,8 @@ import org.jetbrains.annotations.Nullable;
*
* @deprecated use {@link com.destroystokyo.paper.event.inventory.PrepareResultEvent}
*/
@Deprecated @Warning
@Deprecated
@Warning(propagate = false)
public class PrepareInventoryResultEvent extends InventoryEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead
*/
@Deprecated
@Warning(reason = "Don't nag on old event yet") // Paper
@Warning(propagate = false)
public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated chat previews have been removed
*/
@Deprecated(since = "1.19.1")
@Warning
@Warning(value = true, propagate = false)
public class AsyncPlayerChatPreviewEvent extends AsyncPlayerChatEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -1,5 +1,6 @@
package org.bukkit.event.player;
import org.bukkit.Warning;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
@@ -12,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link io.papermc.paper.event.player.PlayerArmSwingEvent}
*/
@Deprecated(since = "26.3")
@Warning(propagate = false)
public class PlayerAnimationEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated Use the more generic {@link PlayerBucketEntityEvent}
*/
@Deprecated(since = "1.16.5")
@Warning
@Warning(propagate = false)
public class PlayerBucketFishEvent extends PlayerBucketEntityEvent {
@ApiStatus.Internal
@@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull;
* @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.")
@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.", value = true, propagate = false)
public class PlayerChatEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated This event is no longer fired due to client changes
*/
@Deprecated(since = "1.13")
@Warning(reason = "This event is no longer fired due to client changes")
@Warning(reason = "This event is no longer fired due to client changes", value = true, propagate = false)
public class PlayerChatTabCompleteEvent extends PlayerEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
* Additionally, this event causes the full player entity to be created much earlier than it would be in Vanilla,
* leaving it with mostly dysfunctional methods and state.
*/
@Warning(reason = "Listening to this event causes the player to be created early.")
@Warning(reason = "Listening to this event causes the player to be created early.", propagate = false) // don't nag yet given permission are not managable yet on the other events
@Deprecated(since = "1.21.6")
public class PlayerLoginEvent extends PlayerEvent {
@@ -11,10 +11,11 @@ import org.jetbrains.annotations.NotNull;
/**
* Thrown when a player picks an item up from the ground
* @deprecated {@link EntityPickupItemEvent}
*
* @deprecated use {@link EntityPickupItemEvent}
*/
@Deprecated(since = "1.12")
@Warning
@Warning(propagate = false)
public class PlayerPickupItemEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
* asynchronous.
*/
@Deprecated(since = "1.3.2")
@Warning(reason = "This event causes a login thread to synchronize with the main thread")
@Warning(reason = "This event causes a login thread to synchronize with the main thread", value = true, propagate = false)
public class PlayerPreLoginEvent extends Event {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent}
*/
@Deprecated(forRemoval = true)
@Warning
@Warning(propagate = false)
public class PlayerRecipeBookClickEvent extends PlayerEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
* @deprecated use {@link io.papermc.paper.event.player.PlayerOpenSignEvent}
*/
@Deprecated(forRemoval = true)
@Warning
@Warning(propagate = false)
public class PlayerSignOpenEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -2,6 +2,7 @@ package org.bukkit.event.player;
import com.google.common.base.Preconditions;
import org.bukkit.Location;
import org.bukkit.Warning;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
@@ -15,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
* @deprecated use {@link com.destroystokyo.paper.event.player.PlayerSetSpawnEvent}
*/
@Deprecated(forRemoval = true)
@Warning(propagate = false)
public class PlayerSpawnChangeEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
@@ -272,10 +272,15 @@ public final class JavaPluginLoader implements PluginLoader {
// This loop checks for extending deprecated events
if (clazz.getAnnotation(Deprecated.class) != null) {
Warning warning = clazz.getAnnotation(Warning.class);
if (warning != null && !warning.propagate() && !clazz.equals(eventClass)) {
break;
}
WarningState warningState = server.getWarningState();
if (!warningState.printFor(warning)) {
break;
}
plugin.getLogger().log(
Level.WARNING,
String.format(
@@ -283,7 +288,7 @@ public final class JavaPluginLoader implements PluginLoader {
plugin.getDescription().getFullName(),
clazz.getName(),
method.toGenericString(),
(warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected",
(warning != null && !warning.reason().isEmpty()) ? warning.reason() : "Please see the deprecation notice on the event for more info",
Arrays.toString(plugin.getDescription().getAuthors().toArray())),
warningState == WarningState.ON ? new AuthorNagException(null) : null);
break;
@@ -10,6 +10,7 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when player is about to spawn in a world after joining the server.
*
@@ -18,8 +19,8 @@ import org.jetbrains.annotations.NotNull;
* cause issues. Retrieving {@link Player#getUniqueId()} and {@link Player#getName()} is safe. Prefer using
* {@link io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent}.
*/
@Warning(value = true, reason = "Listening to this event causes the player to be created early. Using the player from this event will result in undefined behavior. Prefer AsyncPlayerSpawnLocationEvent.")
@Deprecated(since = "1.21.9", forRemoval = true)
@Warning(reason = "Listening to this event causes the player to be created early. Using the player from this event will result in undefined behavior. Prefer AsyncPlayerSpawnLocationEvent.", value = true, propagate = false)
public class PlayerSpawnLocationEvent extends PlayerEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
+9 -4
View File
@@ -90,9 +90,9 @@ val log4jPlugins = sourceSets.create("log4jPlugins")
configurations.named(log4jPlugins.compileClasspathConfigurationName) {
extendsFrom(configurations.compileClasspath.get())
}
val alsoShade: Configuration by configurations.creating
val alsoShade: Configuration = configurations.create("alsoShade")
val runtimeConfiguration by configurations.consumable("runtimeConfiguration") {
configurations.consumable("runtimeConfiguration") {
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
extendsFrom(configurations.getByName(sourceSets.main.get().runtimeElementsConfigurationName))
}
@@ -110,7 +110,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
dependencies {
implementation(project(":paper-api"))
implementation("ca.spottedleaf:leafpile:1.2.0")
implementation("ca.spottedleaf:leafpile:1.2.2")
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
implementation("net.minecrell:terminalconsoleappender:1.3.0")
@@ -209,7 +209,7 @@ tasks.withType<JavaCompile>().configureEach {
options.forkOptions.memoryMaximumSize = "1G"
}
val scanJarForBadCalls by tasks.registering(io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
val scanJarForBadCalls = tasks.register<io.papermc.paperweight.tasks.ScanJarForBadCalls>("scanJarForBadCalls") {
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
classpath.from(configurations.compileClasspath)
@@ -289,6 +289,7 @@ fun TaskContainer.registerRunTask(
systemProperty("disable.watchdog", true)
}
systemProperty("io.papermc.paper.suppress.sout.nags", true)
systemProperty("paper.alwaysPrintWarningState", true)
systemProperty("paper.maxChatCommandInputSize", 32767)
systemProperty("paper.disableMigrationDelay", true)
systemProperty("paper.updatingMinecraft", providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean())
@@ -342,3 +343,7 @@ fill {
}
}
}
tasks.named("publishToFill") {
notCompatibleWithConfigurationCache("Holds an HttpClient in a task field")
}
@@ -1696,10 +1696,10 @@ index 0000000000000000000000000000000000000000..7e5eb3fd7e5c502f33fbf98589e293d4
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java b/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java
new file mode 100644
index 0000000000000000000000000000000000000000..e45d49ea2299504a4d2a9a37279d68c924140471
index 0000000000000000000000000000000000000000..0421fe013b98842485c92ac76c4bce5aebb8daf2
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java
@@ -0,0 +1,64 @@
@@ -0,0 +1,68 @@
+package ca.spottedleaf.dataconverter.minecraft.converters.blockname;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -1720,7 +1720,11 @@ index 0000000000000000000000000000000000000000..e45d49ea2299504a4d2a9a37279d68c9
+ ConverterAbstractStringValueTypeRename.register(version, subVersion, MCTypeRegistry.BLOCK_NAME, renamer);
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(version, subVersion) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ final String name = data.getString("Name");
+ if (name != null) {
+ final String converted = renamer.apply(name);
@@ -9302,7 +9306,7 @@ index 0000000000000000000000000000000000000000..ec3dc7f62c67a9a9191a772c95203e2e
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java b/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fa27561debc7fbf9128ebdd1e380a9ff0ee36b8
index 0000000000000000000000000000000000000000..5f1665ec8029b57486674c68330cbf04e4f071b4
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java
@@ -0,0 +1,418 @@
@@ -9331,7 +9335,7 @@ index 0000000000000000000000000000000000000000..4fa27561debc7fbf9128ebdd1e380a9f
+ public static final MCDataType ENTITY_CHUNK = new MCDataType("EntityChunk");
+ public static final IDDataType TILE_ENTITY = new IDDataType("TileEntity");
+ public static final IDDataType ITEM_STACK = new IDDataType("ItemStack");
+ public static final MCDataType BLOCK_STATE = new MCDataType("BlockState");
+ public static final DynamicDataType BLOCK_STATE = new DynamicDataType("BlockState"); // map, or since 26.3 only the block name for default states
+ public static final MCValueType FLAT_BLOCK_STATE = new MCValueType("FlatBlockState");
+ public static final MCDataType DATA_COMPONENTS = new MCDataType("DataComponents");
+ public static final MCDataType VILLAGER_TRADE = new MCDataType("VillagerTrade");
@@ -11206,10 +11210,10 @@ index 0000000000000000000000000000000000000000..1652c2a36245a17de6fbd923d2dc1c18
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V1450.java b/ca/spottedleaf/dataconverter/minecraft/versions/V1450.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ef238879a0e002563535dae48c54c9a498252bf
index 0000000000000000000000000000000000000000..c55bf0d08f1068744981e3be5bec05ea72fbc574
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V1450.java
@@ -0,0 +1,24 @@
@@ -0,0 +1,28 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -11225,7 +11229,11 @@ index 0000000000000000000000000000000000000000..2ef238879a0e002563535dae48c54c9a
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ final MapType ret = HelperBlockFlatteningV1450.flattenNBT(data);
+ return ret == data ? null : ret.copy(); // copy to avoid problems with later state datafixers
+ }
@@ -15481,10 +15489,10 @@ index 0000000000000000000000000000000000000000..a2f0495c05e670d100cb90d526c1785a
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V2503.java b/ca/spottedleaf/dataconverter/minecraft/versions/V2503.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4b37eba32c2ba4d08429a08564f808325ec7771
index 0000000000000000000000000000000000000000..37fc65ddc016ba2dde50d0d559f1ea1b4054abba
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V2503.java
@@ -0,0 +1,73 @@
@@ -0,0 +1,77 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -15531,7 +15539,11 @@ index 0000000000000000000000000000000000000000..c4b37eba32c2ba4d08429a08564f8083
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!WALL_BLOCKS.contains(data.getString("Name"))) {
+ return null;
+ }
@@ -16423,10 +16435,10 @@ index 0000000000000000000000000000000000000000..b91bcf5e6b7963b1feeb78d811d6e71c
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V2518.java b/ca/spottedleaf/dataconverter/minecraft/versions/V2518.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab1ac06d975ffd75225f9ac4ff7fb8700c6a3c59
index 0000000000000000000000000000000000000000..0518f9beb2eeede60112e0848406bf4d17ad89f2
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V2518.java
@@ -0,0 +1,65 @@
@@ -0,0 +1,69 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -16471,7 +16483,11 @@ index 0000000000000000000000000000000000000000..ab1ac06d975ffd75225f9ac4ff7fb870
+
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!"minecraft:jigsaw".equals(data.getString("Name"))) {
+ return null;
+ }
@@ -16777,10 +16793,10 @@ index 0000000000000000000000000000000000000000..2dbf050a5c4c681b7d2ea3d1cf434c99
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V2531.java b/ca/spottedleaf/dataconverter/minecraft/versions/V2531.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2de69027f0cfe009cfcd3166e3067948af12ba9
index 0000000000000000000000000000000000000000..c6de9d12bbe6cdd21adcbf02e4794790f5f3ddda
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V2531.java
@@ -0,0 +1,63 @@
@@ -0,0 +1,67 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -16799,7 +16815,11 @@ index 0000000000000000000000000000000000000000..e2de69027f0cfe009cfcd3166e306794
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!"minecraft:redstone_wire".equals(data.getString("Name"))) {
+ return null;
+ }
@@ -17752,10 +17772,10 @@ index 0000000000000000000000000000000000000000..ad6c4c4427fc17d7ad743115773cb48d
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V2679.java b/ca/spottedleaf/dataconverter/minecraft/versions/V2679.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d983d852c917c661d3fd387f97b417ed4d45e43
index 0000000000000000000000000000000000000000..7d401d0b9599c4f87bf44bcd333aec684cc8469b
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V2679.java
@@ -0,0 +1,38 @@
@@ -0,0 +1,42 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -17770,7 +17790,11 @@ index 0000000000000000000000000000000000000000..0d983d852c917c661d3fd387f97b417e
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!"minecraft:cauldron".equals(data.getString("Name"))) {
+ return null;
+ }
@@ -25578,10 +25602,10 @@ index 0000000000000000000000000000000000000000..49ea26401d66ebb2678b156e45636db2
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V4294.java b/ca/spottedleaf/dataconverter/minecraft/versions/V4294.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c0d16b04ae74badbed164a9e208a9512d87273d
index 0000000000000000000000000000000000000000..e72b08b22d3b20feb472996e855320721da12872
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V4294.java
@@ -0,0 +1,38 @@
@@ -0,0 +1,42 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -25596,7 +25620,11 @@ index 0000000000000000000000000000000000000000..0c0d16b04ae74badbed164a9e208a951
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!"minecraft:creaking_heart".equals(data.getString("Name"))) {
+ return null;
+ }
@@ -26139,10 +26167,10 @@ index 0000000000000000000000000000000000000000..1796655f07a569c3ac5c798eb06eeae1
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V4305.java b/ca/spottedleaf/dataconverter/minecraft/versions/V4305.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f53294aa6778ed57e702a5132601e31daa4d9e7
index 0000000000000000000000000000000000000000..4a660c3982e765a27999a2e73766c4e4c3365cb3
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V4305.java
@@ -0,0 +1,38 @@
@@ -0,0 +1,42 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -26157,7 +26185,11 @@ index 0000000000000000000000000000000000000000..0f53294aa6778ed57e702a5132601e31
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ if (!"minecraft:test_block".equals(data.getString("Name"))) {
+ return null;
+ }
@@ -27996,10 +28028,10 @@ index 0000000000000000000000000000000000000000..eb2f1f913fbc02aa3e01f36d11ddf8fc
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V5006.java b/ca/spottedleaf/dataconverter/minecraft/versions/V5006.java
new file mode 100644
index 0000000000000000000000000000000000000000..394d5dbe0d5ea90fbee81414a7028310eeb0233c
index 0000000000000000000000000000000000000000..e3443c948c59bd1808667603642f9eb126e447be
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V5006.java
@@ -0,0 +1,28 @@
@@ -0,0 +1,32 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -28018,7 +28050,11 @@ index 0000000000000000000000000000000000000000..394d5dbe0d5ea90fbee81414a7028310
+ public static void register() {
+ MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public @Nullable MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ public @Nullable Object convert(final Object input, final long sourceVersion, final long toVersion) {
+ if (!(input instanceof MapType data)) {
+ return null;
+ }
+
+ RenameHelper.renameSingle(data, "Name", "id");
+ RenameHelper.renameSingle(data, "Properties", "properties");
+ return null;
@@ -28155,10 +28191,10 @@ index 0000000000000000000000000000000000000000..f470dd94811baf54a41ab33d98ee4219
+}
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V5009.java b/ca/spottedleaf/dataconverter/minecraft/versions/V5009.java
new file mode 100644
index 0000000000000000000000000000000000000000..15db5cf1fce9984716ffddbdc8d8987ab0fe46ff
index 0000000000000000000000000000000000000000..42792a8a4ec6cc132e47fc47b6498a03fa9f5ecf
--- /dev/null
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V5009.java
@@ -0,0 +1,39 @@
@@ -0,0 +1,57 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.converter.DataConverter;
@@ -28194,6 +28230,24 @@ index 0000000000000000000000000000000000000000..15db5cf1fce9984716ffddbdc8d8987a
+ return null;
+ }
+ });
+
+ MCTypeRegistry.ENTITY.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public @Nullable MapType convert(final MapType data, final long sourceVersion, final long toVersion) {
+ final MapType brain = data.getMap("Brain");
+ if (brain == null) {
+ return null;
+ }
+
+ final MapType memories = brain.getMap("memories");
+ if (memories == null) {
+ return null;
+ }
+
+ memories.remove("minecraft:is_tempted");
+ return null;
+ }
+ });
+ }
+
+ private V5009() {}
@@ -697,6 +697,123 @@ index 15c181961eb669a0ffde86c256078859f4419f23..4baf46256e90a87d684e57ff623076a8
-}
\ No newline at end of file
+}
diff --git a/ca/spottedleaf/moonrise/patches/bitstorage/PaletteReadoutCache.java b/ca/spottedleaf/moonrise/patches/bitstorage/PaletteReadoutCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d4a48a6a94f63ca793994eae162d7f3abadba83
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/bitstorage/PaletteReadoutCache.java
@@ -0,0 +1,111 @@
+package ca.spottedleaf.moonrise.patches.bitstorage;
+
+import ca.spottedleaf.common.util.IntegerUtil;
+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
+import net.minecraft.util.BitStorage;
+import net.minecraft.util.SimpleBitStorage;
+import net.minecraft.util.ZeroBitStorage;
+import net.minecraft.world.level.chunk.Palette;
+import java.util.Arrays;
+import java.util.Objects;
+
+public final class PaletteReadoutCache {
+
+ public static final int MAX_BIT_STORAGE_SIZE = 4096;
+ public static final int MAX_BIT_STORAGE_BITS = 12;
+ static {
+ if ((1 << MAX_BIT_STORAGE_BITS) != MAX_BIT_STORAGE_SIZE) {
+ throw new IllegalStateException();
+ }
+ }
+
+ public final Object[] newPalette = new Object[MAX_BIT_STORAGE_SIZE];
+ public int newPaletteCount;
+ public final long[] copyCache = new long[MAX_BIT_STORAGE_SIZE];
+ public final int[] reEncoded = new int[MAX_BIT_STORAGE_SIZE];
+ private final int[] newPaletteMapping = new int[MAX_BIT_STORAGE_SIZE];
+ private final Int2IntOpenHashMap newPaletteMappingLarge = new Int2IntOpenHashMap(MAX_BIT_STORAGE_SIZE, 0.5f);
+
+ public SimpleBitStorage repack(final int bits, final int size) {
+ // note: reEcoded len does not need to be size exactly; it must be > size
+ return new SimpleBitStorage(bits, size, this.reEncoded);
+ }
+
+ public boolean readout(final BitStorage src, final Palette<?> srcPalette) {
+ if (src instanceof ZeroBitStorage || srcPalette.getSize() == 1) {
+ return false;
+ }
+
+ final int srcSize = src.getSize();
+
+ if (srcSize > MAX_BIT_STORAGE_SIZE) {
+ throw new UnsupportedOperationException();
+ }
+ final long[] srcRaw = src.getRaw();
+ final int srcCount = src.getSize();
+ final int srcBits = src.getBits();
+ final int srcValuesPerElement = (Long.SIZE / srcBits);
+ final long srcMask = IntegerUtil.getLongMask(srcBits);
+
+ final long[] cpy = this.copyCache;
+ Objects.checkFromToIndex(0, srcRaw.length, cpy.length);
+
+ final int[] newPaletteMapping;
+ final Int2IntOpenHashMap newPaletteMappingLarge;
+ if ((srcMask + 1) > this.newPaletteMapping.length) {
+ newPaletteMapping = null;
+ newPaletteMappingLarge = this.newPaletteMappingLarge;
+
+ newPaletteMappingLarge.clear();
+ } else {
+ newPaletteMapping = this.newPaletteMapping;
+ newPaletteMappingLarge = null;
+
+ Arrays.fill(newPaletteMapping, 0, (int)(srcMask + 1), -1);
+ }
+
+ final int[] reEncoded = this.reEncoded;
+ Objects.checkFromToIndex(0, srcSize, reEncoded.length);
+
+ final Object[] newPalette = this.newPalette;
+ Objects.checkFromToIndex(0, srcSize, newPalette.length);
+
+ int rem = srcCount;
+ int reEncodeIndex = 0;
+ int nextPaletteId = 0;
+ for (int i = 0, len = srcRaw.length; i < len; ++i) {
+ long value = srcRaw[i];
+ cpy[i] = value;
+
+ for (int k = 0, len2 = Math.min(rem, srcValuesPerElement); k < len2; ++k, --rem) {
+ final int decoded = (int)(value & srcMask);
+ value >>>= srcBits;
+
+ final int mapped = newPaletteMapping != null ? newPaletteMapping[decoded] : newPaletteMappingLarge.getOrDefault(decoded, -1);
+ if (mapped != -1) {
+ reEncoded[reEncodeIndex++] = mapped;
+ continue;
+ }
+
+
+ final int computedMapping = nextPaletteId++;
+ newPalette[computedMapping] = srcPalette.valueFor(decoded);
+ reEncoded[reEncodeIndex++] = computedMapping;
+
+ if (newPaletteMapping != null) {
+ newPaletteMapping[decoded] = computedMapping;
+ } else {
+ newPaletteMappingLarge.put(decoded, computedMapping);
+ }
+ }
+ }
+
+ if (rem != 0) {
+ throw new IllegalStateException();
+ }
+
+ this.newPaletteCount = nextPaletteId;
+
+ return true;
+ }
+}
diff --git a/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingBitStorage.java b/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingBitStorage.java
new file mode 100644
index 0000000000000000000000000000000000000000..93bc56daec4526f373c84763b8c7ccb4a30e800b
@@ -1141,10 +1258,10 @@ index 0000000000000000000000000000000000000000..a814512fcfb85312474ae2c2c2144384
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
new file mode 100644
index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b622dfca5e
index 0000000000000000000000000000000000000000..6dd6b4fb79870da6d3bf54dc813ae685237d1f0e
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -0,0 +1,1488 @@
@@ -0,0 +1,1561 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.io;
+
+import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue;
@@ -1937,6 +2054,9 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ if (pendingWrite == null) {
+ // need to add to waiters here, because the regionfile thread will use compute() to lock and check for cancellations
+ if (!running.inProgressRead.addToAsyncWaiters(onComplete)) {
+ if (!running.inProgressRead.written) {
+ throw new IllegalStateException("In progress read is add-blocked but data is not written");
+ }
+ callbackInfo.data = running.inProgressRead.value;
+ callbackInfo.throwable = running.inProgressRead.throwable;
+ callbackInfo.completeNow = true;
@@ -1971,7 +2091,8 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ ret.scheduleReadIO();
+ } else if (callbackInfo.completeNow) {
+ try {
+ onComplete.accept(callbackInfo.data == null ? null : callbackInfo.data.copy(), callbackInfo.throwable);
+ final boolean copy = !(onComplete instanceof NoCopyNBTData);
+ onComplete.accept(callbackInfo.data == null ? null : (copy ? callbackInfo.data.copy() : callbackInfo.data), callbackInfo.throwable);
+ } catch (final Throwable thr) {
+ LOGGER.error("Callback " + ConcurrentUtil.genericToString(onComplete) + " synchronously failed to handle chunk data for task " + ret.toString(), thr);
+ }
@@ -2239,6 +2360,7 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ // further synchronisation.
+ }
+
+ final boolean cancelledWrite;
+ if (canRead[0]) {
+ RegionDataController.ReadData readData = null;
+ Throwable throwable = null;
@@ -2251,12 +2373,12 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ }
+
+ if (throwable != null) {
+ this.finishRead(null, throwable);
+ cancelledWrite = this.finishRead(null, throwable);
+ } else {
+ switch (readData.result()) {
+ case NO_DATA:
+ case SYNC_READ: {
+ this.finishRead(readData.syncRead(), null);
+ cancelledWrite = this.finishRead(readData.syncRead(), null);
+ break;
+ }
+ case HAS_DATA: {
@@ -2270,9 +2392,11 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ }
+ }
+ }
+ } else {
+ cancelledWrite = this.tryAbortWrite();
+ }
+
+ if (!this.tryAbortWrite()) {
+ if (!cancelledWrite) {
+ this.scheduleWriteCompress();
+ }
+ }
@@ -2306,14 +2430,45 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ return;
+ }
+
+ this.finishRead(compoundTag, throwable);
+ if (!this.tryAbortWrite()) {
+ final boolean cancelledWrite = this.finishRead(compoundTag, throwable);
+ if (!cancelledWrite) {
+ this.scheduleWriteCompress();
+ }
+ }
+
+ private void finishRead(final CompoundTag compoundTag, final Throwable throwable) {
+ this.inProgressRead.complete(this, compoundTag, throwable);
+ private boolean finishRead(final CompoundTag compoundTag, final Throwable throwable) {
+ final long chunkKey = CoordinateUtils.getChunkKey(this.chunkX, this.chunkZ);
+
+ final boolean[] canSingleComplete = new boolean[1];
+ final ChunkIOTask inMap = this.regionDataController.chunkTasks.compute(chunkKey, (final long keyInMap, final ChunkIOTask valueInMap) -> {
+ if (valueInMap == null) {
+ throw new IllegalStateException("Read/write completed concurrently, expected this task: " + ChunkIOTask.this.toString() + ", report this!");
+ }
+ if (valueInMap != ChunkIOTask.this) {
+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkIOTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!");
+ }
+
+ canSingleComplete[0] = valueInMap.inProgressRead.hasAtMostOneCallback();
+
+ if (valueInMap.inProgressWrite != null) {
+ return valueInMap;
+ }
+
+ return null;
+ });
+
+ if (canSingleComplete[0]) {
+ this.inProgressRead.completeOne(this, compoundTag, throwable);
+ } else {
+ this.inProgressRead.complete(this, compoundTag, throwable);
+ }
+
+ if (inMap == null) {
+ this.regionDataController.endTask(this);
+ return true; // set the task value to null, indicating we're done
+ }
+ // else: inProgressWrite is present, indicating we need to write a value
+ return false;
+ }
+
+ public void scheduleWriteCompress() {
@@ -2327,7 +2482,7 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ this.currentTask = task;
+ }
+
+ inProgressWrite.addToWaiters(this, (final CompoundTag data, final Throwable throwable) -> {
+ inProgressWrite.addToWaiters(this, (BiConsumer<CompoundTag, Throwable> & NoCopyNBTData) (final CompoundTag data, final Throwable throwable) -> {
+ task.queue();
+ });
+ }
@@ -2469,6 +2624,7 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(InProgressRead.class);
+
+ private boolean written;
+ private CompoundTag value;
+ private Throwable throwable;
+ private final MultiThreadedQueue<BiConsumer<CompoundTag, Throwable>> callbacks = new MultiThreadedQueue<>();
@@ -2485,17 +2641,44 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ return this.callbacks.remove(callback);
+ }
+
+ public boolean hasAtMostOneCallback() {
+ return this.callbacks.size() <= 1;
+ }
+
+ public void completeOne(final ChunkIOTask task, final CompoundTag value, final Throwable throwable) {
+ // since the task is either cancelled (removed) or has an in-progress write,
+ // we can guarantee that the read data is only used by one consumer - eliminating
+ // the need to copy
+
+ this.callbacks.preventAdds();
+
+ final BiConsumer<CompoundTag, Throwable> consumer = this.callbacks.poll();
+ if (consumer != null) {
+ this.completeConsumer(task, consumer, value, throwable);
+
+ if (!this.callbacks.isEmpty()) {
+ throw new IllegalStateException("Expected only one callback");
+ }
+ } // else: add blocked, we are done here
+ }
+
+ private void completeConsumer(final ChunkIOTask task, final BiConsumer<CompoundTag, Throwable> consumer, final CompoundTag value, final Throwable throwable) {
+ try {
+ consumer.accept(value, throwable);
+ } catch (final Throwable thr) {
+ LOGGER.error("Callback " + ConcurrentUtil.genericToString(consumer) + " failed to handle chunk data (read) for task " + task.toString(), thr);
+ }
+ }
+
+ public void complete(final ChunkIOTask task, final CompoundTag value, final Throwable throwable) {
+ this.value = value;
+ this.throwable = throwable;
+ this.written = true;
+
+ BiConsumer<CompoundTag, Throwable> consumer;
+ while ((consumer = this.callbacks.pollOrBlockAdds()) != null) {
+ try {
+ consumer.accept(value == null ? null : value.copy(), throwable);
+ } catch (final Throwable thr) {
+ LOGGER.error("Callback " + ConcurrentUtil.genericToString(consumer) + " failed to handle chunk data (read) for task " + task.toString(), thr);
+ }
+ final boolean copy = !(consumer instanceof NoCopyNBTData);
+ this.completeConsumer(task, consumer, value == null ? null : (copy ? value.copy() : value), throwable);
+ }
+ }
+ }
@@ -2537,7 +2720,8 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+
+ private void syncAccept(final ChunkIOTask task, final BiConsumer<CompoundTag, Throwable> consumer, final CompoundTag value, final Throwable throwable) {
+ try {
+ consumer.accept(value == null ? null : value.copy(), throwable);
+ final boolean copy = !(consumer instanceof NoCopyNBTData);
+ consumer.accept(value == null ? null : (copy ? value.copy() : value), throwable);
+ } catch (final Throwable thr) {
+ LOGGER.error("Callback " + ConcurrentUtil.genericToString(consumer) + " failed to handle chunk data (write) for task " + task.toString(), thr);
+ }
@@ -2562,6 +2746,12 @@ index 0000000000000000000000000000000000000000..27eeb842e6b22bd12b582379eaaa76b6
+ }
+ }
+
+ /**
+ * Use on callbacks indicating that the NBT data input is never modified. The callback is invoked
+ * with uncopied data.
+ */
+ public static interface NoCopyNBTData {}
+
+ public static abstract class RegionDataController {
+
+ public final RegionFileType type;
@@ -6659,10 +6849,10 @@ index 0000000000000000000000000000000000000000..78659864651362de4fc104cbeb3e2e9a
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..e418820359c430b91bb91eb65d137b9cdbe2db4b
index 0000000000000000000000000000000000000000..1e05aab0a259bd0073c4761e419edf90fb175814
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
@@ -0,0 +1,1568 @@
@@ -0,0 +1,1570 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.scheduling;
+
+import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue;
@@ -6686,6 +6876,7 @@ index 0000000000000000000000000000000000000000..e418820359c430b91bb91eb65d137b9c
+import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
+import ca.spottedleaf.moonrise.patches.chunk_system.util.ChunkSystemSortedArraySet;
+import ca.spottedleaf.moonrise.patches.chunk_system.util.stream.TicketSet;
+import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.mojang.logging.LogUtils;
@@ -7809,6 +8000,7 @@ index 0000000000000000000000000000000000000000..e418820359c430b91bb91eb65d137b9c
+ private void removeChunkHolder(final NewChunkHolder holder) {
+ holder.onUnload();
+ this.autoSaveQueue.remove(holder);
+ ((ChunkSystemServerChunkCache)this.world.getChunkSource()).moonrise$chunkHolderUnload(holder);
+ PlatformHooks.get().onChunkHolderDelete(this.world, holder.vanillaChunkHolder);
+ this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
+ }
@@ -8233,7 +8425,7 @@ index 0000000000000000000000000000000000000000..e418820359c430b91bb91eb65d137b9c
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..2aa7a2bb7adcd0ed53f2538368f890b75b114ecf
index 0000000000000000000000000000000000000000..bbba1766ed9da671022c467a45f7de479fb6abb4
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java
@@ -0,0 +1,1046 @@
@@ -8614,7 +8806,7 @@ index 0000000000000000000000000000000000000000..2aa7a2bb7adcd0ed53f2538368f890b7
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
+ }
+
+ final int minLevel = 33 - (toStatus.ordinal() - 1);
+ final int minLevel = ChunkLevel.byStatus(toStatus);
+ final Long chunkReference = addTicket ? getNextChunkLoadId() : null;
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
+
@@ -9697,10 +9889,10 @@ index 0000000000000000000000000000000000000000..7f75cc224d1dea04405f19880b6a1b57
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a9a599ef178f851ee5c783631a724013a693586
index 0000000000000000000000000000000000000000..7a0006f9b56d1e43b06f9f7452e1b5bb0ec53e72
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
@@ -0,0 +1,1975 @@
@@ -0,0 +1,1986 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.scheduling;
+
+import ca.spottedleaf.concurrentutil.completable.CallbackCompletable;
@@ -11406,12 +11598,23 @@ index 0000000000000000000000000000000000000000..9a9a599ef178f851ee5c783631a72401
+ : null;
+ }
+
+ public static final ThreadLocal<Boolean> DO_NOT_COPY_SAVED_DATA = ThreadLocal.withInitial(() -> {
+ return Boolean.FALSE;
+ });
+
+ private boolean saveChunk(final ChunkAccess chunk, final boolean unloading, final Completable<CompoundTag>[] chunkSave) {
+ if (!chunk.isUnsaved()) {
+ return false;
+ }
+ try {
+ final SerializableChunkData chunkData = SerializableChunkData.copyOf(this.world, chunk);
+ final SerializableChunkData chunkData;
+
+ DO_NOT_COPY_SAVED_DATA.set(Boolean.valueOf(unloading));
+ try {
+ chunkData = SerializableChunkData.copyOf(this.world, chunk);
+ } finally {
+ DO_NOT_COPY_SAVED_DATA.set(Boolean.FALSE);
+ }
+ PlatformHooks.get().chunkSyncSave(this.world, chunk, chunkData);
+
+ chunk.tryMarkSaved();
@@ -15900,12 +16103,13 @@ index 0000000000000000000000000000000000000000..ea6b6ed27b212719feb31610faac9748
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/world/ChunkSystemServerChunkCache.java b/ca/spottedleaf/moonrise/patches/chunk_system/world/ChunkSystemServerChunkCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b9e2fa963c14f65f15407c1814c543c2999ea32
index 0000000000000000000000000000000000000000..bfd4a1fbfcfdc3aa90a59784b28ee077dbc26f4d
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/world/ChunkSystemServerChunkCache.java
@@ -0,0 +1,11 @@
@@ -0,0 +1,14 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.world;
+
+import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
+import net.minecraft.world.level.chunk.LevelChunk;
+
+public interface ChunkSystemServerChunkCache {
@@ -15914,6 +16118,8 @@ index 0000000000000000000000000000000000000000..4b9e2fa963c14f65f15407c1814c543c
+
+ public LevelChunk moonrise$getFullChunkIfLoaded(final int chunkX, final int chunkZ);
+
+ public void moonrise$chunkHolderUnload(final NewChunkHolder chunkHolder);
+
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java b/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java
new file mode 100644
@@ -19647,10 +19853,10 @@ index 0000000000000000000000000000000000000000..29563672f4b0e5e13625193125656549
+}
diff --git a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c7b3804cdbcb0a873a0d195325c2658760a8914
index 0000000000000000000000000000000000000000..240416aba0ad4649e1db401aff2565f972f5ca11
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
@@ -0,0 +1,441 @@
@@ -0,0 +1,445 @@
+package ca.spottedleaf.moonrise.patches.starlight.light;
+
+import net.minecraft.world.level.chunk.DataLayer;
@@ -19785,6 +19991,10 @@ index 0000000000000000000000000000000000000000..5c7b3804cdbcb0a873a0d195325c2658
+ }
+
+ public SaveState getSaveState() {
+ return this.getSaveState(true);
+ }
+
+ public SaveState getSaveState(final boolean copy) {
+ synchronized (this) {
+ final int state = this.stateVisible;
+ final byte[] data = this.storageVisible;
@@ -19798,7 +20008,7 @@ index 0000000000000000000000000000000000000000..5c7b3804cdbcb0a873a0d195325c2658
+ if (zero) {
+ return state == INIT_STATE_INIT ? new SaveState(null, INIT_STATE_UNINIT) : null;
+ } else {
+ return new SaveState(data.clone(), state);
+ return new SaveState(copy ? data.clone() : data, state);
+ }
+ }
+ }
@@ -26889,7 +27099,7 @@ index a701288146a1d7cd258faae69f959edf466ec71c..3509df9dd423b38d1ca3e4a420d1352a
}
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace51f7af6f 100644
index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..a6fb79a70de177fcc027ddb0c5ae6fe3ed3c0407 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -54,7 +54,7 @@ import net.minecraft.world.level.storage.SavedDataStorage;
@@ -26901,7 +27111,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
private static final Logger LOGGER = LogUtils.getLogger();
private final DistanceManager distanceManager;
private final ServerLevel level;
@@ -81,6 +81,105 @@ public class ServerChunkCache extends ChunkSource {
@@ -81,6 +81,110 @@ public class ServerChunkCache extends ChunkSource {
}
long chunkFutureAwaitCounter;
// Paper end
@@ -26922,6 +27132,11 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
+ return this.fullChunks.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ }
+
+ @Override
+ public void moonrise$chunkHolderUnload(final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder) {
+ this.chunkHoldersToBroadcast.remove(chunkHolder.vanillaChunkHolder);
+ }
+
+ private ChunkAccess syncLoad(final int chunkX, final int chunkZ, final ChunkStatus toStatus) {
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler chunkTaskScheduler = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler();
+ final CompletableFuture<ChunkAccess> completable = new CompletableFuture<>();
@@ -27007,7 +27222,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
public ServerChunkCache(
final ServerLevel level,
@@ -138,13 +237,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -138,13 +242,7 @@ public class ServerChunkCache extends ChunkSource {
}
// CraftBukkit end
// Paper start
@@ -27022,7 +27237,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
@Nullable
public ChunkAccess getChunkAtImmediately(int x, int z) {
@@ -209,65 +302,41 @@ public class ServerChunkCache extends ChunkSource {
@@ -209,65 +307,41 @@ public class ServerChunkCache extends ChunkSource {
@Override
public @Nullable ChunkAccess getChunk(final int x, final int z, final ChunkStatus targetStatus, final boolean loadOrGenerate) {
@@ -27108,7 +27323,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
}
private void clearCache() {
@@ -295,53 +364,62 @@ public class ServerChunkCache extends ChunkSource {
@@ -295,53 +369,62 @@ public class ServerChunkCache extends ChunkSource {
private CompletableFuture<ChunkResult<ChunkAccess>> getChunkFutureMainThread(
final int x, final int z, final ChunkStatus targetStatus, final boolean loadOrGenerate
) {
@@ -27205,7 +27420,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
}
@Override
@@ -354,28 +432,18 @@ public class ServerChunkCache extends ChunkSource {
@@ -354,28 +437,18 @@ public class ServerChunkCache extends ChunkSource {
}
public boolean runDistanceManagerUpdates() {
@@ -27240,7 +27455,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
this.chunkMap.saveAllChunks(flushStorage);
}
@@ -386,17 +454,15 @@ public class ServerChunkCache extends ChunkSource {
@@ -386,17 +459,15 @@ public class ServerChunkCache extends ChunkSource {
}
public void close(boolean save) throws IOException {
@@ -27261,7 +27476,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
ProfilerFiller gameprofilerfiller = Profiler.get();
gameprofilerfiller.push("purge");
@@ -420,6 +486,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -420,6 +491,7 @@ public class ServerChunkCache extends ChunkSource {
this.runDistanceManagerUpdates();
profiler.popPush("chunks");
if (tickChunks) {
@@ -27269,7 +27484,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
this.tickChunks();
this.chunkMap.tick();
}
@@ -449,7 +516,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -449,7 +521,7 @@ public class ServerChunkCache extends ChunkSource {
profiler.push("broadcast");
for (ChunkHolder chunkHolder : this.chunkHoldersToBroadcast) {
@@ -27278,7 +27493,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
if (chunk != null) {
chunkHolder.broadcastChanges(chunk);
}
@@ -488,7 +555,10 @@ public class ServerChunkCache extends ChunkSource {
@@ -488,7 +560,10 @@ public class ServerChunkCache extends ChunkSource {
profiler.popPush("filteringSpawningChunks");
this.chunkMap.collectSpawningChunks(spawningChunks);
profiler.popPush("shuffleSpawningChunks");
@@ -27289,7 +27504,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
profiler.popPush("tickSpawningChunks");
for (LevelChunk chunk : spawningChunks) {
@@ -499,7 +569,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -499,7 +574,7 @@ public class ServerChunkCache extends ChunkSource {
}
profiler.popPush("tickTickingChunks");
@@ -27298,7 +27513,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
if (doMobSpawning) {
profiler.popPush("customSpawners");
this.level.tickCustomSpawners(this.spawnEnemies);
@@ -511,22 +581,25 @@ public class ServerChunkCache extends ChunkSource {
@@ -511,22 +586,25 @@ public class ServerChunkCache extends ChunkSource {
private void tickSpawningChunk(final LevelChunk chunk, final List<MobCategory> spawningCategories, final NaturalSpawner.SpawnState spawnCookie) {
ChunkPos chunkPos = chunk.getPos();
chunk.incrementInhabitedTime();
@@ -27329,7 +27544,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
}
@Override
@@ -584,19 +657,11 @@ public class ServerChunkCache extends ChunkSource {
@@ -584,19 +662,11 @@ public class ServerChunkCache extends ChunkSource {
}
public CompletableFuture<?> addTicketAndLoadWithRadius(final TicketType type, final ChunkPos pos, final int radius) {
@@ -27354,7 +27569,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
}
public void addTicketWithRadius(final TicketType type, final ChunkPos pos, final int radius) {
@@ -656,6 +721,12 @@ public class ServerChunkCache extends ChunkSource {
@@ -656,6 +726,12 @@ public class ServerChunkCache extends ChunkSource {
this.chunkMap.setServerViewDistance(newDistance);
}
@@ -27367,7 +27582,7 @@ index 10ff01be97664df1c7ac8ff90bbdbbc0b584977c..2dec44b08e6932da87c88233743e7ace
public void setSimulationDistance(final int simulationDistance) {
this.distanceManager.updateSimulationDistance(simulationDistance);
}
@@ -735,18 +806,12 @@ public class ServerChunkCache extends ChunkSource {
@@ -735,18 +811,12 @@ public class ServerChunkCache extends ChunkSource {
@Override
protected boolean pollTask() {
@@ -27405,7 +27620,7 @@ index e7ddd956a7f942f682f60062eecf0fad95b18749..267259a79c7668da85d206f9dcbde16b
List<Entity> passengers = this.entity.getPassengers();
if (!passengers.equals(this.lastPassengers)) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 1ae0e8fe43b3c4598e684ca95d430747e5c581bd..a20c7ed74a54c08b43fdf778fbf6eab4293ea0c6 100644
index 47a0e17e4fed94828e02c7f4159d32195158f6cc..46e7478bd96e42487cf0fc467b6b9b83f2887d10 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -183,7 +183,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
@@ -28894,7 +29109,7 @@ index 3271c83bd103bea9b9ffcd6882b52896ea4da770..f6601bc30fa37a309923ea9883b04233
PrepareSpawnTask.this.loadListener.updateFocus(this.spawnLevel.dimension(), spawnChunk);
}
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index c7d3c19e7df2ca11a04684849762c81020236ae8..b5c7affd9ac2f071992e5621a1cf3dfd335930b1 100644
index b1bf82288596b686dfb4e19d274a6a623fbe1667..010c6c7e9bf59408bdac22a01f05fe2e8fbafe41 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -986,8 +986,8 @@ public abstract class PlayerList {
@@ -28908,7 +29123,7 @@ index c7d3c19e7df2ca11a04684849762c81020236ae8..b5c7affd9ac2f071992e5621a1cf3dfd
// Paper end - view distances
if (level.isRaining()) {
// CraftBukkit start - handle player weather
@@ -1200,7 +1200,7 @@ public abstract class PlayerList {
@@ -1203,7 +1203,7 @@ public abstract class PlayerList {
public void setViewDistance(final int viewDistance) {
this.viewDistance = viewDistance;
@@ -28917,7 +29132,7 @@ index c7d3c19e7df2ca11a04684849762c81020236ae8..b5c7affd9ac2f071992e5621a1cf3dfd
for (ServerLevel level : this.server.getAllLevels()) {
level.getChunkSource().setViewDistance(viewDistance);
@@ -1209,7 +1209,7 @@ public abstract class PlayerList {
@@ -1212,7 +1212,7 @@ public abstract class PlayerList {
public void setSimulationDistance(final int simulationDistance) {
this.simulationDistance = simulationDistance;
@@ -33519,7 +33734,7 @@ index 9b9119afd89f60cd88c3d1e6ec4857b92e95ff11..eec56782be6e6e2c483e7435ff136bf8
boolean maybeHas(Predicate<T> predicate);
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
index 9591b8644da987a6e2dc77bb7388b99566a855e3..a799c2e24b9990b1dc9b8608231a9801d4036493 100644
index 9591b8644da987a6e2dc77bb7388b99566a855e3..9213568da8d590b2f81ba3a51e216ec395badb31 100644
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -24,7 +24,7 @@ import org.jspecify.annotations.Nullable;
@@ -33629,7 +33844,125 @@ index 9591b8644da987a6e2dc77bb7388b99566a855e3..a799c2e24b9990b1dc9b8608231a9801
} finally {
this.release();
}
@@ -317,7 +354,43 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -223,30 +260,104 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette));
}
+ // Paper start - optimise PalettedContainer packing
+ private static final ThreadLocal<ca.spottedleaf.moonrise.patches.bitstorage.PaletteReadoutCache> READOUT_CACHE = ThreadLocal.withInitial(() -> {
+ return new ca.spottedleaf.moonrise.patches.bitstorage.PaletteReadoutCache();
+ });
+ private static final boolean DEBUG_PACKING = false;
+ private static <T> void validate(List<T> palette, long[] data, int bits,
+ BitStorage againstStorage, Palette<T> againstPalette) {
+ BitStorage storage = data == null ? new ZeroBitStorage(againstStorage.getSize()) :
+ new SimpleBitStorage(bits, againstStorage.getSize(), data);
+
+ for (int i = 0; i < storage.getSize(); ++i) {
+ T expect = againstPalette.valueFor(againstStorage.get(i));
+ T got = palette.get(storage.get(i));
+
+ if (expect != got) {
+ throw new IllegalStateException();
+ }
+ }
+ }
+ // Paper end - optimise PalettedContainer packing
+
@Override
public synchronized PalettedContainerRO.PackedData<T> pack(final Strategy<T> strategy) { // Paper - synchronize
+ // Paper start - optimise PalettedContainer packing
this.acquire();
try {
- BitStorage currentStorage = this.data.storage;
- Palette<T> currentPalette = this.data.palette;
- HashMapPalette<T> newPalette = new HashMapPalette<>(currentStorage.getBits());
- int entryCount = strategy.entryCount();
- int[] newContents = reencodeContents(currentStorage, currentPalette, newPalette);
- Configuration storedConfiguration = strategy.getConfigurationForPaletteSize(newPalette.getSize());
- int bitsOnDisc = storedConfiguration.bitsInStorage();
- Optional<LongStream> values;
- if (bitsOnDisc != 0) {
- SimpleBitStorage storage = new SimpleBitStorage(bitsOnDisc, entryCount, newContents);
- values = Optional.of(Arrays.stream(storage.getRaw()));
+ final PalettedContainer.Data<T> data = this.data;
+
+ final BitStorage storage = data.storage();
+ final Palette<T> palette = data.palette();
+
+ final ca.spottedleaf.moonrise.patches.bitstorage.PaletteReadoutCache readoutCache = READOUT_CACHE.get();
+
+ final boolean zero = !readoutCache.readout(storage, palette);
+
+ final int newPaletteSize = zero ? 1 : readoutCache.newPaletteCount;
+ final List<T> newPalette = new java.util.ArrayList<>(newPaletteSize);
+ final long[] dataArray;
+ final Configuration configuration = strategy.getConfigurationForPaletteSize(newPaletteSize);
+ final int bitsToUse = configuration.bitsInStorage();
+ if (zero) {
+ newPalette.add(palette.valueFor(0));
+ if (bitsToUse == 0) {
+ dataArray = null;
+ } else {
+ dataArray = new SimpleBitStorage(bitsToUse, storage.getSize()).getRaw();
+ }
} else {
- values = Optional.empty();
+ if (bitsToUse != 0 && newPaletteSize == palette.getSize() && bitsToUse == storage.getBits()) {
+ // palette and bits are identical, so we can just use the old data
+
+ final List<T> oldPalette = new java.util.ArrayList<>(newPaletteSize);
+ for (int i = 0; i < newPaletteSize; ++i) {
+ oldPalette.add(palette.valueFor(i));
+ }
+
+ // avoid holding references to palette entries
+ Arrays.fill(readoutCache.newPalette, 0, newPaletteSize, null);
+
+ // we need to use the copy cache here, as some bad mods may write to the container off-thread which
+ // may leave the palette desynced
+
+ final long[] cpy = Arrays.copyOf(readoutCache.copyCache, storage.getRaw().length);
+
+ if (DEBUG_PACKING) {
+ validate(oldPalette, cpy, bitsToUse, storage, palette);
+ }
+
+ return new PalettedContainerRO.PackedData<>(oldPalette, Optional.of(Arrays.stream(cpy)), bitsToUse);
+ } else {
+ final Object[] newPaletteRaw = readoutCache.newPalette;
+ java.util.Objects.checkFromToIndex(0, readoutCache.newPaletteCount, newPaletteRaw.length);
+ for (int i = 0, len = readoutCache.newPaletteCount; i < len; ++i) {
+ final T entry = (T)newPaletteRaw[i];
+ // avoid holding references to palette entries
+ newPaletteRaw[i] = null;
+ newPalette.add(entry);
+ }
+
+ if (bitsToUse == 0) {
+ dataArray = null;
+ } else {
+ dataArray = readoutCache.repack(bitsToUse, storage.getSize()).getRaw();
+ }
+ }
}
- return new PalettedContainerRO.PackedData<>(newPalette.getEntries(), values, bitsOnDisc);
+ if (DEBUG_PACKING) {
+ validate(newPalette, dataArray, bitsToUse, storage, palette);
+ }
+
+ // why does this trash use streams...?
+ return new PalettedContainerRO.PackedData<>(newPalette, dataArray == null ? Optional.empty() : Optional.of(Arrays.stream(dataArray)), bitsToUse);
} finally {
this.release();
}
+ // Paper end - optimise PalettedContainer packing
}
private static <T> int[] reencodeContents(final BitStorage storage, final Palette<T> oldPalette, final Palette<T> newPalette) {
@@ -317,7 +428,43 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
void accept(final T entry, final int count);
}
@@ -34558,7 +34891,7 @@ index 2412c31426bbf0a4f8102bf7ce307a4a93935f52..4bc70852449459037d293d2813c1c733
private record PackedChunk<T>(Int2ObjectMap<T> sectionsByY, boolean versionChanged) {
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848da6c4ed0b 100644
index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..5b311dc7f0a9d7cb202011302920478977f27bb0 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -145,7 +145,7 @@ public record SerializableChunkData(
@@ -34676,7 +35009,7 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
}
private static void logErrors(final ChunkPos pos, final int sectionY, final String message) {
@@ -361,21 +424,44 @@ public record SerializableChunkData(
@@ -361,21 +424,46 @@ public record SerializableChunkData(
ChunkPos pos = chunk.getPos();
List<SerializableChunkData.SectionData> sectionData = new ArrayList<>();
@@ -34698,6 +35031,8 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
+ final int maxLightSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxLightSection(level);
+ final int minBlockSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(level);
+
+ final boolean copy = !ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder.DO_NOT_COPY_SAVED_DATA.get().booleanValue();
+
+ final LevelChunkSection[] chunkSections = chunk.getSections();
+ final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles = ((ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk)chunk).starlight$getBlockNibbles();
+ final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] skyNibbles = ((ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk)chunk).starlight$getSkyNibbles();
@@ -34706,13 +35041,13 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
+ final int lightSectionIdx = lightSection - minLightSection;
+ final int blockSectionIdx = lightSection - minBlockSection;
+
+ final LevelChunkSection chunkSection = (blockSectionIdx >= 0 && blockSectionIdx < chunkSections.length) ? chunkSections[blockSectionIdx].copy() : null;
+ final LevelChunkSection chunkSection = (blockSectionIdx >= 0 && blockSectionIdx < chunkSections.length) ? (copy ? chunkSections[blockSectionIdx].copy() : chunkSections[blockSectionIdx]) : null;
+ final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray.SaveState blockNibble = blockNibbles[lightSectionIdx].getSaveState();
+ final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray.SaveState skyNibble = skyNibbles[lightSectionIdx].getSaveState();
+
+ if (chunkSection == null && blockNibble == null && skyNibble == null) {
+ continue;
+ }
}
+
+ final SerializableChunkData.SectionData section = new SerializableChunkData.SectionData(
+ lightSection, chunkSection,
@@ -34726,7 +35061,7 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
+
+ if (skyNibble != null) {
+ ((ca.spottedleaf.moonrise.patches.starlight.storage.StarlightSectionData)(Object)section).starlight$setSkyLightState(skyNibble.state);
}
+ }
+
+ sectionData.add(section);
}
@@ -34734,7 +35069,7 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
List<CompoundTag> blockEntities = new ArrayList<>(chunk.getBlockEntitiesPos().size());
@@ -466,6 +552,19 @@ public record SerializableChunkData(
@@ -466,6 +554,19 @@ public record SerializableChunkData(
sectionTag.putByteArray("SkyLight", section.skyLight.getData());
}
@@ -34754,7 +35089,7 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
if (!sectionTag.isEmpty()) {
sectionTag.putByte("Y", (byte)section.y);
sectionTags.add(sectionTag);
@@ -497,6 +596,14 @@ public record SerializableChunkData(
@@ -497,6 +598,14 @@ public record SerializableChunkData(
tag.put("ChunkBukkitValues", this.persistentDataContainer);
}
// CraftBukkit end
@@ -34769,7 +35104,7 @@ index 9ae8f31c3ed39ed2f2a93a7eb95ea2f93f97adc8..f099aa45853b4e21b4a6e8052fa6848d
return tag;
}
@@ -644,6 +751,60 @@ public record SerializableChunkData(
@@ -644,6 +753,60 @@ public record SerializableChunkData(
}
}
@@ -35701,7 +36036,7 @@ index cbc68e86fd31ad787b6e66ed35d98c85dd9fe364..a4502aa85f907ae532e44b46d065c324
@Override
diff --git a/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java b/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..0815741cb832b4be90c95747ca2b24f3a2a81f4f 100644
index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..b23a4a226a370c3ac535282e28c00e6e4dc130c1 100644
--- a/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
+++ b/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
@@ -4,13 +4,13 @@ import java.util.BitSet;
@@ -35789,7 +36124,7 @@ index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..0815741cb832b4be90c95747ca2b24f3
+ indexX = indexY;
+ for (int x = 0; x < sizeX; ++x, indexX += incX) {
+ for (int zIdx = indexX, endIndex = indexX + sizeZ; zIdx < endIndex; ) {
+ final int firstSetZ = ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.firstSet(bitset, zIdx, endIndex);
+ final int firstSetZ = ca.spottedleaf.common.util.FlatBitsetUtil.firstSet(bitset, zIdx, endIndex);
+
+ if (firstSetZ == -1) {
+ break;
@@ -35803,21 +36138,21 @@ index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..0815741cb832b4be90c95747ca2b24f3
- shape.clearZStrip(lastStartZ, z, endX + 1, y);
- endX++;
+
+ int lastSetZ = ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
+ int lastSetZ = ca.spottedleaf.common.util.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
+ if (lastSetZ == -1) {
+ lastSetZ = endIndex;
+ }
+
+ ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.clearRange(bitset, firstSetZ, lastSetZ);
+ ca.spottedleaf.common.util.FlatBitsetUtil.clearRange(bitset, firstSetZ, lastSetZ);
+
+ // try to merge neighbouring on the X axis
+ int endX = x + 1; // exclusive
+ for (int neighbourIdxStart = firstSetZ + incX, neighbourIdxEnd = lastSetZ + incX;
+ endX < sizeX && ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.isRangeSet(bitset, neighbourIdxStart, neighbourIdxEnd);
+ endX < sizeX && ca.spottedleaf.common.util.FlatBitsetUtil.isRangeSet(bitset, neighbourIdxStart, neighbourIdxEnd);
+ neighbourIdxStart += incX, neighbourIdxEnd += incX) {
+
+ ++endX;
+ ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.clearRange(bitset, neighbourIdxStart, neighbourIdxEnd);
+ ca.spottedleaf.common.util.FlatBitsetUtil.clearRange(bitset, neighbourIdxStart, neighbourIdxEnd);
}
- while (shape.isXZRectangleFull(x, endX + 1, lastStartZ, z, endY + 1)) {
@@ -35834,7 +36169,7 @@ index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..0815741cb832b4be90c95747ca2b24f3
+ // test the whole XZ range
+ for (int testX = x, start = firstSetZY, end = lastSetZY; testX < endX;
+ ++testX, start += incX, end += incX) {
+ if (!ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.isRangeSet(bitset, start, end)) {
+ if (!ca.spottedleaf.common.util.FlatBitsetUtil.isRangeSet(bitset, start, end)) {
+ break y_merge;
+ }
}
@@ -35845,7 +36180,7 @@ index 810cc86e66c8f5ec050a5cc63dcf0b254b263131..0815741cb832b4be90c95747ca2b24f3
+ // passed, so we can clear it
+ for (int testX = x, start = firstSetZY, end = lastSetZY; testX < endX;
+ ++testX, start += incX, end += incX) {
+ ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.clearRange(bitset, start, end);
+ ca.spottedleaf.common.util.FlatBitsetUtil.clearRange(bitset, start, end);
+ }
}
@@ -36390,7 +36725,7 @@ index ec7834b53788f95ab7956c22bddfa38c4ee4e2f2..a612ace0b4e128c05196400b125a12a8
private static DiscreteVoxelShape makeSlice(final DiscreteVoxelShape delegate, final Direction.Axis axis, final int point) {
diff --git a/net/minecraft/world/phys/shapes/VoxelShape.java b/net/minecraft/world/phys/shapes/VoxelShape.java
index 9b210edf1f28285fc206644c5d81c7d05ea5a578..ddc562fbdeb2070212019bb23962538795d05ff6 100644
index 9b210edf1f28285fc206644c5d81c7d05ea5a578..cbf479b7337a78b9980926b8ba984c4546bf9c3d 100644
--- a/net/minecraft/world/phys/shapes/VoxelShape.java
+++ b/net/minecraft/world/phys/shapes/VoxelShape.java
@@ -18,60 +18,545 @@ import net.minecraft.world.phys.Vec3;
@@ -36742,7 +37077,7 @@ index 9b210edf1f28285fc206644c5d81c7d05ea5a578..ddc562fbdeb2070212019bb239625387
+ for (int x = sMinX; x < sMaxX; ++x) {
+ for (int y = sMinY; y < sMaxY; ++y) {
+ final int baseIndex = y*sizeZ + x*(sizeZ*sizeY);
+ if (!ca.spottedleaf.moonrise.common.util.FlatBitsetUtil.isRangeSet(bitset, baseIndex + sMinZ, baseIndex + sMaxZ)) {
+ if (!ca.spottedleaf.common.util.FlatBitsetUtil.isRangeSet(bitset, baseIndex + sMinZ, baseIndex + sMaxZ)) {
+ ret = Boolean.FALSE;
+ break check_full;
+ }
@@ -14,10 +14,10 @@ timestamp so that fs watchers can detect when RegionFiles are
modified.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
index 27eeb842e6b22bd12b582379eaaa76b622dfca5e..18eaedc587160a82b9351787830b1d57793356e4 100644
index 6dd6b4fb79870da6d3bf54dc813ae685237d1f0e..09205efff3a1a2042e67600510af270df9e46c67 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -1271,6 +1271,14 @@ public final class MoonriseRegionFileIO {
@@ -1309,6 +1309,14 @@ public final class MoonriseRegionFileIO {
try {
this.regionDataController.finishWrite(this.chunkX, this.chunkZ, writeData);
@@ -5,10 +5,10 @@ Subject: [PATCH] Remove debug-like logging
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 4cfd50460707ad40498b0e2f5b891811fd99a6ff..f01fede96872749f1ac664d0c53c2ef3617bed0e 100644
index b84690962b9f797f95778a7ecbe0c4e398643643..8305d15e8510c09e4a3cdaa78ff1f96a620fc940 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1754,7 +1754,7 @@ public class ServerGamePacketListenerImpl
@@ -1760,7 +1760,7 @@ public class ServerGamePacketListenerImpl
private void forceSendPlayerSupportBlocks() {
if (this.tickCount >= this.lastSupportedBlocksSend + 200) {
this.lastSupportedBlocksSend = this.tickCount;
@@ -16,7 +16,7 @@ This lets us get faster foreach iteration, as well as avoids map lookups on
the values when needed.
diff --git a/net/minecraft/world/level/pathfinder/PathFinder.java b/net/minecraft/world/level/pathfinder/PathFinder.java
index 8f29c76b050e6d5cc3f93ce008be2de1e869b2d6..3bb5513cf5a1f13746cb3e9d7e56bae15b8c7234 100644
index 8f29c76b050e6d5cc3f93ce008be2de1e869b2d6..b903ae067130b460fca782fa8f37e9405670eeee 100644
--- a/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -55,20 +55,24 @@ public class PathFinder {
@@ -92,8 +92,8 @@ index 8f29c76b050e6d5cc3f93ce008be2de1e869b2d6..3bb5513cf5a1f13746cb3e9d7e56bae1
+ Path best = null;
+ boolean entryListIsEmpty = reachedTargets.isEmpty();
+ Comparator<Path> comparator = entryListIsEmpty
+ ? Comparator.comparingInt(Path::getNodeCount)
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
+ ? Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)
+ : Comparator.comparingInt(Path::getNodeCount);
+ for (Map.Entry<Target, BlockPos> entry : entryListIsEmpty ? targets : reachedTargets) {
+ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty);
+ if (best == null || comparator.compare(path, best) < 0) {
@@ -174,7 +174,7 @@ index 8768e42dd359a7d7c2b7fb715482d74b3a2ee546..1b83d541378c98e3517904973e3ea4e3
@Override
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 279614d017877ea2ba7c216b9cc874065f5e384d..88148640e3476c041f589b3991d8e5b7bfde1613 100644
index ca793f3f7300148cd55d2e873af5b43d9f4c708f..8389d812b2d80a122fd1945b3182c08cdeda7d1c 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -636,7 +636,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -187,10 +187,10 @@ index 279614d017877ea2ba7c216b9cc874065f5e384d..88148640e3476c041f589b3991d8e5b7
this.weatherData.setLevel(this);
this.typeKey = typeKey;
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index 42a5b29648d318d27998f5732045f375c5b8c385..2ec5cc549ccaf5ecdf991241cfa2fc11cdec6aaa 100644
index 0ce4e8be3862b90ade6ddea710e47b7eb96c8942..a901aa6547c52643d11249c201688341e2961f01 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -325,6 +325,7 @@ public class ServerPlayerGameMode {
@@ -326,6 +326,7 @@ public class ServerPlayerGameMode {
this.abortDestroyBlock(pos, sequence);
}
}
@@ -215,7 +215,7 @@ index 22b10500ef74694243a4fec40822bb54ef96cc0c..196c01fe5f200ed57e6f23e0939cac61
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), connection.getPlayer().getBukkitEntity()).callEvent();
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index f4e2261a0ffb1d763c1e6a7b353b181178434471..42fd84f078eb3268d820de8f211e78023eab85f9 100644
index 459dd3ae3c9a1c303b8c4f6606d4d2f81c2a532c..a7f589970a04e520eb5cbe6dfeb333bc9cd479a8 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -334,7 +334,7 @@ public abstract class PlayerList {
@@ -345,7 +345,7 @@ index b2c6bcb8d82fc01bf4e8540c6d9f6bc94feb3659..dc0270de6d13b7b6fc5de463fab05e9c
public int getSerializedSize() {
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
index a799c2e24b9990b1dc9b8608231a9801d4036493..9c4eb6c151307240f3fa7f5053d48bded003edbe 100644
index 9213568da8d590b2f81ba3a51e216ec395badb31..55037971b2631100ac5fd5fd8157adbbc0604d36 100644
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -26,6 +26,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -530,8 +530,8 @@ index a799c2e24b9990b1dc9b8608231a9801d4036493..9c4eb6c151307240f3fa7f5053d48bde
+ return DataResult.success(new PalettedContainer<>(strategy, storedConfiguration, storage, palette, paletteEntries, defaultValue, presetValues)); // Paper - Anti-Xray - Add preset values
}
@Override
@@ -330,12 +414,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
// Paper start - optimise PalettedContainer packing
@@ -404,12 +488,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@Override
public PalettedContainer<T> copy() {
@@ -546,7 +546,7 @@ index a799c2e24b9990b1dc9b8608231a9801d4036493..9c4eb6c151307240f3fa7f5053d48bde
}
@Override
@@ -417,9 +501,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -491,9 +575,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return 1 + this.palette.getSerializedSize(globalMap) + this.storage.getRaw().length * 8;
}
@@ -634,7 +634,7 @@ index 5c518b6ec7da546460884c37e9af682b6ab9fc22..958be147cd940ac430576ca5b4ada70f
private static final Palette.Factory HASHMAP_PALETTE_FACTORY = HashMapPalette::create;
private static final Configuration ZERO_BITS = new Configuration.Simple(SINGLE_VALUE_PALETTE_FACTORY, 0);
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index f099aa45853b4e21b4a6e8052fa6848da6c4ed0b..1bfb83a0194bf5d802370ae53d4cbfeca0069584 100644
index 5b311dc7f0a9d7cb202011302920478977f27bb0..84a92dc868e61969460dddb156af332e6384bcd1 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -128,6 +128,7 @@ public record SerializableChunkData(
@@ -10,10 +10,10 @@ hoping that at least then we don't swap chunks, and maybe recover
them all.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
index 18eaedc587160a82b9351787830b1d57793356e4..3bb9b58ee97464687e348e23b99159226415c267 100644
index 09205efff3a1a2042e67600510af270df9e46c67..775d93d35855e394e5eccf0ad80eca43b1ed9562 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -1474,7 +1474,7 @@ public final class MoonriseRegionFileIO {
@@ -1547,7 +1547,7 @@ public final class MoonriseRegionFileIO {
public abstract void finishWrite(final int chunkX, final int chunkZ, final WriteData writeData) throws IOException;
@@ -800,7 +800,7 @@ index 590bd1ca60956e5c5be58481f97401e55f9e1aeb..4e0c9fa1eecfa9f21285b7911e25830b
return new RegionStorageInfo(this.level, this.dimension, this.type + suffix);
}
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 1bfb83a0194bf5d802370ae53d4cbfeca0069584..3781b2707163357bae5f5482694c94a927b54d58 100644
index 84a92dc868e61969460dddb156af332e6384bcd1..3fef98e8c3c9908c6f05ded33596cbcb18996c3d 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -119,6 +119,18 @@ public record SerializableChunkData(
@@ -822,7 +822,7 @@ index 1bfb83a0194bf5d802370ae53d4cbfeca0069584..3781b2707163357bae5f5482694c94a9
// Paper start - Do not let the server load chunks from newer versions
private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().dataVersion().version();
@@ -526,7 +538,7 @@ public record SerializableChunkData(
@@ -528,7 +540,7 @@ public record SerializableChunkData(
tag.putInt("xPos", this.chunkPos.x());
tag.putInt("yPos", this.minSectionY);
tag.putInt("zPos", this.chunkPos.z());
@@ -6,7 +6,7 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc313d0ef17b 100644
index 8305d15e8510c09e4a3cdaa78ff1f96a620fc940..cc0d455f88bc7c5798ea27abfaa3333c2656eb92 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -647,6 +647,7 @@ public class ServerGamePacketListenerImpl
@@ -71,7 +71,7 @@ index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc31
}
@Override
@@ -1570,7 +1605,7 @@ public class ServerGamePacketListenerImpl
@@ -1576,7 +1611,7 @@ public class ServerGamePacketListenerImpl
}
}
@@ -80,7 +80,7 @@ index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc31
xDist = targetX - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
yDist = targetY - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
zDist = targetZ - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -1600,6 +1635,7 @@ public class ServerGamePacketListenerImpl
@@ -1606,6 +1641,7 @@ public class ServerGamePacketListenerImpl
this.player.move(MoverType.PLAYER, new Vec3(xDist, yDist, zDist));
this.player.onGround = isOnGround; // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
@@ -88,7 +88,7 @@ index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc31
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1633,7 +1669,17 @@ public class ServerGamePacketListenerImpl
@@ -1639,7 +1675,17 @@ public class ServerGamePacketListenerImpl
}
// Paper start - Add fail move event
@@ -107,7 +107,7 @@ index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc31
if (!allowMovement) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
targetX, targetY, targetZ, targetYRot, targetXRot, false);
@@ -1781,7 +1827,7 @@ public class ServerGamePacketListenerImpl
@@ -1787,7 +1833,7 @@ public class ServerGamePacketListenerImpl
private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) {
@@ -116,7 +116,7 @@ index f01fede96872749f1ac664d0c53c2ef3617bed0e..ce2120d187454921bde6b7bd1787bc31
this.awaitingTeleportTime = this.tickCount;
this.teleport(
this.awaitingPositionFromClient.x,
@@ -1800,6 +1846,34 @@ public class ServerGamePacketListenerImpl
@@ -1806,6 +1852,34 @@ public class ServerGamePacketListenerImpl
}
}
@@ -42,10 +42,10 @@ index 206a897e9d74b48d38e2ea1652e9b7ed4735f828..fee899044c389003a1f976f04b752bc7
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 2dec44b08e6932da87c88233743e7ace51f7af6f..974101843195dd9e37072500e1e392f80700276a 100644
index a6fb79a70de177fcc027ddb0c5ae6fe3ed3c0407..c1f6f20247e85c98fbefaee707c1532e8bca64f1 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -529,7 +529,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -534,7 +534,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private void tickChunks(final ProfilerFiller profiler) {
profiler.push("naturalSpawnCount");
int chunkCount = this.distanceManager.getNaturalSpawnChunkCount();
@@ -65,7 +65,7 @@ index 2dec44b08e6932da87c88233743e7ace51f7af6f..974101843195dd9e37072500e1e392f8
this.lastSpawnState = spawnCookie;
boolean doMobSpawning = this.level.getGameRules().get(GameRules.SPAWN_MOBS) && !this.level.players().isEmpty(); // CraftBukkit
int tickSpeed = this.level.getGameRules().get(GameRules.RANDOM_TICK_SPEED);
@@ -557,7 +568,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -562,7 +573,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
profiler.popPush("shuffleSpawningChunks");
// Paper start - chunk tick iteration optimisation
this.shuffleRandom.setSeed(this.level.getRandom().nextLong());
@@ -37,10 +37,10 @@ index fee899044c389003a1f976f04b752bc78e2bfb69..b4d62fac8af59f98463f55f2b864343b
// Paper end - Optional per player mob spawns
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 974101843195dd9e37072500e1e392f80700276a..cdf64cbd84460f88d29583e9bd3bc644eb607395 100644
index c1f6f20247e85c98fbefaee707c1532e8bca64f1..66d706d2a7995b437d102903012a714c38e4876c 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -534,7 +534,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -539,7 +539,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
// re-set mob counts
for (ServerPlayer player : this.level.players()) {
@@ -5,10 +5,10 @@ Subject: [PATCH] DataConverter, Moonrise & co fixes
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index ce2120d187454921bde6b7bd1787bc313d0ef17b..572b28fa8df0f441c07c5728e5b95c0337b189c0 100644
index cc0d455f88bc7c5798ea27abfaa3333c2656eb92..e24c7e2db785bce4a8801373d8e2bcd25477dbb6 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1850,9 +1850,14 @@ public class ServerGamePacketListenerImpl
@@ -1856,9 +1856,14 @@ public class ServerGamePacketListenerImpl
private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
final List<AABB> collisionsBB = new java.util.ArrayList<>();
final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
@@ -34,19 +34,20 @@
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
ByteBufCodecs::optional
);
@@ -93,7 +_,25 @@
@@ -93,7 +_,26 @@
return ExtraCodecs.orCompressed(contentsCodec, discriminatorCodec);
}
+ // Paper start - adventure; create separate codec for each locale
+ private static final java.util.Map<java.util.Locale, Codec<Component>> LOCALIZED_CODECS = new java.util.concurrent.ConcurrentHashMap<>();
+ private static final com.google.common.cache.LoadingCache<java.util.Locale, Codec<Component>> LOCALIZED_CODECS = com.google.common.cache.CacheBuilder.newBuilder()
+ .maximumSize(256)
+ .build(com.google.common.cache.CacheLoader.from(loc -> Codec.recursive("Component", selfCodec -> createCodec(selfCodec, loc))));
+
+ public static Codec<Component> localizedCodec(final java.util.@org.checkerframework.checker.nullness.qual.Nullable Locale locale) {
+ if (locale == null) {
+ return CODEC;
+ }
+ return LOCALIZED_CODECS.computeIfAbsent(locale,
+ loc -> Codec.recursive("Component", selfCodec -> createCodec(selfCodec, loc)));
+ return LOCALIZED_CODECS.getUnchecked(locale);
+ }
+ // Paper end - adventure; create separate codec for each locale
+
@@ -0,0 +1,11 @@
--- a/net/minecraft/network/protocol/game/ServerboundSetGameRulePacket.java
+++ b/net/minecraft/network/protocol/game/ServerboundSetGameRulePacket.java
@@ -12,7 +_,7 @@
public record ServerboundSetGameRulePacket(List<ServerboundSetGameRulePacket.Entry> entries) implements Packet<ServerGamePacketListener> {
public static final StreamCodec<ByteBuf, ServerboundSetGameRulePacket> STREAM_CODEC = StreamCodec.composite(
- ServerboundSetGameRulePacket.Entry.STREAM_CODEC.apply(ByteBufCodecs.list()), ServerboundSetGameRulePacket::entries, ServerboundSetGameRulePacket::new
+ ServerboundSetGameRulePacket.Entry.STREAM_CODEC.apply(ByteBufCodecs.list(128)), ServerboundSetGameRulePacket::entries, ServerboundSetGameRulePacket::new // Paper - add limit
);
@Override
@@ -1504,7 +1504,7 @@
}
@Override
@@ -2114,4 +_,24 @@
@@ -2114,4 +_,28 @@
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
@@ -1518,14 +1518,18 @@
+ // Paper end - check global player list where appropriate
+
+ // Paper start - lag compensation
+ private long lagCompensationTick = MinecraftServer.SERVER_INIT;
+ private long lagCompensationTick = currentLagCompensationTick();
+
+ public long getLagCompensationTick() {
+ return this.lagCompensationTick;
+ }
+
+ public void updateLagCompensationTick() {
+ this.lagCompensationTick = (System.nanoTime() - MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
+ this.lagCompensationTick = currentLagCompensationTick();
+ }
+
+ private static long currentLagCompensationTick() {
+ return (System.nanoTime() - MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
+ }
+ // Paper end - lag compensation
}
@@ -694,6 +694,26 @@
}
public boolean isReceivingWaypoints() {
@@ -1057,6 +_,19 @@
this.connection.send(new ClientboundPostEffectsPacket(this.postEffects));
}
+ // Paper start - Post effects API
+ public boolean setPostEffects(final Collection<Identifier> postEffects) {
+ if (com.google.common.collect.Iterables.elementsEqual(this.postEffects, postEffects)) {
+ return false;
+ }
+
+ this.postEffects.clear();
+ this.postEffects.addAll(postEffects);
+ this.postEffectsDirty = true;
+ return true;
+ }
+ // Paper end - Post effects API
+
public boolean addPostEffect(final Identifier postEffect) {
if (this.postEffects.contains(postEffect)) {
return false;
@@ -1103,15 +_,17 @@
if (block instanceof RespawnAnchorBlock && (forced || blockState.getValue(RespawnAnchorBlock.CHARGE) > 0) && RespawnAnchorBlock.canSetSpawn(level, pos)
)
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -52,17 +_,37 @@
@@ -52,17 +_,38 @@
private BlockPos delayedDestroyPos = BlockPos.ZERO;
private int delayedTickStart;
private int lastSentState = -1;
@@ -10,6 +10,7 @@
public ServerPlayerGameMode(final ServerPlayer player) {
this.player = player;
this.level = player.level();
+ this.gameTicks = (int) this.level.getLagCompensationTick(); // Paper - lag compensate eating; start in the same clock as tick()
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
@@ -57,7 +58,7 @@
}
protected void setGameModeForPlayer(final GameType gameModeForPlayer, final @Nullable GameType previousGameModeForPlayer) {
@@ -111,10 +_,11 @@
@@ -111,20 +_,27 @@
}
public void tick() {
@@ -71,8 +72,11 @@
+ if (blockState == null || blockState.isAir()) { // Paper - Don't allow digging into unloaded chunks
this.hasDelayedDestroy = false;
} else {
float destroyProgress = this.incrementDestroyProgress(blockState, this.delayedDestroyPos, this.delayedTickStart);
@@ -124,7 +_,13 @@
- float destroyProgress = this.incrementDestroyProgress(blockState, this.delayedDestroyPos, this.delayedTickStart);
+ float destroyProgress = this.incrementDestroyProgress(blockState, this.delayedDestroyPos, this.gameTicks - this.delayedTickStart); // Paper - fix delayed destroy using the start tick as ticks spent destroying
if (destroyProgress >= 1.0F) {
this.hasDelayedDestroy = false;
this.destroyBlock(this.delayedDestroyPos);
}
}
} else if (this.isDestroyingBlock) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/network/ServerCommandSuggestionsProvider.java
+++ b/net/minecraft/server/network/ServerCommandSuggestionsProvider.java
@@ -47,6 +_,13 @@
@@ -47,11 +_,25 @@
MinecraftServer server = this.player.level().getServer();
CommandDispatcher<CommandSourceStack> dispatcher = server.getCommands().getDispatcher();
ParseResults<CommandSourceStack> parse = dispatcher.parse(reader, this.player.createCommandSourceStack());
@@ -14,3 +14,16 @@
if (this.lastRequest.get() != null) {
return;
}
- dispatcher.getCompletionSuggestions(parse).thenAccept(suggestions -> request.future.complete(limitSuggestionCount(suggestions)));
+ // Paper start - Option to disable sending of namespaced commands
+ dispatcher.getCompletionSuggestions(parse).thenAccept(suggestions -> {
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && suggestions.getRange().getStart() <= 1) {
+ suggestions.getList().removeIf(suggestion -> suggestion.getText().contains(":"));
+ }
+ request.future.complete(limitSuggestionCount(suggestions));
+ });
+ // Paper end - Option to disable sending of namespaced commands
} catch (Exception e) {
LOGGER.error("Failed to resolve command suggestions for {}", this.player.getGameProfile().name(), e);
}
@@ -318,7 +318,7 @@
+
+ // Prevent 40 event-calls for less than a single pixel of movement >.>
+ double delta = Mth.square(this.lastPosX - to.getX()) + Mth.square(this.lastPosY - to.getY()) + Mth.square(this.lastPosZ - to.getZ());
+ float deltaAngle = Math.abs(this.lastYRot - to.getYaw()) + Math.abs(this.lastXRot - to.getPitch());
+ float deltaAngle = Math.abs(Mth.wrapDegrees(this.lastYRot - to.getYaw())) + Math.abs(this.lastXRot - to.getPitch());
+
+ if ((delta > 1.0F / 256 || deltaAngle > 10.0F) && !this.player.isImmobile()) {
+ this.lastPosX = to.getX();
@@ -382,7 +382,7 @@
this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering());
}
@@ -610,8 +_,82 @@
@@ -610,18 +_,98 @@
}
}
@@ -452,8 +452,7 @@
+ }
+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join();
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, packet.command());
+ suggestEvent.setCancelled(suggestions.isEmpty());
+ if (suggestEvent.callEvent()) {
+ if (suggestEvent.callEvent() && !suggestEvent.getSuggestions().isEmpty()) { // prevents [<args>] from showing for plugins with nothing more to offer
+ this.connection.send(new ClientboundCommandSuggestionsPacket(
+ packet.id(), ServerCommandSuggestionsProvider.limitSuggestionCount(suggestEvent.getSuggestions())
+ ));
@@ -465,7 +464,17 @@
int clientId = packet.id();
this.commandSuggestionsProvider
.request(packet.command())
@@ -621,7 +_,7 @@
- .thenAccept(suggestions -> this.send(new ClientboundCommandSuggestionsPacket(clientId, suggestions)));
+ .thenAccept(suggestions -> {
+ // Paper start
+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, packet.command());
+ if (suggestEvent.callEvent() && !suggestEvent.getSuggestions().isEmpty()) { // prevents [<args>] from showing for plugins with nothing more to offer
+ this.send(new ClientboundCommandSuggestionsPacket(clientId, ServerCommandSuggestionsProvider.limitSuggestionCount(suggestEvent.getSuggestions())));
+ }
+ // Paper end
+ });
}
@Override
public void handleSetCommandBlock(final ServerboundSetCommandBlockPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
@@ -878,7 +887,7 @@
+
+ // Prevent 40 event-calls for less than a single pixel of movement >.>
+ double delta = Mth.square(this.lastPosX - to.getX()) + Mth.square(this.lastPosY - to.getY()) + Mth.square(this.lastPosZ - to.getZ());
+ float deltaAngle = Math.abs(this.lastYRot - to.getYaw()) + Math.abs(this.lastXRot - to.getPitch());
+ float deltaAngle = Math.abs(Mth.wrapDegrees(this.lastYRot - to.getYaw())) + Math.abs(this.lastXRot - to.getPitch());
+
+ if ((delta > 1.0F / 256 || deltaAngle > 10.0F) && !this.player.isImmobile()) {
+ this.lastPosX = to.getX();
@@ -738,7 +738,7 @@
}
public UserWhiteList getWhiteList() {
@@ -658,12 +_,20 @@
@@ -658,12 +_,23 @@
public void sendLevelInfo(final ServerPlayer player, final ServerLevel level) {
WorldBorder worldBorder = level.getWorldBorder();
player.connection.send(new ClientboundInitializeBorderPacket(worldBorder));
@@ -759,6 +759,9 @@
+ // player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, level.getThunderLevel(1.0F)));
+ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false);
+ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel);
+ } else {
+ player.setPlayerWeather(org.bukkit.WeatherType.CLEAR, false);
+ player.updateWeather(-1.0F, level.rainLevel, -1.0F, level.thunderLevel);
+ // CraftBukkit end
}
@@ -45,10 +45,10 @@
}
+
+ // Paper start - track position inside effect was triggered on
+ private net.minecraft.core.BlockPos currentBlockPos = null;
+ private net.minecraft.core.@org.jspecify.annotations.Nullable BlockPos currentBlockPos = null;
+
+ private Consumer<Entity> recorded(final InsideBlockEffectType type) {
+ return new RecordedEffect(this.currentBlockPos.immutable(), type.effect());
+ return new RecordedEffect(java.util.Objects.requireNonNull(this.currentBlockPos, "Cannot record effect without a current block position set").immutable(), type.effect());
+ }
+
+ record RecordedEffect(
@@ -12,3 +12,23 @@
return isValidTarget ? transportItemTarget : null;
}
@@ -377,8 +_,17 @@
}
private boolean targetHasNotChanged(final Level level, final TransportItemsBetweenContainers.TransportItemTarget target) {
- return target.blockEntity.equals(level.getBlockEntity(target.pos));
- }
+ // Paper start
+ return target.blockEntity.equals(level.getBlockEntity(target.pos)) && !isContainerRemoved(target.container);
+ }
+
+ private static boolean isContainerRemoved(final Container container) {
+ if (container instanceof net.minecraft.world.CompoundContainer compoundContainer) {
+ return isContainerRemoved(compoundContainer.container1) || isContainerRemoved(compoundContainer.container2);
+ }
+ return container instanceof BlockEntity blockEntity && blockEntity.isRemoved();
+ }
+ // Paper end
private Stream<TransportItemsBetweenContainers.TransportItemTarget> getConnectedTargets(
final TransportItemsBetweenContainers.TransportItemTarget target, final Level level
@@ -19,3 +19,11 @@
}
@Override
@@ -117,6 +_,7 @@
BlockPos blockPos = this.blockPosition();
FluidState fluidState = level.getBlockState(blockPos).getFluidState();
if (this.collidedWithFluid(fluidState, blockPos, this.position(), this.position())) {
+ this.insideEffectCollector.advanceStep(0, blockPos); // Paper - track position inside effect was triggered on
fluidState.entityInside(level, blockPos, this, this.insideEffectCollector);
this.insideEffectCollector.applyAndClear(this);
}
@@ -156,6 +156,17 @@
this.playSound(this.getEjectSound());
this.pickupTimer = 100;
}
@@ -747,6 +_,10 @@
double sulfurCubeTopPosition = sulfurCubeBottomPosition + this.getBbHeight();
double pusherTopPosition = pusherFeetPosition + pusher.getBbHeight();
if (cubeToPusher.horizontalDistance() < 1.3F && pusherFeetPosition <= sulfurCubeTopPosition && pusherTopPosition > sulfurCubeBottomPosition) {
+ // Paper start - Add EntityCollideWithEntity Event
+ if (io.papermc.paper.event.entity.EntityCollideWithEntityEvent.getHandlerList().getRegisteredListeners().length != 0 &&
+ !new io.papermc.paper.event.entity.EntityCollideWithEntityEvent(this.getBukkitEntity(), pusher.getBukkitEntity()).callEvent()) return;
+ // Paper end - Add EntityCollideWithEntity Event
double knockback = Math.max(0.0, 1.0 - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
Vec3 pushDirection = cubeToPusher.horizontal().normalize().scale(knockback);
float pushSpeedScale = player.isPassenger() ? 0.16F : 0.3F;
@@ -826,7 +_,7 @@
}
@@ -0,0 +1,14 @@
--- a/net/minecraft/world/item/CushionItem.java
+++ b/net/minecraft/world/item/CushionItem.java
@@ -59,6 +_,11 @@
}
cushion.snapTo(entityPos, Direction.fromYRot(placeContext.getRotation()).toYRot(), 0.0F);
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, cushion).isCancelled()) {
+ return InteractionResult.FAIL;
+ }
+ // Paper end
serverLevel.addFreshEntity(cushion);
cushion.destroyIfInFire(serverLevel);
level.playSound(null, cushion.getX(), cushion.getY(), cushion.getZ(), SoundEvents.CUSHION_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F);
@@ -1,42 +0,0 @@
--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParamSets.java
+++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParamSets.java
@@ -35,6 +_,27 @@
.required(LootContextParams.ENCHANTMENT_ACTIVE)
.required(LootContextParams.ENCHANTMENT_LEVEL)
);
+ // Paper start
+ public static final ContextKeySet ALL_PARAMS_OPTIONAL = register(
+ "generic_optional",
+ builder -> builder.optional(LootContextParams.THIS_ENTITY)
+ .optional(LootContextParams.LAST_DAMAGE_PLAYER)
+ .optional(LootContextParams.DAMAGE_SOURCE)
+ .optional(LootContextParams.ATTACKING_ENTITY)
+ .optional(LootContextParams.DIRECT_ATTACKING_ENTITY)
+ .optional(LootContextParams.ORIGIN)
+ .optional(LootContextParams.BLOCK_STATE)
+ .optional(LootContextParams.BLOCK_ENTITY)
+ .optional(LootContextParams.TOOL)
+ .optional(LootContextParams.EXPLOSION_RADIUS)
+ .optional(LootContextParams.ADDITIONAL_COST_COMPONENT_ALLOWED)
+ .optional(LootContextParams.CONTAINER)
+ .optional(LootContextParams.INTERACTING_ENTITY)
+ .optional(LootContextParams.TARGET_ENTITY)
+ .optional(LootContextParams.ENCHANTMENT_ACTIVE)
+ .optional(LootContextParams.ENCHANTMENT_LEVEL)
+ );
+ // Paper end
public static final ContextKeySet CHEST = register("chest", builder -> builder.required(LootContextParams.ORIGIN).optional(LootContextParams.THIS_ENTITY));
public static final ContextKeySet COMMAND = register(
"command", builder -> builder.required(LootContextParams.ORIGIN).optional(LootContextParams.THIS_ENTITY)
@@ -194,5 +_,11 @@
if (!missingFromAllParams.isEmpty()) {
throw new IllegalStateException("Missing parameters from 'all_params': " + missingFromAllParams);
}
+ // Paper start
+ Set<ContextKey<?>> missingFromAllParamsOptional = Sets.difference(allParams, ALL_PARAMS_OPTIONAL.allowed());
+ if (!missingFromAllParamsOptional.isEmpty()) {
+ throw new IllegalStateException("Missing parameters from 'all_params_optional': " + missingFromAllParamsOptional);
+ }
+ // Paper end
}
}
@@ -1,109 +0,0 @@
package ca.spottedleaf.moonrise.common.util;
import java.util.Objects;
public final class FlatBitsetUtil {
private static final int LOG2_LONG = 6;
private static final long ALL_SET = -1L;
private static final int BITS_PER_LONG = Long.SIZE;
// from inclusive
// to exclusive
public static int firstSet(final long[] bitset, final int from, final int to) {
if ((from | to | (to - from)) < 0) {
throw new IndexOutOfBoundsException();
}
int bitsetIdx = from >>> LOG2_LONG;
int bitIdx = from & ~(BITS_PER_LONG - 1);
long tmp = bitset[bitsetIdx] & (ALL_SET << from);
for (;;) {
if (tmp != 0L) {
final int ret = bitIdx | Long.numberOfTrailingZeros(tmp);
return ret >= to ? -1 : ret;
}
bitIdx += BITS_PER_LONG;
if (bitIdx >= to) {
return -1;
}
tmp = bitset[++bitsetIdx];
}
}
// from inclusive
// to exclusive
public static int firstClear(final long[] bitset, final int from, final int to) {
if ((from | to | (to - from)) < 0) {
throw new IndexOutOfBoundsException();
}
// like firstSet, but invert the bitset
int bitsetIdx = from >>> LOG2_LONG;
int bitIdx = from & ~(BITS_PER_LONG - 1);
long tmp = (~bitset[bitsetIdx]) & (ALL_SET << from);
for (;;) {
if (tmp != 0L) {
final int ret = bitIdx | Long.numberOfTrailingZeros(tmp);
return ret >= to ? -1 : ret;
}
bitIdx += BITS_PER_LONG;
if (bitIdx >= to) {
return -1;
}
tmp = ~bitset[++bitsetIdx];
}
}
// from inclusive
// to exclusive
public static void clearRange(final long[] bitset, final int from, int to) {
if ((from | to | (to - from)) < 0) {
throw new IndexOutOfBoundsException();
}
if (from == to) {
return;
}
--to;
final int fromBitsetIdx = from >>> LOG2_LONG;
final int toBitsetIdx = to >>> LOG2_LONG;
final long keepFirst = ~(ALL_SET << from);
final long keepLast = ~(ALL_SET >>> ((BITS_PER_LONG - 1) ^ to));
Objects.checkFromToIndex(fromBitsetIdx, toBitsetIdx, bitset.length);
if (fromBitsetIdx == toBitsetIdx) {
// special case: need to keep both first and last
bitset[fromBitsetIdx] &= (keepFirst | keepLast);
} else {
bitset[fromBitsetIdx] &= keepFirst;
for (int i = fromBitsetIdx + 1; i < toBitsetIdx; ++i) {
bitset[i] = 0L;
}
bitset[toBitsetIdx] &= keepLast;
}
}
// from inclusive
// to exclusive
public static boolean isRangeSet(final long[] bitset, final int from, final int to) {
return firstClear(bitset, from, to) == -1;
}
private FlatBitsetUtil() {}
}
@@ -1,5 +1,8 @@
package io.papermc.paper.adventure;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.serialization.JavaOps;
import io.netty.util.AttributeKey;
@@ -10,7 +13,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -221,16 +223,18 @@ public final class PaperAdventure {
.anyMatch(t -> t.hasAnyTranslations().toBooleanOrElse(true));
}
private static final Map<Locale, com.mojang.serialization.Codec<Component>> LOCALIZED_CODECS = new ConcurrentHashMap<>();
private static final LoadingCache<Locale, com.mojang.serialization.Codec<Component>> LOCALIZED_CODECS = CacheBuilder.newBuilder()
.maximumSize(256)
.build(CacheLoader.from(locale -> AdventureCodecs.COMPONENT_CODEC.xmap(
component -> component, // decode
component -> translated(component, locale) // encode
)));
public static com.mojang.serialization.Codec<Component> localizedCodec(final @Nullable Locale l) {
if (l == null) {
return AdventureCodecs.COMPONENT_CODEC;
}
return LOCALIZED_CODECS.computeIfAbsent(l, locale -> AdventureCodecs.COMPONENT_CODEC.xmap(
component -> component, // decode
component -> translated(component, locale) // encode
));
return LOCALIZED_CODECS.getUnchecked(l);
}
public static String asPlain(final Component component, final Locale locale) {
@@ -6,11 +6,9 @@ import io.papermc.paper.datacomponent.item.PaperAttackRange;
import io.papermc.paper.datacomponent.item.PaperBannerPatternLayers;
import io.papermc.paper.datacomponent.item.PaperBlockItemDataProperties;
import io.papermc.paper.datacomponent.item.PaperBlocksAttacks;
import io.papermc.paper.datacomponent.item.PaperBrewingFuel;
import io.papermc.paper.datacomponent.item.PaperBundleContents;
import io.papermc.paper.datacomponent.item.PaperChargedProjectiles;
import io.papermc.paper.datacomponent.item.PaperConsumable;
import io.papermc.paper.datacomponent.item.PaperCookingFuel;
import io.papermc.paper.datacomponent.item.PaperCustomModelData;
import io.papermc.paper.datacomponent.item.PaperDamageResistant;
import io.papermc.paper.datacomponent.item.PaperDeathProtection;
@@ -228,8 +226,6 @@ public final class DataComponentAdapters {
register(DataComponents.SIGN_TEXT_BACK, PaperSignText::new);
registerUntyped(DataComponents.WAXED);
register(DataComponents.CUSHION_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.COOKING_FUEL, PaperCookingFuel::new);
register(DataComponents.BREWING_FUEL, PaperBrewingFuel::new);
for (final ResourceKey<DataComponentType<?>> key : BuiltInRegistries.DATA_COMPONENT_TYPE.registryKeySet()) {
if (!ADAPTERS.containsKey(key)) {
@@ -307,13 +307,4 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
public SignText.Builder signText() {
return new PaperSignText.BuilderImpl();
}
@Override
public BrewingFuel.Builder brewingFuel() {
return new PaperBrewingFuel.BuilderImpl();
}
@Override
public CookingFuel.Builder cookingFuel() {
return new PaperCookingFuel.BuilderImpl();
}
}
@@ -1,55 +0,0 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.loot.number.PaperResolvableFloat;
import io.papermc.paper.loot.number.PaperResolvableInt;
import net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat;
import net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperBrewingFuel(
net.minecraft.world.item.component.BrewingFuel impl
) implements BrewingFuel, Handleable<net.minecraft.world.item.component.BrewingFuel> {
@Override
public net.minecraft.world.item.component.BrewingFuel getHandle() {
return this.impl;
}
@Override
public io.papermc.paper.loot.number.ResolvableInt uses() {
return PaperResolvableInt.fromVanilla(this.impl.uses());
}
@Override
public io.papermc.paper.loot.number.ResolvableFloat speedMultiplier() {
return PaperResolvableFloat.fromVanilla(this.impl.speedMultiplier());
}
static final class BuilderImpl implements BrewingFuel.Builder {
private int uses = 0;
private float speedMultiplier = 1.0F;
@Override
public Builder uses(int uses) {
this.uses = uses;
return this;
}
@Override
public Builder speedMultiplier(float speedMultiplier) {
this.speedMultiplier = speedMultiplier;
return this;
}
@Override
public BrewingFuel build() {
return new PaperBrewingFuel(
new net.minecraft.world.item.component.BrewingFuel(
new ResolvableInt.Constant(this.uses),
new ResolvableFloat.Constant(this.speedMultiplier)
)
);
}
}
}
@@ -1,55 +0,0 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.loot.number.PaperResolvableFloat;
import io.papermc.paper.loot.number.PaperResolvableInt;
import net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat;
import net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperCookingFuel(
net.minecraft.world.item.component.CookingFuel impl
) implements CookingFuel, Handleable<net.minecraft.world.item.component.CookingFuel> {
@Override
public net.minecraft.world.item.component.CookingFuel getHandle() {
return this.impl;
}
@Override
public io.papermc.paper.loot.number.ResolvableInt burnTime() {
return PaperResolvableInt.fromVanilla(this.impl.burnTime());
}
@Override
public io.papermc.paper.loot.number.ResolvableFloat speedMultiplier() {
return PaperResolvableFloat.fromVanilla(this.impl.speedMultiplier());
}
static final class BuilderImpl implements CookingFuel.Builder {
private int burnTime = 0;
private float speedMultiplier = 1.0F;
@Override
public Builder burnTime(final int burnTime) {
this.burnTime = burnTime;
return this;
}
@Override
public Builder speedMultiplier(final float speedMultiplier) {
this.speedMultiplier = speedMultiplier;
return this;
}
@Override
public CookingFuel build() {
return new PaperCookingFuel(
new net.minecraft.world.item.component.CookingFuel(
new ResolvableInt.Constant(this.burnTime),
new ResolvableFloat.Constant(this.speedMultiplier)
)
);
}
}
}
@@ -0,0 +1,59 @@
package io.papermc.paper.entity;
import com.google.common.base.Preconditions;
import io.papermc.paper.adventure.PaperAdventure;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.SequencedCollection;
import net.kyori.adventure.key.Key;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import org.jspecify.annotations.NullMarked;
@NullMarked
public final class PaperPlayerPostEffects implements PlayerPostEffects {
private final ServerPlayer handle;
public PaperPlayerPostEffects(final ServerPlayer handle) {
this.handle = handle;
}
private ServerPlayer getHandle() {
return this.handle;
}
@Override
public List<Key> values() {
return this.getHandle().getPostEffects().stream().map(PaperAdventure::asAdventure).toList();
}
@Override
public boolean set(final SequencedCollection<Key> postEffects) {
Preconditions.checkArgument(postEffects != null, "postEffects cannot be null");
final LinkedHashSet<Identifier> ids = new LinkedHashSet<>(postEffects.size());
for (final Key effect : postEffects) {
Preconditions.checkArgument(effect != null, "effects cannot be null");
Preconditions.checkArgument(ids.add(PaperAdventure.asVanilla(effect)), "effects cannot be duplicate [%s]", effect);
}
return this.getHandle().setPostEffects(ids);
}
@Override
public boolean add(final Key key) {
Preconditions.checkArgument(key != null, "key cannot be null");
return this.getHandle().addPostEffect(PaperAdventure.asVanilla(key));
}
@Override
public boolean remove(final Key key) {
Preconditions.checkArgument(key != null, "key cannot be null");
return this.getHandle().removePostEffect(PaperAdventure.asVanilla(key));
}
@Override
public boolean clear() {
return this.getHandle().clearPostEffects();
}
}
@@ -1,41 +0,0 @@
package io.papermc.paper.loot.number;
import java.util.Optional;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import org.bukkit.craftbukkit.CraftLootContext;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.loot.LootContext;
public record PaperResolvableFloat(
net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat impl
) implements ResolvableFloat, Handleable<net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat> {
@Override
public float resolve(final LootContext context, final float defaultValue) {
LootParams lootParams = CraftLootContext.createLootParams(context, LootContextParamSets.ALL_PARAMS_OPTIONAL, false);
net.minecraft.world.level.storage.loot.LootContext vanillaContext = new net.minecraft.world.level.storage.loot.LootContext.Builder(lootParams).create(Optional.empty());
return this.impl.get(vanillaContext, defaultValue);
}
@Override
public net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat getHandle() {
return this.impl;
}
public static ResolvableFloat fromVanilla(net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat vanilla) {
if (vanilla instanceof net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat.Constant(
float value
)) {
return new PaperResolvableFloat.Constant(value);
}
return new PaperResolvableFloat(vanilla);
}
record Constant(float value) implements ResolvableFloat.Constant {
@Override
public float getValue() {
return this.value;
}
}
}
@@ -1,41 +0,0 @@
package io.papermc.paper.loot.number;
import java.util.Optional;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import org.bukkit.craftbukkit.CraftLootContext;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.loot.LootContext;
public record PaperResolvableInt(
net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt impl
) implements ResolvableInt, Handleable<net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt> {
@Override
public int resolve(final LootContext context, final int defaultValue) {
LootParams lootParams = CraftLootContext.createLootParams(context, LootContextParamSets.ALL_PARAMS_OPTIONAL, false);
net.minecraft.world.level.storage.loot.LootContext vanillaContext = new net.minecraft.world.level.storage.loot.LootContext.Builder(lootParams).create(Optional.empty());
return this.impl.get(vanillaContext, defaultValue);
}
@Override
public net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt getHandle() {
return this.impl;
}
public static ResolvableInt fromVanilla(net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt vanilla) {
if (vanilla instanceof net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt.Constant(
int value
)) {
return new Constant(value);
}
return new PaperResolvableInt(vanilla);
}
public record Constant(int value) implements ResolvableInt.Constant {
@Override
public int getValue() {
return this.value;
}
}
}
@@ -1,4 +0,0 @@
@NullMarked
package io.papermc.paper.loot.number;
import org.jspecify.annotations.NullMarked;
@@ -1,9 +1,15 @@
package io.papermc.paper.plugin.manager;
import co.aikar.timings.TimedEventExecutor;
import com.destroystokyo.paper.event.server.ServerExceptionEvent;
import com.destroystokyo.paper.exception.ServerEventException;
import com.google.common.collect.Sets;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.bukkit.Server;
import org.bukkit.Warning;
import org.bukkit.event.Event;
@@ -18,14 +24,6 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
class PaperEventManager {
private final Server server;
@@ -163,10 +161,15 @@ class PaperEventManager {
// This loop checks for extending deprecated events
if (clazz.getAnnotation(Deprecated.class) != null) {
Warning warning = clazz.getAnnotation(Warning.class);
if (warning != null && !warning.propagate() && !clazz.equals(eventClass)) {
break;
}
Warning.WarningState warningState = this.server.getWarningState();
if (!warningState.printFor(warning)) {
break;
}
plugin.getLogger().log(
Level.WARNING,
String.format(
@@ -174,7 +177,7 @@ class PaperEventManager {
plugin.getPluginMeta().getDisplayName(),
clazz.getName(),
method.toGenericString(),
(warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected",
(warning != null && !warning.reason().isEmpty()) ? warning.reason() : "Please see the deprecation notice on the event for more info",
Arrays.toString(plugin.getPluginMeta().getAuthors().toArray())),
warningState == Warning.WarningState.ON ? new AuthorNagException(null) : null);
break;
@@ -1,106 +0,0 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.context.ContextKey;
import net.minecraft.util.context.ContextKeySet;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Location;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.loot.LootContext;
public final class CraftLootContext {
public static LootParams createLootParams(final LootContext context, final ContextKeySet paramSet, final boolean empty) {
Preconditions.checkArgument(context != null, "LootContext cannot be null");
final Location loc = context.getLocation();
Preconditions.checkArgument(loc.getWorld() != null, "LootContext.getLocation#getWorld cannot be null");
final ServerLevel handle = ((CraftWorld) loc.getWorld()).getHandle();
final LootParams.Builder builder = new LootParams.Builder(handle);
setMaybe(builder, paramSet, LootContextParams.ORIGIN, CraftLocation.toVec3(loc));
final BlockState blockState = ((CraftBlockState) loc.getBlock().getState()).getHandle();
setMaybe(builder, paramSet, LootContextParams.BLOCK_STATE, blockState);
if (blockState.hasBlockEntity()) {
setMaybe(builder, paramSet, LootContextParams.BLOCK_ENTITY, handle.getBlockEntity(CraftLocation.toBlockPos(loc)));
}
if (!empty) {
builder.withLuck(context.getLuck());
if (context.getLootedEntity() instanceof CraftEntity craftLootedEntity) {
Entity nmsLootedEntity = craftLootedEntity.getHandle();
setMaybe(builder, paramSet, LootContextParams.THIS_ENTITY, nmsLootedEntity);
setMaybe(builder, paramSet, LootContextParams.DAMAGE_SOURCE, handle.damageSources().generic());
setMaybe(builder, paramSet, LootContextParams.ORIGIN, nmsLootedEntity.position());
}
if (context.getKiller() instanceof CraftHumanEntity craftHumanKiller) {
Player nmsKiller = craftHumanKiller.getHandle();
setMaybe(builder, paramSet, LootContextParams.ATTACKING_ENTITY, nmsKiller);
// If there is a player killer, damage source should reflect that in case loot tables use that information
setMaybe(builder, paramSet, LootContextParams.DAMAGE_SOURCE, handle.damageSources().playerAttack(nmsKiller));
setMaybe(builder, paramSet, LootContextParams.LAST_DAMAGE_PLAYER, nmsKiller); // SPIGOT-5603 - Set minecraft:killed_by_player
setMaybe(builder, paramSet, LootContextParams.TOOL, nmsKiller.getUseItem()); // SPIGOT-6925 - Set minecraft:match_tool
}
}
// SPIGOT-5603 - Avoid IllegalArgumentException in ContextKeySet.Builder#create
final ContextKeySet.Builder nmsBuilder = new ContextKeySet.Builder();
for (final ContextKey<?> param : paramSet.required()) {
nmsBuilder.required(param);
}
for (final ContextKey<?> param : paramSet.allowed()) {
if (!paramSet.required().contains(param)) {
nmsBuilder.optional(param);
}
}
return builder.create(paramSet);
}
private static <T> void setMaybe(final LootParams.Builder builder, final ContextKeySet paramSet, final ContextKey<T> param, final T value) {
if (paramSet.required().contains(param) || paramSet.allowed().contains(param)) {
builder.withParameter(param, value);
}
}
public static LootContext toBukkit(final net.minecraft.world.level.storage.loot.LootContext info) {
final Entity entity = info.getOptional(LootContextParams.THIS_ENTITY);
Vec3 position = info.getOptional(LootContextParams.ORIGIN);
// Every vanilla context has origin or this_entity, see LootContextParamSets but can be Optional so need to check for null
if (position == null && entity != null) {
position = entity.position();
}
final Location location = CraftLocation.toBukkit(position, info.getLevel());
final LootContext.Builder contextBuilder = new LootContext.Builder(location);
final Entity killer = info.getOptional(LootContextParams.ATTACKING_ENTITY);
if (killer != null && killer.getBukkitEntity() instanceof CraftHumanEntity craftHumanKiller) {
contextBuilder.killer(craftHumanKiller);
}
if (entity != null) {
contextBuilder.lootedEntity(entity.getBukkitEntity());
}
contextBuilder.luck(info.getLuck());
return contextBuilder.build();
}
private CraftLootContext() {
throw new UnsupportedOperationException("Cannot instantiate");
}
}
@@ -8,13 +8,24 @@ import java.util.Random;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.context.ContextKey;
import net.minecraft.util.context.ContextKeySet;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.RandomSourceWrapper;
import org.bukkit.inventory.Inventory;
@@ -58,7 +69,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
@Override
public Collection<ItemStack> populateLoot(Random random, LootContext context) {
Preconditions.checkArgument(context != null, "LootContext cannot be null");
LootParams nmsContext = CraftLootContext.createLootParams(context, this.getHandle().getParamSet(), this.getHandle() == LootTable.EMPTY);
LootParams nmsContext = this.convertContext(context);
List<net.minecraft.world.item.ItemStack> nmsItems = this.handle.getRandomItems(nmsContext, random == null ? null : new RandomSourceWrapper(random));
Collection<ItemStack> bukkit = new ArrayList<>(nmsItems.size());
@@ -76,7 +87,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
public void fillInventory(Inventory inventory, Random random, LootContext context) {
Preconditions.checkArgument(inventory != null, "Inventory cannot be null");
Preconditions.checkArgument(context != null, "LootContext cannot be null");
LootParams nmsContext = CraftLootContext.createLootParams(context, this.getHandle().getParamSet(), this.getHandle() == LootTable.EMPTY);
LootParams nmsContext = this.convertContext(context);
CraftInventory craftInventory = (CraftInventory) inventory;
Container handle = craftInventory.getInventory();
@@ -89,6 +100,77 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
return this.key;
}
private LootParams convertContext(LootContext context) {
Preconditions.checkArgument(context != null, "LootContext cannot be null");
Location loc = context.getLocation();
Preconditions.checkArgument(loc.getWorld() != null, "LootContext.getLocation#getWorld cannot be null");
ServerLevel handle = ((CraftWorld) loc.getWorld()).getHandle();
LootParams.Builder builder = new LootParams.Builder(handle);
this.setMaybe(builder, LootContextParams.ORIGIN, CraftLocation.toVec3(loc));
if (this.getHandle() != LootTable.EMPTY) {
builder.withLuck(context.getLuck());
if (context.getLootedEntity() != null) {
Entity nmsLootedEntity = ((CraftEntity) context.getLootedEntity()).getHandle();
this.setMaybe(builder, LootContextParams.THIS_ENTITY, nmsLootedEntity);
this.setMaybe(builder, LootContextParams.DAMAGE_SOURCE, handle.damageSources().generic());
this.setMaybe(builder, LootContextParams.ORIGIN, nmsLootedEntity.position());
}
if (context.getKiller() != null) {
Player nmsKiller = ((CraftHumanEntity) context.getKiller()).getHandle();
this.setMaybe(builder, LootContextParams.ATTACKING_ENTITY, nmsKiller);
// If there is a player killer, damage source should reflect that in case loot tables use that information
this.setMaybe(builder, LootContextParams.DAMAGE_SOURCE, handle.damageSources().playerAttack(nmsKiller));
this.setMaybe(builder, LootContextParams.LAST_DAMAGE_PLAYER, nmsKiller); // SPIGOT-5603 - Set minecraft:killed_by_player
this.setMaybe(builder, LootContextParams.TOOL, nmsKiller.getUseItem()); // SPIGOT-6925 - Set minecraft:match_tool
}
}
// SPIGOT-5603 - Avoid IllegalArgumentException in ContextKeySet.Builder#create
ContextKeySet.Builder nmsBuilder = new ContextKeySet.Builder();
for (ContextKey<?> param : this.getHandle().getParamSet().required()) {
nmsBuilder.required(param);
}
for (ContextKey<?> param : this.getHandle().getParamSet().allowed()) {
if (!this.getHandle().getParamSet().required().contains(param)) {
nmsBuilder.optional(param);
}
}
return builder.create(this.getHandle().getParamSet());
}
private <T> void setMaybe(LootParams.Builder builder, ContextKey<T> param, T value) {
if (this.getHandle().getParamSet().required().contains(param) || this.getHandle().getParamSet().allowed().contains(param)) {
builder.withParameter(param, value);
}
}
public static LootContext convertContext(net.minecraft.world.level.storage.loot.LootContext info) {
Vec3 position = info.getOptional(LootContextParams.ORIGIN);
if (position == null) {
position = info.getOptional(LootContextParams.THIS_ENTITY).position(); // Every vanilla context has origin or this_entity, see LootContextParamSets
}
Location location = CraftLocation.toBukkit(position, info.getLevel());
LootContext.Builder contextBuilder = new LootContext.Builder(location);
if (info.hasParameter(LootContextParams.ATTACKING_ENTITY)) {
CraftEntity killer = info.getOptional(LootContextParams.ATTACKING_ENTITY).getBukkitEntity();
if (killer instanceof CraftHumanEntity) {
contextBuilder.killer((CraftHumanEntity) killer);
}
}
if (info.hasParameter(LootContextParams.THIS_ENTITY)) {
contextBuilder.lootedEntity(info.getOptional(LootContextParams.THIS_ENTITY).getBukkitEntity());
}
contextBuilder.luck(info.getLuck());
return contextBuilder.build();
}
@Override
public String toString() {
return this.key.toString();
@@ -17,7 +17,9 @@ import io.papermc.paper.dialog.Dialog;
import io.papermc.paper.dialog.PaperDialog;
import io.papermc.paper.entity.LookAnchor;
import io.papermc.paper.entity.PaperPlayerGiveResult;
import io.papermc.paper.entity.PaperPlayerPostEffects;
import io.papermc.paper.entity.PlayerGiveResult;
import io.papermc.paper.entity.PlayerPostEffects;
import io.papermc.paper.math.Angle;
import io.papermc.paper.math.Position;
import io.papermc.paper.util.MCUtil;
@@ -1688,8 +1690,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
final Optional<net.minecraft.world.item.enchantment.EnchantedItemInUse> selected = net.minecraft.world.item.enchantment.EnchantmentHelper
.getRandomItemWith(net.minecraft.world.item.enchantment.EnchantmentEffectComponents.REPAIR_WITH_XP, handle, net.minecraft.world.item.ItemStack::isDamaged);
final net.minecraft.world.item.ItemStack itemstack = selected.map(net.minecraft.world.item.enchantment.EnchantedItemInUse::itemStack).orElse(net.minecraft.world.item.ItemStack.EMPTY);
if (!itemstack.isEmpty() && itemstack.getItem().components().has(net.minecraft.core.component.DataComponents.MAX_DAMAGE)) {
net.minecraft.world.entity.ExperienceOrb orb = net.minecraft.world.entity.EntityTypes.EXPERIENCE_ORB.create(handle.level(), net.minecraft.world.entity.EntitySpawnReason.COMMAND);
if (!itemstack.isEmpty()) {
final net.minecraft.world.entity.ExperienceOrb orb = net.minecraft.world.entity.EntityTypes.EXPERIENCE_ORB.create(handle.level(), net.minecraft.world.entity.EntitySpawnReason.COMMAND);
if (orb == null) {
return amount;
}
orb.setValue(amount);
orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM;
orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ());
@@ -3392,4 +3397,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
this.getHandle().fixedPose = false;
this.getHandle().updatePlayerPose();
}
@Override
public PlayerPostEffects postEffects() {
return new PaperPlayerPostEffects(this.getHandle());
}
}
@@ -10,7 +10,9 @@ import net.minecraft.world.entity.SulfurCubeArchetype;
import net.minecraft.world.entity.item.PrimedTnt;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.SulfurCube;
import org.bukkit.inventory.ItemStack;
public class CraftSulfurCube extends CraftAbstractCubeMob implements SulfurCube, PaperShearable, PaperBucketable {
public CraftSulfurCube(final CraftServer server, final net.minecraft.world.entity.monster.cubemob.SulfurCube entity) {
@@ -44,6 +46,11 @@ public class CraftSulfurCube extends CraftAbstractCubeMob implements SulfurCube,
return this.getHandle().primeTime(imminent);
}
@Override
public boolean swallow(final ItemStack itemStack) {
return this.getHandle().equipItem(CraftItemStack.asNMSCopy(itemStack));
}
@Override
public int getAge() {
return this.getHandle().getAge();
@@ -98,7 +98,7 @@ import org.bukkit.craftbukkit.CraftChunk;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.CraftExplosionResult;
import org.bukkit.craftbukkit.CraftGameRule;
import org.bukkit.craftbukkit.CraftLootContext;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.CraftRaid;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftStatistic;
@@ -1996,7 +1996,7 @@ public class CraftEventFactory {
Entity entity = lootInfo.getOptional(LootContextParams.THIS_ENTITY);
List<org.bukkit.inventory.ItemStack> bukkitLoot = loot.stream().map(CraftItemStack::asBukkitMirror).collect(Collectors.toCollection(ArrayList::new));
LootGenerateEvent event = new LootGenerateEvent(world, (entity != null ? entity.getBukkitEntity() : null), inventory.getOwner(), lootTable.craftLootTable, CraftLootContext.toBukkit(lootInfo), bukkitLoot, plugin);
LootGenerateEvent event = new LootGenerateEvent(world, (entity != null ? entity.getBukkitEntity() : null), inventory.getOwner(), lootTable.craftLootTable, CraftLootTable.convertContext(lootInfo), bukkitLoot, plugin);
Bukkit.getPluginManager().callEvent(event);
return event;
}
@@ -1,6 +1,6 @@
package org.bukkit.craftbukkit.inventory;
import io.papermc.paper.datacomponent.DataComponentTypes;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.crafting.SingleRecipeInput;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import org.bukkit.block.Furnace;
@@ -44,7 +44,7 @@ public class CraftInventoryFurnace extends CraftInventory implements FurnaceInve
@Override
public boolean isFuel(ItemStack stack) {
return stack != null && !stack.isEmpty() && stack.hasData(DataComponentTypes.COOKING_FUEL);
return stack != null && !stack.isEmpty() && CraftItemStack.asNMSCopy(stack).has(DataComponents.COOKING_FUEL);
}
@Override
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff. Show more