Merge remote-tracking branch 'upstream/main'
All checks were successful
SteamWarCI Build successful

This commit is contained in:
2025-05-31 19:42:03 +02:00
337 changed files with 4559 additions and 1903 deletions

View File

@ -17,13 +17,8 @@ public net.minecraft.commands.arguments.blocks.BlockInput tag
public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V
public net.minecraft.nbt.ListTag <init>(Ljava/util/List;)V public net.minecraft.nbt.ListTag <init>(Ljava/util/List;)V
public net.minecraft.nbt.ListTag identifyRawElementType()B public net.minecraft.nbt.ListTag identifyRawElementType()B
public net.minecraft.nbt.TagParser readArrayTag()Lnet/minecraft/nbt/Tag;
public net.minecraft.nbt.TagParser type(Ljava/lang/String;)Lnet/minecraft/nbt/Tag;
public net.minecraft.network.Connection address public net.minecraft.network.Connection address
public net.minecraft.network.Connection channel public net.minecraft.network.Connection channel
public net.minecraft.network.chat.HoverEvent$ItemStackInfo components
public net.minecraft.network.chat.HoverEvent$ItemStackInfo count
public net.minecraft.network.chat.HoverEvent$ItemStackInfo item
public net.minecraft.network.chat.TextColor name public net.minecraft.network.chat.TextColor name
public net.minecraft.network.chat.contents.TranslatableContents filterAllowedArguments(Ljava/lang/Object;)Lcom/mojang/serialization/DataResult; public net.minecraft.network.chat.contents.TranslatableContents filterAllowedArguments(Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;
public net.minecraft.network.chat.numbers.FixedFormat value public net.minecraft.network.chat.numbers.FixedFormat value
@ -108,14 +103,12 @@ public net.minecraft.server.level.ServerPlayer triggerDimensionChangeTriggers(Ln
public net.minecraft.server.level.ServerPlayer wardenSpawnTracker public net.minecraft.server.level.ServerPlayer wardenSpawnTracker
public net.minecraft.server.level.ServerPlayer$RespawnPosAngle public net.minecraft.server.level.ServerPlayer$RespawnPosAngle
public net.minecraft.server.level.ServerPlayerGameMode level public net.minecraft.server.level.ServerPlayerGameMode level
public net.minecraft.server.level.Ticket key
public net.minecraft.server.level.TicketType register(Ljava/lang/String;JZLnet/minecraft/server/level/TicketType$TicketUse;)Lnet/minecraft/server/level/TicketType; public net.minecraft.server.level.TicketType register(Ljava/lang/String;JZLnet/minecraft/server/level/TicketType$TicketUse;)Lnet/minecraft/server/level/TicketType;
public net.minecraft.server.network.ServerGamePacketListenerImpl isChatMessageIllegal(Ljava/lang/String;)Z public net.minecraft.server.network.ServerGamePacketListenerImpl isChatMessageIllegal(Ljava/lang/String;)Z
public net.minecraft.server.network.ServerLoginPacketListenerImpl authenticatedProfile public net.minecraft.server.network.ServerLoginPacketListenerImpl authenticatedProfile
public net.minecraft.server.network.ServerLoginPacketListenerImpl connection public net.minecraft.server.network.ServerLoginPacketListenerImpl connection
public net.minecraft.server.network.ServerLoginPacketListenerImpl state public net.minecraft.server.network.ServerLoginPacketListenerImpl state
public net.minecraft.server.network.ServerLoginPacketListenerImpl$State public net.minecraft.server.network.ServerLoginPacketListenerImpl$State
public net.minecraft.server.packs.VanillaPackResourcesBuilder safeGetPath(Ljava/net/URI;)Ljava/nio/file/Path;
public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector
public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector <init>(Lnet/minecraft/world/level/validation/DirectoryValidator;)V public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector <init>(Lnet/minecraft/world/level/validation/DirectoryValidator;)V
public net.minecraft.server.packs.repository.Pack resources public net.minecraft.server.packs.repository.Pack resources
@ -129,7 +122,6 @@ public net.minecraft.tags.TagEntry id
public net.minecraft.tags.TagEntry required public net.minecraft.tags.TagEntry required
public net.minecraft.tags.TagEntry tag public net.minecraft.tags.TagEntry tag
public net.minecraft.util.datafix.fixes.BlockStateData register(ILcom/mojang/serialization/Dynamic;[Lcom/mojang/serialization/Dynamic;)V public net.minecraft.util.datafix.fixes.BlockStateData register(ILcom/mojang/serialization/Dynamic;[Lcom/mojang/serialization/Dynamic;)V
public net.minecraft.util.datafix.fixes.EntityCustomNameToComponentFix fixCustomName(Lcom/mojang/serialization/DynamicOps;Ljava/lang/String;Ljava/lang/String;)Lcom/mojang/serialization/Dynamic;
public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES
public net.minecraft.util.datafix.fixes.ItemSpawnEggFix ID_TO_ENTITY public net.minecraft.util.datafix.fixes.ItemSpawnEggFix ID_TO_ENTITY
public net.minecraft.world.BossEvent color public net.minecraft.world.BossEvent color
@ -138,6 +130,11 @@ public net.minecraft.world.BossEvent overlay
public net.minecraft.world.CompoundContainer container1 public net.minecraft.world.CompoundContainer container1
public net.minecraft.world.CompoundContainer container2 public net.minecraft.world.CompoundContainer container2
public net.minecraft.world.SimpleContainer items public net.minecraft.world.SimpleContainer items
public net.minecraft.world.damagesource.CombatTracker entries
public net.minecraft.world.damagesource.CombatTracker getMostSignificantFall()Lnet/minecraft/world/damagesource/CombatEntry;
public net.minecraft.world.damagesource.CombatTracker inCombat
public net.minecraft.world.damagesource.CombatTracker mob
public net.minecraft.world.damagesource.CombatTracker takingDamage
public net.minecraft.world.damagesource.DamageSource <init>(Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V public net.minecraft.world.damagesource.DamageSource <init>(Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V
public net.minecraft.world.effect.MobEffect attributeModifiers public net.minecraft.world.effect.MobEffect attributeModifiers
public net.minecraft.world.effect.MobEffect$AttributeTemplate public net.minecraft.world.effect.MobEffect$AttributeTemplate
@ -198,7 +195,6 @@ public net.minecraft.world.entity.Entity getSwimSound()Lnet/minecraft/sounds/Sou
public net.minecraft.world.entity.Entity getSwimSplashSound()Lnet/minecraft/sounds/SoundEvent; public net.minecraft.world.entity.Entity getSwimSplashSound()Lnet/minecraft/sounds/SoundEvent;
public net.minecraft.world.entity.Entity hasVisualFire public net.minecraft.world.entity.Entity hasVisualFire
public net.minecraft.world.entity.Entity isAffectedByBlocks()Z public net.minecraft.world.entity.Entity isAffectedByBlocks()Z
public net.minecraft.world.entity.Entity isInBubbleColumn()Z
public net.minecraft.world.entity.Entity isInRain()Z public net.minecraft.world.entity.Entity isInRain()Z
public net.minecraft.world.entity.Entity isInvulnerableToBase(Lnet/minecraft/world/damagesource/DamageSource;)Z public net.minecraft.world.entity.Entity isInvulnerableToBase(Lnet/minecraft/world/damagesource/DamageSource;)Z
public net.minecraft.world.entity.Entity onGround public net.minecraft.world.entity.Entity onGround
@ -213,7 +209,6 @@ public net.minecraft.world.entity.Entity unsetRemoved()V
public net.minecraft.world.entity.Entity wasTouchingWater public net.minecraft.world.entity.Entity wasTouchingWater
public net.minecraft.world.entity.ExperienceOrb count public net.minecraft.world.entity.ExperienceOrb count
public net.minecraft.world.entity.ExperienceOrb setValue(I)V public net.minecraft.world.entity.ExperienceOrb setValue(I)V
public net.minecraft.world.entity.ExperienceOrb value
public net.minecraft.world.entity.GlowSquid setDarkTicks(I)V public net.minecraft.world.entity.GlowSquid setDarkTicks(I)V
public net.minecraft.world.entity.Interaction attack public net.minecraft.world.entity.Interaction attack
public net.minecraft.world.entity.Interaction getHeight()F public net.minecraft.world.entity.Interaction getHeight()F
@ -248,14 +243,10 @@ public net.minecraft.world.entity.LivingEntity lastHurtByMob
public net.minecraft.world.entity.LivingEntity lastHurtByMobTimestamp public net.minecraft.world.entity.LivingEntity lastHurtByMobTimestamp
public net.minecraft.world.entity.LivingEntity lastHurtByPlayer public net.minecraft.world.entity.LivingEntity lastHurtByPlayer
public net.minecraft.world.entity.LivingEntity lastHurtByPlayerMemoryTime public net.minecraft.world.entity.LivingEntity lastHurtByPlayerMemoryTime
public net.minecraft.world.entity.LivingEntity lastHurtByPlayerTime
public net.minecraft.world.entity.LivingEntity playSecondaryHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V public net.minecraft.world.entity.LivingEntity playSecondaryHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V
public net.minecraft.world.entity.LivingEntity setLivingEntityFlag(IZ)V public net.minecraft.world.entity.LivingEntity setLivingEntityFlag(IZ)V
public net.minecraft.world.entity.LivingEntity useItemRemaining public net.minecraft.world.entity.LivingEntity useItemRemaining
public net.minecraft.world.entity.Mob armorDropChances
public net.minecraft.world.entity.Mob getAmbientSound()Lnet/minecraft/sounds/SoundEvent; public net.minecraft.world.entity.Mob getAmbientSound()Lnet/minecraft/sounds/SoundEvent;
public net.minecraft.world.entity.Mob getEquipmentDropChance(Lnet/minecraft/world/entity/EquipmentSlot;)F
public net.minecraft.world.entity.Mob handDropChances
public net.minecraft.world.entity.Mob isSunBurnTick()Z public net.minecraft.world.entity.Mob isSunBurnTick()Z
public net.minecraft.world.entity.Mob lootTable public net.minecraft.world.entity.Mob lootTable
public net.minecraft.world.entity.Mob lootTableSeed public net.minecraft.world.entity.Mob lootTableSeed
@ -431,7 +422,6 @@ public net.minecraft.world.entity.npc.Villager setUnhappy()V
public net.minecraft.world.entity.npc.WanderingTrader getWanderTarget()Lnet/minecraft/core/BlockPos; public net.minecraft.world.entity.npc.WanderingTrader getWanderTarget()Lnet/minecraft/core/BlockPos;
public net.minecraft.world.entity.player.Abilities flyingSpeed public net.minecraft.world.entity.player.Abilities flyingSpeed
public net.minecraft.world.entity.player.Abilities walkingSpeed public net.minecraft.world.entity.player.Abilities walkingSpeed
public net.minecraft.world.entity.player.Inventory compartments
public net.minecraft.world.entity.player.Inventory equipment public net.minecraft.world.entity.player.Inventory equipment
public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION
public net.minecraft.world.entity.player.Player closeContainer()V public net.minecraft.world.entity.player.Player closeContainer()V
@ -492,7 +482,6 @@ public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ
public net.minecraft.world.entity.projectile.SpectralArrow duration public net.minecraft.world.entity.projectile.SpectralArrow duration
public net.minecraft.world.entity.projectile.ThrowableItemProjectile getDefaultItem()Lnet/minecraft/world/item/Item; public net.minecraft.world.entity.projectile.ThrowableItemProjectile getDefaultItem()Lnet/minecraft/world/item/Item;
public net.minecraft.world.entity.projectile.ThrownPotion isLingering()Z
public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage
public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V
public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V
@ -522,6 +511,7 @@ public net.minecraft.world.flag.FeatureFlagRegistry names
public net.minecraft.world.food.FoodData exhaustionLevel public net.minecraft.world.food.FoodData exhaustionLevel
public net.minecraft.world.food.FoodData foodLevel public net.minecraft.world.food.FoodData foodLevel
public net.minecraft.world.food.FoodData saturationLevel public net.minecraft.world.food.FoodData saturationLevel
public net.minecraft.world.inventory.AbstractContainerMenu menuType
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftSlots public net.minecraft.world.inventory.AbstractContainerMenu quickcraftSlots
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftStatus public net.minecraft.world.inventory.AbstractContainerMenu quickcraftStatus
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftType public net.minecraft.world.inventory.AbstractContainerMenu quickcraftType
@ -558,7 +548,6 @@ public net.minecraft.world.item.context.UseOnContext <init>(Lnet/minecraft/world
public net.minecraft.world.item.crafting.RecipeManager recipes public net.minecraft.world.item.crafting.RecipeManager recipes
public net.minecraft.world.item.crafting.RecipeMap byKey public net.minecraft.world.item.crafting.RecipeMap byKey
public net.minecraft.world.item.crafting.RecipeMap byType public net.minecraft.world.item.crafting.RecipeMap byType
public net.minecraft.world.item.enchantment.ItemEnchantments showInTooltip
public net.minecraft.world.item.trading.MerchantOffer demand public net.minecraft.world.item.trading.MerchantOffer demand
public net.minecraft.world.item.trading.MerchantOffer result public net.minecraft.world.item.trading.MerchantOffer result
public net.minecraft.world.item.trading.MerchantOffer specialPriceDiff public net.minecraft.world.item.trading.MerchantOffer specialPriceDiff
@ -777,7 +766,6 @@ public-f net.minecraft.world.inventory.AbstractContainerMenu lastSlots
public-f net.minecraft.world.inventory.AbstractContainerMenu remoteDataSlots public-f net.minecraft.world.inventory.AbstractContainerMenu remoteDataSlots
public-f net.minecraft.world.inventory.AbstractContainerMenu remoteSlots public-f net.minecraft.world.inventory.AbstractContainerMenu remoteSlots
public-f net.minecraft.world.inventory.AbstractContainerMenu slots public-f net.minecraft.world.inventory.AbstractContainerMenu slots
public-f net.minecraft.world.item.enchantment.ItemEnchantments$Mutable showInTooltip
public-f net.minecraft.world.item.trading.MerchantOffer baseCostA public-f net.minecraft.world.item.trading.MerchantOffer baseCostA
public-f net.minecraft.world.item.trading.MerchantOffer costB public-f net.minecraft.world.item.trading.MerchantOffer costB
public-f net.minecraft.world.item.trading.MerchantOffer maxUses public-f net.minecraft.world.item.trading.MerchantOffer maxUses

View File

@ -2,7 +2,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins { plugins {
id("io.papermc.paperweight.core") version "2.0.0-beta.16" apply false id("io.papermc.paperweight.core") version "2.0.0-beta.17" apply false
} }
subprojects { subprojects {

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

6
gradlew vendored
View File

@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

4
gradlew.bat vendored
View File

@ -70,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@ -11,8 +11,7 @@ java {
val annotationsVersion = "26.0.2" val annotationsVersion = "26.0.2"
// Keep in sync with paper-server adventure-text-serializer-ansi dep // Keep in sync with paper-server adventure-text-serializer-ansi dep
val adventureVersion = "4.21.0-mc1215-SNAPSHOT" // FIXME move to release asap val adventureVersion = "4.21.0"
val adventureJavadocVersion = "4.20.0" // Fixme remove me
val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21" val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21"
val slf4jVersion = "2.0.16" val slf4jVersion = "2.0.16"
val log4jVersion = "2.24.1" val log4jVersion = "2.24.1"
@ -58,15 +57,13 @@ dependencies {
exclude("com.google.guava", "guava") exclude("com.google.guava", "guava")
} }
// FIXME remove me when we are using a release again apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
val adventureGroup = "io.papermc.adventure" apiAndDocs("net.kyori:adventure-api")
apiAndDocs(platform("$adventureGroup:adventure-bom:$adventureVersion")) apiAndDocs("net.kyori:adventure-text-minimessage")
apiAndDocs("$adventureGroup:adventure-api") apiAndDocs("net.kyori:adventure-text-serializer-gson")
apiAndDocs("$adventureGroup:adventure-text-minimessage") apiAndDocs("net.kyori:adventure-text-serializer-legacy")
apiAndDocs("$adventureGroup:adventure-text-serializer-gson") apiAndDocs("net.kyori:adventure-text-serializer-plain")
apiAndDocs("$adventureGroup:adventure-text-serializer-legacy") apiAndDocs("net.kyori:adventure-text-logger-slf4j")
apiAndDocs("$adventureGroup:adventure-text-serializer-plain")
apiAndDocs("$adventureGroup:adventure-text-logger-slf4j")
api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins
compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
@ -179,13 +176,13 @@ tasks.withType<Javadoc> {
"https://javadoc.io/doc/org.joml/joml/1.10.8/", "https://javadoc.io/doc/org.joml/joml/1.10.8/",
"https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0", "https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0",
"https://jspecify.dev/docs/api/", "https://jspecify.dev/docs/api/",
"https://jd.advntr.dev/api/$adventureJavadocVersion/", "https://jd.advntr.dev/api/$adventureVersion/",
"https://jd.advntr.dev/key/$adventureJavadocVersion/", "https://jd.advntr.dev/key/$adventureVersion/",
"https://jd.advntr.dev/text-minimessage/$adventureJavadocVersion/", "https://jd.advntr.dev/text-minimessage/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-gson/$adventureJavadocVersion/", "https://jd.advntr.dev/text-serializer-gson/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-legacy/$adventureJavadocVersion/", "https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-plain/$adventureJavadocVersion/", "https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
"https://jd.advntr.dev/text-logger-slf4j/$adventureJavadocVersion/", "https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
"https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/", "https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/",
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3",

View File

@ -27,7 +27,9 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
} }
/** /**
* @return The reason the enderman is trying to escape * Gets the reason the enderman is trying to escape.
*
* @return The reason
*/ */
public Reason getReason() { public Reason getReason() {
return this.reason; return this.reason;
@ -42,7 +44,8 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
* Cancels the escape. * Cancels the escape.
* <p> * <p>
* If this escape normally had resulted in damage avoidance such as indirect, * If this escape normally had resulted in damage avoidance such as indirect,
* the enderman will now take damage. * the enderman will now take damage. However, this does not change the Enderman's
* innate immunities or damage behavior like arrows where the damage never happens.
*/ */
@Override @Override
public void setCancelled(final boolean cancel) { public void setCancelled(final boolean cancel) {
@ -76,7 +79,7 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
*/ */
STARE, STARE,
/** /**
* Specific case for {@link #CRITICAL_HIT} where the enderman is taking rain damage * Specific case for {@link #CRITICAL_HIT} where the enderman is taking damage by drowning (ex: rain)
*/ */
DROWN DROWN
} }

View File

@ -1,9 +1,10 @@
package com.destroystokyo.paper.event.player; package com.destroystokyo.paper.event.player;
import io.papermc.paper.event.player.AbstractRespawnEvent;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerRespawnEvent;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
@ -11,36 +12,31 @@ import org.jspecify.annotations.NullMarked;
* Fired after a player has respawned * Fired after a player has respawned
*/ */
@NullMarked @NullMarked
public class PlayerPostRespawnEvent extends PlayerEvent { public class PlayerPostRespawnEvent extends AbstractRespawnEvent {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final Location respawnedLocation;
private final boolean isBedSpawn;
@ApiStatus.Internal @ApiStatus.Internal
public PlayerPostRespawnEvent(final Player respawnPlayer, final Location respawnedLocation, final boolean isBedSpawn) { public PlayerPostRespawnEvent(
super(respawnPlayer); final Player respawnPlayer,
this.respawnedLocation = respawnedLocation; final Location respawnLocation,
this.isBedSpawn = isBedSpawn; final boolean isBedSpawn,
final boolean isAnchorSpawn,
final boolean missingRespawnBlock,
final PlayerRespawnEvent.RespawnReason respawnReason
) {
super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, missingRespawnBlock, respawnReason);
} }
/** /**
* Returns the location of the respawned player * Returns the location of the respawned player.
* *
* @return location of the respawned player * @return location of the respawned player
* @see #getRespawnLocation()
*/ */
@ApiStatus.Obsolete
public Location getRespawnedLocation() { public Location getRespawnedLocation() {
return this.respawnedLocation.clone(); return super.getRespawnLocation();
}
/**
* Checks if the player respawned to their bed
*
* @return whether the player respawned to their bed
*/
public boolean isBedSpawn() {
return this.isBedSpawn;
} }
@Override @Override

View File

@ -119,7 +119,7 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable {
* the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])}
* or current player names will not be called. * or current player names will not be called.
* <p> * <p>
* The passed collection will be cloned to a new {@code List}. You must call {{@link #getCompletions()}} to mutate from here * The passed collection will be cloned to a new {@code List}. You must call {@link #getCompletions()} to mutate from here
* *
* @param completions the new completions * @param completions the new completions
*/ */

View File

@ -21,12 +21,24 @@ public interface VersionFetcher {
/** /**
* Gets the version message to cache and show to command senders. * Gets the version message to cache and show to command senders.
* *
* <p>NOTE: This is run in a new thread separate from that of the command processing thread</p> * @return the message to show when requesting a version
* @apiNote This method may involve a web request which will block the executing thread
*/
Component getVersionMessage();
/**
* Gets the version message to cache and show to command senders.
* *
* @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()})
* @return the message to show when requesting a version * @return the message to show when requesting a version
* @apiNote This method may involve a web request which will block the current thread
* @see #getVersionMessage()
* @deprecated {@code serverVersion} is not required
*/ */
Component getVersionMessage(String serverVersion); @Deprecated
default Component getVersionMessage(String serverVersion) {
return getVersionMessage();
}
@ApiStatus.Internal @ApiStatus.Internal
class DummyVersionFetcher implements VersionFetcher { class DummyVersionFetcher implements VersionFetcher {
@ -37,7 +49,7 @@ public interface VersionFetcher {
} }
@Override @Override
public Component getVersionMessage(final String serverVersion) { public Component getVersionMessage() {
Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!");
Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()");
new Throwable().printStackTrace(); new Throwable().printStackTrace();

View File

@ -1,10 +1,15 @@
package io.papermc.paper; package io.papermc.paper;
import io.papermc.paper.world.damagesource.CombatEntry;
import io.papermc.paper.world.damagesource.FallLocationType;
import net.kyori.adventure.util.Services; import net.kyori.adventure.util.Services;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageEffect;
import org.bukkit.damage.DamageSource;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/** /**
* Static bridge to the server internals. * Static bridge to the server internals.
@ -45,5 +50,28 @@ public interface InternalAPIBridge {
@Deprecated(forRemoval = true, since = "1.21.5") @Deprecated(forRemoval = true, since = "1.21.5")
@ApiStatus.ScheduledForRemoval(inVersion = "1.22") @ApiStatus.ScheduledForRemoval(inVersion = "1.22")
Biome constructLegacyCustomBiome(); Biome constructLegacyCustomBiome();
/**
* Creates a new combat entry.
* <p>
* The fall location and fall distance will be calculated from the entity's current state.
*
* @param entity entity
* @param damageSource damage source
* @param damage damage amount
* @return new combat entry
*/
CombatEntry createCombatEntry(LivingEntity entity, DamageSource damageSource, float damage);
/**
* Creates a new combat entry
*
* @param damageSource damage source
* @param damage damage amount
* @param fallLocationType fall location type
* @param fallDistance fall distance
* @return combat entry
*/
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
} }

View File

@ -15,5 +15,9 @@ public enum CommandRegistrationFlag {
* @deprecated This is the default behavior now. * @deprecated This is the default behavior now.
*/ */
@Deprecated(since = "1.21.4") @Deprecated(since = "1.21.4")
FLATTEN_ALIASES FLATTEN_ALIASES,
/**
* Prevents this command from being sent to the client.
*/
SERVER_ONLY
} }

View File

@ -0,0 +1,24 @@
package io.papermc.paper.configuration;
/**
* Represents the configuration settings for a server.
* <p>
* This interface doesn't aim to cover every possible server configuration
* option but focuses on selected critical settings and behaviors.
*/
public interface ServerConfiguration {
/**
* Gets whether the server is in online mode.
* <p>
* This method returns true if:
* <ul>
* <li>The server is in {@link org.bukkit.Server#getOnlineMode online mode},</li>
* <li>Velocity is enabled and configured to be in online mode, or</li>
* <li>BungeeCord is enabled and configured to be in online mode.</li>
* </ul>
*
* @return whether the server is in online mode or behind a proxy configured for online mode
*/
boolean isProxyOnlineMode();
}

View File

@ -1,6 +1,8 @@
package io.papermc.paper.datacomponent.item; package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentBuilder; import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.datacomponent.item.blocksattacks.DamageReduction;
import io.papermc.paper.datacomponent.item.blocksattacks.ItemDamageFunction;
import io.papermc.paper.registry.tag.TagKey; import io.papermc.paper.registry.tag.TagKey;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
@ -8,8 +10,13 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import java.util.List;
// TODO /**
* Holds block attacks to the holding player like Shield.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
*/
@NullMarked @NullMarked
@ApiStatus.Experimental @ApiStatus.Experimental
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
@ -20,19 +27,59 @@ public interface BlocksAttacks {
return ItemComponentTypesBridge.bridge().blocksAttacks(); return ItemComponentTypesBridge.bridge().blocksAttacks();
} }
/**
* Gets the amount of time (in seconds) that use must be held before successfully blocking attacks.
*
* @return the delay in seconds
*/
float blockDelaySeconds(); float blockDelaySeconds();
/**
* Gets the multiplier applied to the cooldown time for the item when attacked by a disabling attack (the multiplier for {@link Weapon#disableBlockingForSeconds()}).
* <br>
* If set to 0, this item can never be disabled by attacks.
*
* @return the multiplier for the cooldown time
*/
float disableCooldownScale(); float disableCooldownScale();
//List<DamageReduction> damageReductions(); /**
* Gets a list of {@link DamageReduction} of how much damage should be blocked in a given attack.
*
* @return a list of damage reductions
*/
List<DamageReduction> damageReductions();
//ItemDamageFunction itemDamage(); /**
* Gets how much damage should be applied to the item from a given attack.
*
* @return the damage function
*/
ItemDamageFunction itemDamage();
@Nullable TagKey<DamageType> bypassedBy(); /**
* Gets the DamageType that can bypass the blocking.
*
* @return a damage type tag key, or null if there is no such tag key
*/
@Nullable
TagKey<DamageType> bypassedBy();
@Nullable Key blockSound(); /**
* Gets the key sound to play when an attack is successfully blocked.
*
* @return a key of the sound
*/
@Nullable
Key blockSound();
@Nullable Key disableSound(); /**
* Gets the key sound to play when the item goes on its disabled cooldown due to an attack.
*
* @return a key of the sound
*/
@Nullable
Key disableSound();
/** /**
* Builder for {@link BlocksAttacks}. * Builder for {@link BlocksAttacks}.
@ -47,14 +94,14 @@ public interface BlocksAttacks {
@Contract(value = "_ -> this", mutates = "this") @Contract(value = "_ -> this", mutates = "this")
Builder disableCooldownScale(float scale); Builder disableCooldownScale(float scale);
//@Contract(value = "_ -> this", mutates = "this") @Contract(value = "_ -> this", mutates = "this")
//Builder addDamageReduction(DamageReduction reduction); Builder addDamageReduction(DamageReduction reduction);
//@Contract(value = "_ -> this", mutates = "this") @Contract(value = "_ -> this", mutates = "this")
//Builder damageReductions(List<DamageReduction> reductions); Builder damageReductions(List<DamageReduction> reductions);
//@Contract(value = "_ -> this", mutates = "this") @Contract(value = "_ -> this", mutates = "this")
//Builder itemDamage(ItemDamageFunction function); Builder itemDamage(ItemDamageFunction function);
@Contract(value = "_ -> this", mutates = "this") @Contract(value = "_ -> this", mutates = "this")
Builder bypassedBy(@Nullable TagKey<DamageType> bypassedBy); Builder bypassedBy(@Nullable TagKey<DamageType> bypassedBy);

View File

@ -60,6 +60,27 @@ public interface PotionContents {
@Contract(pure = true) @Contract(pure = true)
@Nullable String customName(); @Nullable String customName();
/**
* All effects that this component applies.
* <p>
* This is a combination of the base potion type and any custom effects.
*
* @return an unmodifiable list of all effects.
*/
@Contract(pure = true)
@Unmodifiable List<PotionEffect> allEffects();
/**
* Computes the effective colour of this potion contents component.
* <p>
* This blends all custom effects, or uses a default fallback colour.
* It may or may not have an alpha channel, used for tipped arrows.
*
* @return the effective colour this component would display with.
*/
@Contract(pure = true)
Color computeEffectiveColor();
@ApiStatus.Experimental @ApiStatus.Experimental
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<PotionContents> { interface Builder extends DataComponentBuilder<PotionContents> {

View File

@ -0,0 +1,21 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import java.util.Optional;
import java.util.ServiceLoader;
@NullMarked
@ApiStatus.Internal
interface BlocksAttacksBridge {
Optional<BlocksAttacksBridge> BRIDGE = ServiceLoader.load(BlocksAttacksBridge.class).findFirst();
static BlocksAttacksBridge bridge() {
return BRIDGE.orElseThrow();
}
DamageReduction.Builder blocksAttacksDamageReduction();
ItemDamageFunction.Builder blocksAttacksItemDamageFunction();
}

View File

@ -0,0 +1,78 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.registry.set.RegistryKeySet;
import org.bukkit.damage.DamageType;
import org.checkerframework.checker.index.qual.Positive;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Hold how much damage should be blocked in a given attack.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
* @see io.papermc.paper.datacomponent.item.BlocksAttacks#damageReductions()
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface DamageReduction {
@Contract(value = "-> new", pure = true)
static DamageReduction.Builder damageReduction() {
return BlocksAttacksBridge.bridge().blocksAttacksDamageReduction();
}
/**
* The damage types to block.
*
* @return the set of damage type
*/
@Nullable
RegistryKeySet<DamageType> type();
/**
* Get the maximum angle between the users facing direction and the direction of the incoming attack to be blocked.
*
* @return the angle
*/
@Positive
float horizontalBlockingAngle();
/**
* Get the constant amount of damage to be blocked.
*
* @return the base
*/
float base();
/**
* Get the fraction of the dealt damage to be blocked.
*
* @return the factor
*/
float factor();
/**
* Builder for {@link DamageReduction}.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<DamageReduction> {
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder type(RegistryKeySet<DamageType> type);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder horizontalBlockingAngle(@Positive float horizontalBlockingAngle);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder base(float base);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder factor(float factor);
}
}

View File

@ -0,0 +1,71 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import org.checkerframework.checker.index.qual.NonNegative;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
/**
* Hold how much damage should be applied to the item from a given attack.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
* @see io.papermc.paper.datacomponent.item.BlocksAttacks#itemDamage()
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface ItemDamageFunction {
@Contract(value = "-> new", pure = true)
static ItemDamageFunction.Builder itemDamageFunction() {
return BlocksAttacksBridge.bridge().blocksAttacksItemDamageFunction();
}
/**
* Get the minimum amount of damage dealt by the attack before item damage is applied to the item.
*
* @return the threshold
*/
@NonNegative
float threshold();
/**
* Get the constant amount of damage applied to the item, if threshold is passed.
*
* @return the base
*/
float base();
/**
* Get the fraction of the dealt damage that should be applied to the item, if threshold is passed.
*
* @return the factor
*/
float factor();
/**
* Get the damage to apply for the item.
*
* @apiNote this doesn't apply enchantments like {@link org.bukkit.enchantments.Enchantment#UNBREAKING}
* @return the damage to apply
*/
int damageToApply(float damage);
/**
* Builder for {@link ItemDamageFunction}.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<ItemDamageFunction> {
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder threshold(@NonNegative final float threshold);
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder base(final float base);
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder factor(final float factor);
}
}

View File

@ -0,0 +1,52 @@
package io.papermc.paper.event.entity;
import org.bukkit.entity.FishHook;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Called just before a {@link FishHook}'s {@link FishHook.HookState} is changed.
*
* <p>If you want to monitor a player's fishing state transition, you can use {@link PlayerFishEvent}.</p>
*/
@NullMarked
public final class FishHookStateChangeEvent extends EntityEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
private final FishHook.HookState newHookState;
@ApiStatus.Internal
public FishHookStateChangeEvent(final FishHook entity, final FishHook.HookState newHookState) {
super(entity);
this.newHookState = newHookState;
}
/**
* Get the <strong>new</strong> hook state of the {@link FishHook}.
*
* <p>Refer to {@link FishHook#getState()} to get the current hook state.</p>
*
* @return the <strong>new</strong> hook state
*/
public FishHook.HookState getNewHookState() {
return this.newHookState;
}
@Override
public FishHook getEntity() {
return (FishHook) super.getEntity();
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,94 @@
package io.papermc.paper.event.packet;
import io.papermc.paper.math.BlockPosition;
import io.papermc.paper.math.Position;
import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.Component;
import org.bukkit.block.sign.Side;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
/**
* Called when a client attempts to modify a sign, but the location at which the sign should be edited
* has not yet been checked for the existence of a real sign.
* <p>
* Cancelling this event will prevent further processing of the sign change, but needs further handling
* by the plugin as the client's local world might be in an inconsistent state.
*
* @see Player#openVirtualSign(Position, Side)
*/
@NullMarked
@ApiStatus.Experimental
public class UncheckedSignChangeEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
private boolean cancel = false;
private final BlockPosition editedBlockPosition;
private final Side side;
private final List<Component> lines;
@ApiStatus.Internal
public UncheckedSignChangeEvent(
final Player editor,
final BlockPosition editedBlockPosition,
final Side side,
final List<Component> lines
) {
super(editor);
this.editedBlockPosition = editedBlockPosition;
this.side = side;
this.lines = lines;
}
/**
* Gets the location at which a potential sign was edited.
*
* @return location where the change happened
*/
public BlockPosition getEditedBlockPosition() {
return editedBlockPosition;
}
/**
* Gets which side of the sign was edited.
*
* @return {@link Side} that was edited
*/
public Side getSide() {
return side;
}
/**
* Gets the lines that the player has entered.
*
* @return the lines
*/
public @Unmodifiable List<Component> lines() {
return Collections.unmodifiableList(lines);
}
@Override
public boolean isCancelled() {
return cancel;
}
@Override
public void setCancelled(final boolean cancel) {
this.cancel = cancel;
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,98 @@
package io.papermc.paper.event.player;
import com.google.common.collect.ImmutableSet;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import java.util.Set;
@NullMarked
public abstract class AbstractRespawnEvent extends PlayerEvent {
protected Location respawnLocation;
private final boolean isBedSpawn;
private final boolean isAnchorSpawn;
private final boolean missingRespawnBlock;
private final PlayerRespawnEvent.RespawnReason respawnReason;
private final Set<PlayerRespawnEvent.RespawnFlag> respawnFlags;
protected AbstractRespawnEvent(
final Player respawnPlayer, final Location respawnLocation, final boolean isBedSpawn,
final boolean isAnchorSpawn, final boolean missingRespawnBlock, final PlayerRespawnEvent.RespawnReason respawnReason
) {
super(respawnPlayer);
this.respawnLocation = respawnLocation;
this.isBedSpawn = isBedSpawn;
this.isAnchorSpawn = isAnchorSpawn;
this.missingRespawnBlock = missingRespawnBlock;
this.respawnReason = respawnReason;
ImmutableSet.Builder<PlayerRespawnEvent.RespawnFlag> builder = ImmutableSet.builder();
if (respawnReason == PlayerRespawnEvent.RespawnReason.END_PORTAL) builder.add(PlayerRespawnEvent.RespawnFlag.END_PORTAL);
if (this.isBedSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.BED_SPAWN);
if (this.isAnchorSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.ANCHOR_SPAWN);
this.respawnFlags = builder.build();
}
/**
* Gets the current respawn location.
*
* @return the current respawn location
*/
public Location getRespawnLocation() {
return this.respawnLocation.clone();
}
/**
* Gets whether the respawn location is the player's bed.
*
* @return {@code true} if the respawn location is the player's bed
*/
public boolean isBedSpawn() {
return this.isBedSpawn;
}
/**
* Gets whether the respawn location is the player's respawn anchor.
*
* @return {@code true} if the respawn location is the player's respawn anchor
*/
public boolean isAnchorSpawn() {
return this.isAnchorSpawn;
}
/**
* Gets whether the player is missing a valid respawn block.
* <p>
* This will occur if the players respawn block is obstructed,
* or it is the first death after it was either destroyed or
* in case of a respawn anchor, ran out of charges.
*
* @return whether the player is missing a valid respawn block
*/
public boolean isMissingRespawnBlock() {
return this.missingRespawnBlock;
}
/**
* Gets the reason this respawn event was called.
*
* @return the reason the event was called
*/
public PlayerRespawnEvent.RespawnReason getRespawnReason() {
return this.respawnReason;
}
/**
* Gets the set of flags that apply to this respawn.
*
* @return an immutable set of the flags that apply to this respawn
* @deprecated in favour of {@link #getRespawnReason()}/{@link #isBedSpawn}/{@link #isAnchorSpawn()}
*/
@Deprecated
public @Unmodifiable Set<PlayerRespawnEvent.RespawnFlag> getRespawnFlags() {
return this.respawnFlags;
}
}

View File

@ -0,0 +1,63 @@
package io.papermc.paper.event.player;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
/**
* Called when a player creates a filled map by right-clicking an empty map.
*/
@NullMarked
public class PlayerMapFilledEvent extends PlayerEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
private final ItemStack originalItem;
private ItemStack createdMap;
@ApiStatus.Internal
public PlayerMapFilledEvent(final Player player, final ItemStack originalItem, final ItemStack createdMap) {
super(player);
this.originalItem = originalItem;
this.createdMap = createdMap;
}
/**
* Returns a copy of the empty map before it was consumed.
*
* @return cloned original item
*/
public ItemStack getOriginalItem() {
return this.originalItem.clone();
}
/**
* Returns a copy of the filled map which was created.
*
* @return cloned created map item
*/
public ItemStack getCreatedMap() {
return this.createdMap.clone();
}
/**
* Sets the filled map that will be created.
*
* @param createdMap map item
*/
public void setCreatedMap(final ItemStack createdMap) {
this.createdMap = createdMap.clone();
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,32 @@
package io.papermc.paper.event.player;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Event that is fired when a player uses the pick item functionality on a block
* (middle-clicking a block to get the appropriate item).
* After the handling of this event, the contents of the source and the target slot will be swapped,
* and the currently selected hotbar slot of the player will be set to the target slot.
*/
@NullMarked
public class PlayerPickBlockEvent extends PlayerPickItemEvent {
private final Block block;
@ApiStatus.Internal
public PlayerPickBlockEvent(final Player player, final Block block, final boolean includeData, final int targetSlot, final int sourceSlot) {
super(player, includeData, targetSlot, sourceSlot);
this.block = block;
}
/**
* Retrieves the block associated with this event.
*
* @return the block involved in the event
*/
public Block getBlock() {
return this.block;
}
}

View File

@ -0,0 +1,32 @@
package io.papermc.paper.event.player;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Event that is fired when a player uses the pick item functionality on an entity
* (middle-clicking an entity to get the appropriate item).
* After the handling of this event, the contents of the source and the target slot will be swapped,
* and the currently selected hotbar slot of the player will be set to the target slot.
*/
@NullMarked
public class PlayerPickEntityEvent extends PlayerPickItemEvent {
private final Entity entity;
@ApiStatus.Internal
public PlayerPickEntityEvent(final Player player, final Entity entity, final boolean includeData, final int targetSlot, final int sourceSlot) {
super(player, includeData, targetSlot, sourceSlot);
this.entity = entity;
}
/**
* Retrieves the entity associated with this event.
*
* @return the entity involved in the event
*/
public Entity getEntity() {
return this.entity;
}
}

View File

@ -10,27 +10,44 @@ import org.jetbrains.annotations.Range;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
/** /**
* Event that is fired when a player uses the pick item functionality (middle-clicking a block or entity to get the * Event that is fired when a player uses the pick item functionality
* appropriate item). After the handling of this event, the contents of the source and the target slot will be swapped * (middle-clicking a {@link PlayerPickBlockEvent block}
* or {@link PlayerPickEntityEvent entity} to get the appropriate item).
* After the handling of this event, the contents of the source and the target slot will be swapped,
* and the currently selected hotbar slot of the player will be set to the target slot. * and the currently selected hotbar slot of the player will be set to the target slot.
*
* @see PlayerPickEntityEvent
* @see PlayerPickBlockEvent
*/ */
@NullMarked @NullMarked
public class PlayerPickItemEvent extends PlayerEvent implements Cancellable { public abstract class PlayerPickItemEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final boolean includeData;
private int targetSlot; private int targetSlot;
private int sourceSlot; private int sourceSlot;
private boolean cancelled; private boolean cancelled;
@ApiStatus.Internal @ApiStatus.Internal
public PlayerPickItemEvent(final Player player, final int targetSlot, final int sourceSlot) { protected PlayerPickItemEvent(final Player player, final boolean includeData, final int targetSlot, final int sourceSlot) {
super(player); super(player);
this.includeData = includeData;
this.targetSlot = targetSlot; this.targetSlot = targetSlot;
this.sourceSlot = sourceSlot; this.sourceSlot = sourceSlot;
} }
/**
* Checks whether the player wants block/entity data included.
*
* @return {@code true} if data is included, otherwise {@code false}.
*/
public boolean isIncludeData() {
return includeData;
}
/** /**
* Returns the slot the item that is being picked goes into. * Returns the slot the item that is being picked goes into.
* *

View File

@ -0,0 +1,45 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Cat;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Cat.Type} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface CatTypeRegistryEntry {
/**
* Provides the client texture asset of the cat type, which represents the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset clientTextureAsset();
/**
* A mutable builder for the {@link CatTypeRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #clientTextureAsset(ClientTextureAsset)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends CatTypeRegistryEntry, RegistryBuilder<Cat.Type> {
/**
* Sets the client texture asset of the cat type, which is the location of the texture to use.
*
* @param clientTextureAsset the client texture asset.
* @return this builder instance.
* @see CatTypeRegistryEntry#clientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder clientTextureAsset(ClientTextureAsset clientTextureAsset);
}
}

View File

@ -0,0 +1,78 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Chicken;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Chicken.Variant} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface ChickenVariantRegistryEntry {
/**
* The model of the chicken variant to render the configured texture on.
*/
enum Model {
/**
* The normal chicken model.
*/
NORMAL,
/**
* The cold chicken model.
*/
COLD,
}
/**
* Provides the client texture asset of the chicken variant, which represents the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset clientTextureAsset();
/**
* Provides the model of the chicken variant.
*
* @return the model.
*/
Model model();
/**
* A mutable builder for the {@link ChickenVariantRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #clientTextureAsset(ClientTextureAsset)}</li>
* <li>{@link #model(Model)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends ChickenVariantRegistryEntry, RegistryBuilder<Chicken.Variant> {
/**
* Sets the client texture asset of the chicken variant, which is the location of the texture to use.
*
* @param clientTextureAsset the client texture asset.
* @return this builder instance.
* @see ChickenVariantRegistryEntry#clientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder clientTextureAsset(ClientTextureAsset clientTextureAsset);
/**
* Sets the model to use for this chicken variant.
*
* @param model the model.
* @return this builder instance.
* @see ChickenVariantRegistryEntry#model()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder model(Model model);
}
}

View File

@ -0,0 +1,83 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Cow;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Cow.Variant} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface CowVariantRegistryEntry {
/**
* The model of the cow variant to render the configured texture on.
*/
enum Model {
/**
* The normal cow model.
*/
NORMAL,
/**
* The cold cow model.
*/
COLD,
/**
* The warm cow model.
*/
WARM,
}
/**
* Provides the client texture asset of the cow variant, which represents the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset clientTextureAsset();
/**
* Provides the model of the cow variant.
*
* @return the model.
*/
Model model();
/**
* A mutable builder for the {@link CowVariantRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #clientTextureAsset(ClientTextureAsset)}</li>
* <li>{@link #model(Model)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends CowVariantRegistryEntry, RegistryBuilder<Cow.Variant> {
/**
* Sets the client texture asset of the cow variant, which is the location of the texture to use.
*
* @param clientTextureAsset the client texture asset.
* @return this builder instance.
* @see CowVariantRegistryEntry#clientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder clientTextureAsset(ClientTextureAsset clientTextureAsset);
/**
* Sets the model to use for this cow variant.
*
* @param model the model.
* @return this builder instance.
* @see CowVariantRegistryEntry#model()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder model(Model model);
}
}

View File

@ -0,0 +1,45 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Frog;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Frog.Variant} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface FrogVariantRegistryEntry {
/**
* Provides the client texture asset of the frog variant, which represents the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset clientTextureAsset();
/**
* A mutable builder for the {@link FrogVariantRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #clientTextureAsset(ClientTextureAsset)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends FrogVariantRegistryEntry, RegistryBuilder<Frog.Variant> {
/**
* Sets the client texture asset of the frog variant, which is the location of the texture to use.
*
* @param clientTextureAsset the client texture asset.
* @return this builder instance.
* @see FrogVariantRegistryEntry#clientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder clientTextureAsset(ClientTextureAsset clientTextureAsset);
}
}

View File

@ -0,0 +1,78 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Pig;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Pig.Variant} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface PigVariantRegistryEntry {
/**
* The model of the pig variant to render the configured texture on.
*/
enum Model {
/**
* The normal pig model.
*/
NORMAL,
/**
* The cold pig model.
*/
COLD,
}
/**
* Provides the client texture asset of the pig variant, which represents the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset clientTextureAsset();
/**
* Provides the model of the pig variant.
*
* @return the model.
*/
Model model();
/**
* A mutable builder for the {@link PigVariantRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #clientTextureAsset(ClientTextureAsset)}</li>
* <li>{@link #model(Model)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends PigVariantRegistryEntry, RegistryBuilder<Pig.Variant> {
/**
* Sets the client texture asset of the pig variant, which is the location of the texture to use.
*
* @param clientTextureAsset the client texture asset.
* @return this builder instance.
* @see PigVariantRegistryEntry#clientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder clientTextureAsset(ClientTextureAsset clientTextureAsset);
/**
* Sets the model to use for this pig variant.
*
* @param model the model.
* @return this builder instance.
* @see PigVariantRegistryEntry#model()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder model(Model model);
}
}

View File

@ -0,0 +1,81 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.data.client.ClientTextureAsset;
import org.bukkit.entity.Wolf;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link Wolf.Variant} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface WolfVariantRegistryEntry {
/**
* Provides the client texture asset of the wolf variant for when it is angry, which is the location of the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset angryClientTextureAsset();
/**
* Provides the client texture asset of the wolf variant for when it is wild, which is the location of the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset wildClientTextureAsset();
/**
* Provides the client texture asset of the wolf variant for when it is tame, which is the location of the texture to use.
*
* @return the client texture asset.
*/
ClientTextureAsset tameClientTextureAsset();
/**
* A mutable builder for the {@link WolfVariantRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #angryClientTextureAsset(ClientTextureAsset)}</li>
* <li>{@link #wildClientTextureAsset(ClientTextureAsset)}</li>
* <li>{@link #tameClientTextureAsset(ClientTextureAsset)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends WolfVariantRegistryEntry, RegistryBuilder<Wolf.Variant> {
/**
* Sets the client texture asset of the wolf variant for when it is angry, which is the location of the texture to use.
*
* @param angryClientTextureAsset the client texture asset.
* @return this builder instance.
* @see WolfVariantRegistryEntry#angryClientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder angryClientTextureAsset(ClientTextureAsset angryClientTextureAsset);
/**
* Sets the client texture asset of the wolf variant for when it is wild, which is the location of the texture to use.
*
* @param wildClientTextureAsset the client texture asset.
* @return this builder instance.
* @see WolfVariantRegistryEntry#wildClientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder wildClientTextureAsset(ClientTextureAsset wildClientTextureAsset);
/**
* Sets the client texture asset of the wolf variant for when it is tame, which is the location of the texture to use.
*
* @param tameClientTextureAsset the client texture asset.
* @return this builder instance.
* @see WolfVariantRegistryEntry#tameClientTextureAsset()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder tameClientTextureAsset(ClientTextureAsset tameClientTextureAsset);
}
}

View File

@ -0,0 +1,66 @@
package io.papermc.paper.registry.data.client;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.KeyPattern;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific representation of a client texture asset, composed of an identifier and a path.
* Follows the same, version-specific, compatibility guarantees as the RegistryEntry types it is used in.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface ClientTextureAsset {
/**
* The identifier of the client texture asset, uniquely identifying the asset on the client.
*
* @return the identifier.
*/
Key identifier();
/**
* The path of the texture on the client, split into a namespace and a path/key.
*
* @return the texture path.
*/
Key texturePath();
/**
* Creates a new {@link ClientTextureAsset} with the specified identifier and texture path.
*
* @param identifier the unique identifier for the client texture asset.
* @param texturePath the path where the asset is located on the client.
* @return a new {@code ClientAsset} instance.
*/
@Contract("_,_ -> new")
static ClientTextureAsset clientTextureAsset(final Key identifier, final Key texturePath) {
return new ClientTextureAssetImpl(identifier, texturePath);
}
/**
* Creates a new {@link ClientTextureAsset} using the provided identifier and infers the texture path from it.
*
* @param identifier the unique identifier for the client texture asset.
* @return a new {@code ClientAsset} instance.
*/
@Contract("_ -> new")
static ClientTextureAsset clientTextureAsset(final Key identifier) {
return new ClientTextureAssetImpl(identifier, ClientTextureAssetImpl.pathFromIdentifier(identifier));
}
/**
* Creates a new {@link ClientTextureAsset} from the provided string-formatted {@link Key}
* and infers the texture path from it.
* <p>
* The identifier string must conform to the {@link KeyPattern} format.
*
* @param identifier the string representation of the asset's identifier.
* @return a new {@code ClientAsset} instance.
*/
@Contract("_ -> new")
static ClientTextureAsset clientTextureAsset(final @KeyPattern String identifier) {
return clientTextureAsset(Key.key(identifier));
}
}

View File

@ -0,0 +1,31 @@
package io.papermc.paper.registry.data.client;
import net.kyori.adventure.key.Key;
import org.intellij.lang.annotations.Subst;
import org.jspecify.annotations.NullMarked;
/**
* Package local implementation of the {@link ClientTextureAsset} type.
* Chosen over bridging into server internals as no internal types are required for this.
*/
@NullMarked
record ClientTextureAssetImpl(
Key identifier,
Key texturePath
) implements ClientTextureAsset {
/**
* Constructs the default asset path from the identifier of the asset.
* Mirrors internal logic in net.minecraft.core.ClientAsset
*
* @param identifier the identifier of the asset.
* @return the key/path of the asset.
*/
static Key pathFromIdentifier(@Subst("") final Key identifier) {
return Key.key(
identifier.namespace(),
"textures/" + identifier.value() + ".png"
);
}
}

View File

@ -2,15 +2,27 @@ package io.papermc.paper.registry.event;
import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.BannerPatternRegistryEntry; import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
import io.papermc.paper.registry.data.CatTypeRegistryEntry;
import io.papermc.paper.registry.data.ChickenVariantRegistryEntry;
import io.papermc.paper.registry.data.CowVariantRegistryEntry;
import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.DamageTypeRegistryEntry;
import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
import io.papermc.paper.registry.data.FrogVariantRegistryEntry;
import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry;
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
import io.papermc.paper.registry.data.PigVariantRegistryEntry;
import io.papermc.paper.registry.data.WolfVariantRegistryEntry;
import org.bukkit.Art; import org.bukkit.Art;
import org.bukkit.GameEvent; import org.bukkit.GameEvent;
import org.bukkit.block.banner.PatternType; import org.bukkit.block.banner.PatternType;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Wolf;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
@ -28,9 +40,15 @@ public final class RegistryEvents {
// @GeneratedFrom 1.21.5 // @GeneratedFrom 1.21.5
public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT); public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
public static final RegistryEventProvider<DamageType, DamageTypeRegistryEntry.Builder> DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE); public static final RegistryEventProvider<DamageType, DamageTypeRegistryEntry.Builder> DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE);
public static final RegistryEventProvider<Wolf.Variant, WolfVariantRegistryEntry.Builder> WOLF_VARIANT = create(RegistryKey.WOLF_VARIANT);
public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT); public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT);
public static final RegistryEventProvider<PatternType, BannerPatternRegistryEntry.Builder> BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN); public static final RegistryEventProvider<PatternType, BannerPatternRegistryEntry.Builder> BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN);
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
public static final RegistryEventProvider<Cat.Type, CatTypeRegistryEntry.Builder> CAT_VARIANT = create(RegistryKey.CAT_VARIANT);
public static final RegistryEventProvider<Frog.Variant, FrogVariantRegistryEntry.Builder> FROG_VARIANT = create(RegistryKey.FROG_VARIANT);
public static final RegistryEventProvider<Chicken.Variant, ChickenVariantRegistryEntry.Builder> CHICKEN_VARIANT = create(RegistryKey.CHICKEN_VARIANT);
public static final RegistryEventProvider<Cow.Variant, CowVariantRegistryEntry.Builder> COW_VARIANT = create(RegistryKey.COW_VARIANT);
public static final RegistryEventProvider<Pig.Variant, PigVariantRegistryEntry.Builder> PIG_VARIANT = create(RegistryKey.PIG_VARIANT);
// End generate - RegistryEvents // End generate - RegistryEvents
private RegistryEvents() { private RegistryEvents() {

View File

@ -0,0 +1,82 @@
package io.papermc.paper.world.damagesource;
import io.papermc.paper.InternalAPIBridge;
import org.bukkit.damage.DamageSource;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a combat entry
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface CombatEntry {
/**
* Gets the damage source.
*
* @return the damage source
*/
DamageSource getDamageSource();
/**
* Gets the amount of damage caused.
*
* @return the amount of damage caused
*/
float getDamage();
/**
* Gets the fall location type at the time of this damage.
*
* @return the fall location type
*/
@Nullable FallLocationType getFallLocationType();
/**
* Gets the fall distance at the time of this damage.
*
* @return the fall distance
*/
float getFallDistance();
/**
* Creates a new combat entry.
* <p>
* The fall location and fall distance will be calculated from the entity's current state.
*
* @param entity entity
* @param damageSource damage source
* @param damage damage amount
* @return combat entry
* @see #combatEntry(DamageSource, float, FallLocationType, float)
*/
static CombatEntry combatEntry(final LivingEntity entity, final DamageSource damageSource, final float damage) {
return InternalAPIBridge.get().createCombatEntry(entity, damageSource, damage);
}
/**
* Creates a new combat entry
*
* @param damageSource damage source
* @param damage damage amount
* @param fallLocationType fall location type
* @param fallDistance fall distance
* @return a new combat entry
* @see CombatTracker#calculateFallLocationType()
* @see Entity#getFallDistance()
*/
static CombatEntry combatEntry(
final DamageSource damageSource,
final float damage,
@Nullable final FallLocationType fallLocationType,
final float fallDistance
) {
return InternalAPIBridge.get().createCombatEntry(damageSource, damage, fallLocationType, fallDistance);
}
}

View File

@ -0,0 +1,110 @@
package io.papermc.paper.world.damagesource;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.List;
/**
* Represents entity's combat tracker
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface CombatTracker {
/**
* Gets the entity behind this combat tracker.
*
* @return the entity behind this combat tracker
*/
LivingEntity getEntity();
/**
* Gets the list of recorded combat entries.
* <p>
* The returned list is a copy, so any modifications
* to its contents won't affect this entity's
* combat history.
*
* @return the list of combat entries
* @see #setCombatEntries(List)
*/
List<CombatEntry> getCombatEntries();
/**
* Sets the entity's combat history.
* <p>
* Note that overriding the entity's combat history won't
* affect the entity's current or new combat state.
* Reset the current combat state and register new combat entries instead
* if you want the new history to affect the combat state.
*
* @param combatEntries combat entries
* @see #resetCombatState()
* @see #addCombatEntry(CombatEntry)
*/
void setCombatEntries(List<CombatEntry> combatEntries);
/**
* Calculates the most significant fall damage entry.
*
* @return the most significant fall damage entry
*/
@Nullable CombatEntry computeMostSignificantFall();
/**
* Checks whether the entity is in combat,
* i.e. has taken damage from an entity
* since the combat tracking has begun.
*
* @return whether the entity is in combat
*/
boolean isInCombat();
/**
* Checks whether the entity has started recording damage,
* i.e. its combat tracking is active.
*
* @return whether the entity has started recording damage
*/
boolean isTakingDamage();
/**
* Gets the last or current combat duration.
*
* @return the combat duration
* @see #isInCombat()
*/
int getCombatDuration();
/**
* Adds a new entry the pool of combat entries,
* updating the entity's combat state.
*
* @param combatEntry combat entry
*/
void addCombatEntry(CombatEntry combatEntry);
/**
* Constructs a death message based on the current combat history.
*
* @return a death message
*/
Component getDeathMessage();
/**
* Resets entity's combat state, clearing combat history.
*/
void resetCombatState();
/**
* Calculates the fall location type from the current entity's location.
*
* @return the fall location type
*/
@Nullable FallLocationType calculateFallLocationType();
}

View File

@ -0,0 +1,63 @@
package io.papermc.paper.world.damagesource;
import net.kyori.adventure.translation.Translatable;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Represents a type of location from which the entity fell.
*/
@NullMarked
@ApiStatus.Experimental
public sealed interface FallLocationType extends Translatable permits FallLocationTypeImpl {
/**
* Gets the fall location id.
*
* @return the fall location id
*/
String id();
/**
* Gets the translation key used for a fall death message
* caused by falling from this location
*
* @return the translation key
*/
@Override
String translationKey();
/**
* The entity was not within a special fall location.
*/
FallLocationType GENERIC = new FallLocationTypeImpl("generic");
/**
* The entity was within the ladder.
*/
FallLocationType LADDER = new FallLocationTypeImpl("ladder");
/**
* The entity was in vines.
*/
FallLocationType VINES = new FallLocationTypeImpl("vines");
/**
* The entity was in weeping wines.
*/
FallLocationType WEEPING_VINES = new FallLocationTypeImpl("weeping_vines");
/**
* The entity was in twisting vines.
*/
FallLocationType TWISTING_VINES = new FallLocationTypeImpl("twisting_vines");
/**
* The entity was in scaffolding.
*/
FallLocationType SCAFFOLDING = new FallLocationTypeImpl("scaffolding");
/**
* The entity was within some other climbable block.
*/
FallLocationType OTHER_CLIMBABLE = new FallLocationTypeImpl("other_climbable");
/**
* The entity was in water.
*/
FallLocationType WATER = new FallLocationTypeImpl("water");
}

View File

@ -0,0 +1,14 @@
package io.papermc.paper.world.damagesource;
import org.jspecify.annotations.NullMarked;
@NullMarked
record FallLocationTypeImpl(String id) implements FallLocationType {
@Override
public String translationKey() {
// Same as net.minecraft.world.damagesource.FallLocation#languageKey
return "death.fell.accident." + this.id;
}
}

View File

@ -14,6 +14,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
import io.papermc.paper.configuration.ServerConfiguration;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Warning.WarningState; import org.bukkit.Warning.WarningState;
import org.bukkit.advancement.Advancement; import org.bukkit.advancement.Advancement;
@ -1435,6 +1436,15 @@ public final class Bukkit {
return server.getOnlineMode(); return server.getOnlineMode();
} }
/**
* Retrieves the server configuration.
*
* @return the instance of ServerConfiguration containing the server's configuration details
*/
public static @NotNull ServerConfiguration getServerConfig() {
return server.getServerConfig();
}
/** /**
* Gets whether this server allows flying or not. * Gets whether this server allows flying or not.
* *

View File

@ -732,7 +732,7 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm
/** /**
* Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ())
* @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ())
* @throws NullPointerException if {{@link #getWorld()}} is {@code null} * @throws NullPointerException if {@link #getWorld()} is {@code null}
*/ */
@NotNull @NotNull
public Location toHighestLocation() { public Location toHighestLocation() {

View File

@ -5,10 +5,12 @@ import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.RegistryKey;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import org.jetbrains.annotations.NotNull; import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable; import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - translation keys @NullMarked
public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable {
// Start generate - MusicInstrument // Start generate - MusicInstrument
// @GeneratedFrom 1.21.5 // @GeneratedFrom 1.21.5
@ -38,7 +40,7 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran
*/ */
@Nullable @Nullable
@Deprecated(since = "1.20.1") @Deprecated(since = "1.20.1")
public static MusicInstrument getByKey(@NotNull NamespacedKey namespacedKey) { public static MusicInstrument getByKey(final NamespacedKey namespacedKey) {
return Registry.INSTRUMENT.get(namespacedKey); return Registry.INSTRUMENT.get(namespacedKey);
} }
@ -48,25 +50,50 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran
* @return the memoryKeys * @return the memoryKeys
* @deprecated use {@link Registry#iterator()}. * @deprecated use {@link Registry#iterator()}.
*/ */
@NotNull
@Deprecated(since = "1.20.1") @Deprecated(since = "1.20.1")
public static Collection<MusicInstrument> values() { public static Collection<MusicInstrument> values() {
return Collections.unmodifiableCollection(Lists.newArrayList(Registry.INSTRUMENT)); return Collections.unmodifiableCollection(Lists.newArrayList(Registry.INSTRUMENT));
} }
@NotNull private static MusicInstrument getInstrument(final String key) {
private static MusicInstrument getInstrument(@NotNull String key) {
return RegistryAccess.registryAccess().getRegistry(RegistryKey.INSTRUMENT).getOrThrow(NamespacedKey.minecraft(key)); return RegistryAccess.registryAccess().getRegistry(RegistryKey.INSTRUMENT).getOrThrow(NamespacedKey.minecraft(key));
} }
// Paper start - deprecate getKey /**
* Gets the use duration of this music instrument.
*
* @return the duration expressed in seconds.
*/
public abstract float getDuration();
/**
* Gets the range of the sound.
*
* @return the range of the sound.
*/
public abstract float getRange();
/**
* Provides the description of this instrument as displayed to the client.
*
* @return the description component.
*/
public abstract Component description();
/**
* Gets the sound for this instrument.
*
* @return the sound
*/
public abstract Sound getSound();
/** /**
* @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)},
* and {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT}. MusicInstruments can exist without a key. * and {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT}. MusicInstruments can exist without a key.
*/ */
@Deprecated(forRemoval = true, since = "1.20.5") @Deprecated(forRemoval = true, since = "1.20.5")
@Override @Override
public abstract @NotNull NamespacedKey getKey(); public abstract NamespacedKey getKey();
/** /**
* @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)},
@ -78,15 +105,11 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran
return Keyed.super.key(); return Keyed.super.key();
} }
// Paper end - deprecate getKey
// Paper start - mark translation key as deprecated
/** /**
* @deprecated this method assumes that the instrument description * @deprecated this method assumes that the instrument description
* always be a translatable component which is not guaranteed. * always be a translatable component which is not guaranteed.
*/ */
@Override @Override
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public abstract @NotNull String translationKey(); public abstract String translationKey();
// Paper end - mark translation key as deprecated
} }

View File

@ -287,13 +287,28 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
// Paper end // Paper end
/** /**
* Gets the Location where the player will spawn at, null if they * Gets the Location where the player will spawn at, {@code null} if they
* don't have a valid respawn point.
* <br>
* Unlike online players, the location if found will not be loaded by default.
*
* @return respawn location if exists, otherwise {@code null}.
* @see #getRespawnLocation(boolean) for more fine-grained control over chunk loading and validation behaviour.
*/
default @Nullable Location getRespawnLocation() {
return this.getRespawnLocation(false); // keep old behavior for offline players
}
/**
* Gets the Location where the player will spawn at, {@code null} if they
* don't have a valid respawn point. * don't have a valid respawn point.
* *
* @return respawn location if exists, otherwise null. * @param loadLocationAndValidate load the expected respawn location to retrieve the exact position of the spawn
* block and check if this position is still valid or not. Loading the location
* will induce a sync chunk load and must hence be used with caution.
* @return respawn location if exists, otherwise {@code null}.
*/ */
@Nullable @Nullable Location getRespawnLocation(boolean loadLocationAndValidate);
public Location getRespawnLocation();
/** /**
* Increments the given statistic for this player. * Increments the given statistic for this player.

View File

@ -14,6 +14,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
import io.papermc.paper.configuration.ServerConfiguration;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
@ -1267,6 +1268,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/ */
public boolean getOnlineMode(); public boolean getOnlineMode();
/**
* Retrieves the server configuration.
*
* @return the instance of ServerConfiguration containing the server's configuration details
*/
@NotNull ServerConfiguration getServerConfig();
/** /**
* Gets whether this server allows flying or not. * Gets whether this server allows flying or not.
* *
@ -2319,6 +2327,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API
* wherever possible, rather than directly reading from a server config. * wherever possible, rather than directly reading from a server config.
* *
* @see #getServerConfig()
* @return The server's spigot config. * @return The server's spigot config.
*/ */
@Deprecated(since = "1.21.4", forRemoval = true) @Deprecated(since = "1.21.4", forRemoval = true)
@ -2331,6 +2340,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API
* wherever possible, rather than directly reading from a server config. * wherever possible, rather than directly reading from a server config.
* *
* @see #getServerConfig()
* @return The server's bukkit config. * @return The server's bukkit config.
*/ */
// Paper start // Paper start
@ -2345,6 +2355,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API
* wherever possible, rather than directly reading from a server config. * wherever possible, rather than directly reading from a server config.
* *
* @see #getServerConfig()
* @return The server's spigot config. * @return The server's spigot config.
*/ */
@Deprecated(since = "1.21.4", forRemoval = true) @Deprecated(since = "1.21.4", forRemoval = true)
@ -2358,6 +2369,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API
* wherever possible, rather than directly reading from a server config. * wherever possible, rather than directly reading from a server config.
* *
* @see #getServerConfig()
* @return The server's paper config. * @return The server's paper config.
*/ */
@Deprecated(since = "1.21.4", forRemoval = true) @Deprecated(since = "1.21.4", forRemoval = true)

View File

@ -7,7 +7,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.regex.Matcher; // Paper import java.util.regex.Matcher; // Paper
import java.util.regex.Pattern; // Paper import java.util.regex.Pattern; // Paper
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -27,7 +29,7 @@ public class FormattedCommandAlias extends Command {
if (throwable instanceof IllegalArgumentException) { if (throwable instanceof IllegalArgumentException) {
sender.sendMessage(throwable.getMessage()); sender.sendMessage(throwable.getMessage());
} else { } else {
sender.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); sender.sendMessage(Component.text("An internal error occurred while attempting to perform this command", NamedTextColor.RED));
} }
return false; return false;
} }

View File

@ -5,7 +5,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -14,32 +13,26 @@ import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.command.defaults.BukkitCommand; import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.command.defaults.HelpCommand; import org.bukkit.command.defaults.HelpCommand;
import org.bukkit.command.defaults.PluginsCommand;
import org.bukkit.command.defaults.ReloadCommand; import org.bukkit.command.defaults.ReloadCommand;
import org.bukkit.command.defaults.VersionCommand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil; import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class SimpleCommandMap implements CommandMap { public class SimpleCommandMap implements CommandMap {
protected final Map<String, Command> knownCommands; // Paper protected final Map<String, Command> knownCommands;
private final Server server; private final Server server;
// Paper start
@org.jetbrains.annotations.ApiStatus.Internal @org.jetbrains.annotations.ApiStatus.Internal
public SimpleCommandMap(@NotNull final Server server, Map<String, Command> backing) { public SimpleCommandMap(@NotNull final Server server, Map<String, Command> backing) {
this.knownCommands = backing; this.knownCommands = backing;
// Paper end
this.server = server; this.server = server;
setDefaultCommands(); setDefaultCommands();
} }
private void setDefaultCommands() { private void setDefaultCommands() {
register("bukkit", new VersionCommand("version"));
register("bukkit", new ReloadCommand("reload")); register("bukkit", new ReloadCommand("reload"));
//register("bukkit", new PluginsCommand("plugins")); // Paper register("bukkit", new co.aikar.timings.TimingsCommand("timings"));
register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper
} }
public void setFallbackCommands() { public void setFallbackCommands() {

View File

@ -10,8 +10,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.help.HelpMap; import org.bukkit.help.HelpMap;
@ -78,31 +81,29 @@ public class HelpCommand extends BukkitCommand {
} }
if (topic == null || !topic.canSee(sender)) { if (topic == null || !topic.canSee(sender)) {
sender.sendMessage(ChatColor.RED + "No help for " + command); sender.sendMessage(Component.text("No help for " + command, NamedTextColor.RED));
return true; return true;
} }
ChatPaginator.ChatPage page = ChatPaginator.paginate(topic.getFullText(sender), pageNumber, pageWidth, pageHeight); ChatPaginator.ChatPage page = ChatPaginator.paginate(topic.getFullText(sender), pageNumber, pageWidth, pageHeight);
StringBuilder header = new StringBuilder(); TextComponent.Builder header = Component.text()
header.append(ChatColor.YELLOW); .append(Component.text("--------- ", NamedTextColor.YELLOW))
header.append("--------- "); .append(Component.text("Help: ", NamedTextColor.WHITE))
header.append(ChatColor.WHITE); .append(Component.text(topic.getName()))
header.append("Help: "); .append(Component.space());
header.append(topic.getName());
header.append(" ");
if (page.getTotalPages() > 1) { if (page.getTotalPages() > 1) {
header.append("("); header.append(Component.text("("))
header.append(page.getPageNumber()); .append(Component.text(page.getPageNumber()))
header.append("/"); .append(Component.text("/"))
header.append(page.getTotalPages()); .append(Component.text(page.getTotalPages()))
header.append(") "); .append(Component.text(") "));
} }
header.append(ChatColor.YELLOW); final TextComponent headerComponent = header.build();
for (int i = header.length(); i < ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH; i++) { final int headerSize = PlainTextComponentSerializer.plainText().serialize(headerComponent).length();
header.append("-"); final int headerEndingCount = Math.max(0, ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - headerSize);
}
sender.sendMessage(header.toString()); sender.sendMessage(headerComponent.append(Component.text("-".repeat(headerEndingCount), NamedTextColor.YELLOW)));
sender.sendMessage(page.getLines()); sender.sendMessage(page.getLines());

View File

@ -32,6 +32,7 @@ import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
@Deprecated(forRemoval = true)
public class VersionCommand extends BukkitCommand { public class VersionCommand extends BukkitCommand {
private VersionFetcher versionFetcher; // Paper - version command 2.0 private VersionFetcher versionFetcher; // Paper - version command 2.0
private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration

View File

@ -1,8 +1,38 @@
package org.bukkit.entity; package org.bukkit.entity;
import org.jspecify.annotations.NullMarked;
/** /**
* Represents an Armadillo. * Represents an Armadillo.
*/ */
@NullMarked
public interface Armadillo extends Animals { public interface Armadillo extends Animals {
/**
* Get the current state of the armadillo.
*
* @return the state of the armadillo
*/
State getState();
/**
* Attempt to roll up if the armadillo is {@link State#IDLE}
*/
void rollUp();
/**
* Attempt to roll out if the armadillo is not {@link State#IDLE}
*/
void rollOut();
/**
* Represents the current state of the armadillo.
*/
enum State {
IDLE,
ROLLING,
SCARED,
UNROLLING;
}
} }

View File

@ -5,6 +5,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import io.papermc.paper.datacomponent.DataComponentView; import io.papermc.paper.datacomponent.DataComponentView;
import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.LookAnchor;
import net.kyori.adventure.util.TriState;
import org.bukkit.Chunk; // Paper import org.bukkit.Chunk; // Paper
import org.bukkit.EntityEffect; import org.bukkit.EntityEffect;
import org.bukkit.Location; import org.bukkit.Location;
@ -19,6 +20,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Directional; import org.bukkit.material.Directional;
import org.bukkit.metadata.Metadatable; import org.bukkit.metadata.Metadatable;
import org.bukkit.persistence.PersistentDataHolder; import org.bukkit.persistence.PersistentDataHolder;
@ -296,17 +298,43 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
/** /**
* Sets if the entity has visual fire (it will always appear to be on fire). * Sets if the entity has visual fire (it will always appear to be on fire).
* *
* @deprecated This method doesn't allow visually extinguishing a burning entity,
* use {@link #setVisualFire(TriState)} instead
* @param fire whether visual fire is enabled * @param fire whether visual fire is enabled
*/ */
@Deprecated
void setVisualFire(boolean fire); void setVisualFire(boolean fire);
/**
* Sets if the entity has visual fire (it will always appear to be on fire).
* <ul>
* <li>{@link TriState#NOT_SET} will revert the entity's visual fire to default</li>
* <li>{@link TriState#TRUE} will make the entity appear to be on fire</li>
* <li>{@link TriState#FALSE} will make the entity appear to be not on fire</li>
* </ul>
*
* @param fire a TriState value representing the state of the visual fire.
*/
void setVisualFire(@NotNull TriState fire);
/** /**
* Gets if the entity has visual fire (it will always appear to be on fire). * Gets if the entity has visual fire (it will always appear to be on fire).
* *
* @deprecated This method can't properly reflect the three possible states of visual fire,
* use {@link #getVisualFire()} instead
* @return whether visual fire is enabled * @return whether visual fire is enabled
*/ */
@Deprecated
boolean isVisualFire(); boolean isVisualFire();
/**
* Retrieves the visual fire state of the object.
*
* @return A TriState indicating the current visual fire state.
*/
@NotNull
TriState getVisualFire();
/** /**
* Returns the entity's current freeze ticks (amount of ticks the entity has * Returns the entity's current freeze ticks (amount of ticks the entity has
* been in powdered snow). * been in powdered snow).
@ -511,6 +539,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/ */
public boolean eject(); public boolean eject();
/**
* Gets the {@link ItemStack} that a player would select / create (in creative mode)
* when using the pick block action on this entity.
*
* @return item stack result or an empty item stack
*/
@NotNull
ItemStack getPickItemStack();
/** /**
* Returns the distance this entity has fallen * Returns the distance this entity has fallen
* *

View File

@ -1,6 +1,7 @@
package org.bukkit.entity; package org.bukkit.entity;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import io.papermc.paper.event.entity.FishHookStateChangeEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -306,6 +307,7 @@ public interface FishHook extends Projectile {
/** /**
* Represents a state in which a fishing hook may be. * Represents a state in which a fishing hook may be.
* State transitions can be listened for using {@link FishHookStateChangeEvent}
*/ */
public enum HookState { public enum HookState {

View File

@ -485,9 +485,11 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
* to validate if the current respawn location is still valid. * to validate if the current respawn location is still valid.
* *
* @return respawn location if exists, otherwise null. * @return respawn location if exists, otherwise null.
* @deprecated this method doesn't take the respawn angle into account, use
* {@link Player#getRespawnLocation(boolean)} with loadLocationAndValidate = false instead
*/ */
@Nullable @Deprecated(since = "1.21.5")
Location getPotentialRespawnLocation(); @Nullable Location getPotentialRespawnLocation();
/** /**
* @return the player's fishing hook if they are fishing * @return the player's fishing hook if they are fishing

View File

@ -4,6 +4,8 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import io.papermc.paper.world.damagesource.CombatTracker;
import io.papermc.paper.world.damagesource.FallLocationType;
import org.bukkit.FluidCollisionMode; import org.bukkit.FluidCollisionMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -21,6 +23,7 @@ import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team; import org.bukkit.scoreboard.Team;
import org.bukkit.util.RayTraceResult; import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -1452,4 +1455,12 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
*/ */
boolean canUseEquipmentSlot(org.bukkit.inventory.@NotNull EquipmentSlot slot); boolean canUseEquipmentSlot(org.bukkit.inventory.@NotNull EquipmentSlot slot);
// Paper end - Expose canUseSlot // Paper end - Expose canUseSlot
/**
* Gets the entity's combat tracker
*
* @return the entity's combat tracker
*/
@ApiStatus.Experimental
@NotNull CombatTracker getCombatTracker();
} }

View File

@ -12,6 +12,7 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.LookAnchor;
import io.papermc.paper.entity.PlayerGiveResult; import io.papermc.paper.entity.PlayerGiveResult;
import io.papermc.paper.math.Position;
import org.bukkit.BanEntry; import org.bukkit.BanEntry;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.Effect; import org.bukkit.Effect;
@ -52,7 +53,6 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.PluginMessageRecipient; import org.bukkit.plugin.messaging.PluginMessageRecipient;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
@ -293,7 +293,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* set in the client, the {@link CompletableFuture} will complete with a * set in the client, the {@link CompletableFuture} will complete with a
* null value. * null value.
*/ */
CompletableFuture<byte[]> retrieveCookie(NamespacedKey key); CompletableFuture<byte @Nullable []> retrieveCookie(NamespacedKey key);
/** /**
* Stores a cookie in this player's client. * Stores a cookie in this player's client.
@ -545,6 +545,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/ */
public boolean isSleepingIgnored(); public boolean isSleepingIgnored();
/**
* Gets the Location where the player will spawn at, {@code null} if they
* don't have a valid respawn point.
* <br>
* Unlike offline players, the location if found will be loaded to validate by default.
*
* @return respawn location if exists, otherwise {@code null}.
* @see #getRespawnLocation(boolean) for more fine-grained control over chunk loading and validation behaviour.
*/
@Override
default @Nullable Location getRespawnLocation() {
return this.getRespawnLocation(true);
}
/** /**
* Sets the Location where the player will spawn at their bed. * Sets the Location where the player will spawn at their bed.
* *
@ -1164,7 +1178,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* (constructed e.g. via {@link Material#createBlockData()}) * (constructed e.g. via {@link Material#createBlockData()})
*/ */
@Deprecated // Paper @Deprecated // Paper
public void sendSignChange(Location loc, @Nullable String[] lines) throws IllegalArgumentException; public void sendSignChange(Location loc, @Nullable String @Nullable [] lines) throws IllegalArgumentException;
/** /**
* Send a sign change. This fakes a sign change packet for a user at * Send a sign change. This fakes a sign change packet for a user at
@ -1190,7 +1204,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* (constructed e.g. via {@link Material#createBlockData()}) * (constructed e.g. via {@link Material#createBlockData()})
*/ */
@Deprecated // Paper @Deprecated // Paper
public void sendSignChange(Location loc, @Nullable String[] lines, DyeColor dyeColor) throws IllegalArgumentException; public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor) throws IllegalArgumentException;
/** /**
* Send a sign change. This fakes a sign change packet for a user at * Send a sign change. This fakes a sign change packet for a user at
@ -1217,7 +1231,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* (constructed e.g. via {@link Material#createBlockData()}) * (constructed e.g. via {@link Material#createBlockData()})
*/ */
@Deprecated // Paper @Deprecated // Paper
public void sendSignChange(Location loc, @Nullable String[] lines, DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException; public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException;
/** /**
* Send a TileState change. This fakes a TileState change for a user at * Send a TileState change. This fakes a TileState change for a user at
@ -2822,7 +2836,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes * @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long. * long.
*/ */
public void addResourcePack(UUID id, String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); public void addResourcePack(UUID id, String url, byte @Nullable [] hash, @Nullable String prompt, boolean force);
/** /**
* Request that the player's client remove a resource pack sent by the * Request that the player's client remove a resource pack sent by the
@ -3435,6 +3449,21 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/ */
public void openSign(Sign sign, Side side); public void openSign(Sign sign, Side side);
/**
* Open a sign for editing by the player.
* <p>
* The sign must only be placed locally for the player, which can be done with {@link #sendBlockChange(Location, BlockData)} and {@link #sendBlockUpdate(Location, TileState)}.
* A side-effect of this is that normal events, like {@link org.bukkit.event.block.SignChangeEvent} will not be called (unless there is an actual sign in the world).
* Additionally, the client may enforce distance limits to the opened position.
* </p>
*
* @param block The block where the client has a sign placed
* @param side The side to edit
* @see io.papermc.paper.event.packet.UncheckedSignChangeEvent
*/
@ApiStatus.Experimental
void openVirtualSign(Position block, Side side);
/** /**
* Shows the demo screen to the player, this screen is normally only seen in * Shows the demo screen to the player, this screen is normally only seen in
* the demo version of the game. * the demo version of the game.

View File

@ -5,7 +5,6 @@ import io.papermc.paper.registry.RegistryKey;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.Keyed; import org.bukkit.Keyed;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**

View File

@ -71,7 +71,7 @@ public interface Zombie extends Monster, Ageable {
/** /**
* Gets the amount of ticks until this entity will be converted to a Drowned * Gets the amount of ticks until this entity will be converted to a Drowned
* as a result of being underwater. * as a result of being underwater.
* * <br>
* When this reaches 0, the entity will be converted. * When this reaches 0, the entity will be converted.
* *
* @return conversion time * @return conversion time
@ -82,7 +82,7 @@ public interface Zombie extends Monster, Ageable {
/** /**
* Sets the amount of ticks until this entity will be converted to a Drowned * Sets the amount of ticks until this entity will be converted to a Drowned
* as a result of being underwater. * as a result of being underwater.
* * <br>
* When this reaches 0, the entity will be converted. A value of less than 0 * When this reaches 0, the entity will be converted. A value of less than 0
* will stop the current conversion process without converting the current * will stop the current conversion process without converting the current
* entity. * entity.
@ -121,7 +121,6 @@ public interface Zombie extends Monster, Ageable {
* Make zombie start drowning * Make zombie start drowning
* *
* @param drownedConversionTime Amount of time until zombie converts from drowning * @param drownedConversionTime Amount of time until zombie converts from drowning
*
* @deprecated See {@link #setConversionTime(int)} * @deprecated See {@link #setConversionTime(int)}
*/ */
@Deprecated @Deprecated
@ -136,7 +135,7 @@ public interface Zombie extends Monster, Ageable {
* Set if zombie has its arms raised * Set if zombie has its arms raised
* *
* @param raised True to raise arms * @param raised True to raise arms
* @deprecated use {{@link #setAggressive(boolean)}} * @deprecated use {@link #setAggressive(boolean)}
*/ */
@Deprecated @Deprecated
void setArmsRaised(boolean raised); void setArmsRaised(boolean raised);

View File

@ -6,11 +6,12 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.NullMarked;
/** /**
* Called when an entity is about to be replaced by another entity. * Called when an entity is about to be replaced by another entity.
*/ */
@NullMarked
public class EntityTransformEvent extends EntityEvent implements Cancellable { public class EntityTransformEvent extends EntityEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
@ -22,10 +23,10 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable {
private boolean cancelled; private boolean cancelled;
@ApiStatus.Internal @ApiStatus.Internal
public EntityTransformEvent(@NotNull Entity original, @NotNull List<Entity> convertedList, @NotNull TransformReason transformReason) { public EntityTransformEvent(Entity original, List<Entity> convertedList, TransformReason transformReason) {
super(original); super(original);
this.convertedList = Collections.unmodifiableList(convertedList); this.convertedList = Collections.unmodifiableList(convertedList);
this.converted = convertedList.get(0); this.converted = convertedList.getFirst();
this.transformReason = transformReason; this.transformReason = transformReason;
} }
@ -34,7 +35,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable {
* *
* @return The transformed entities. * @return The transformed entities.
*/ */
@NotNull
public List<Entity> getTransformedEntities() { public List<Entity> getTransformedEntities() {
return this.convertedList; return this.convertedList;
} }
@ -47,7 +47,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable {
* @return The transformed entity. * @return The transformed entity.
* @see #getTransformedEntities() * @see #getTransformedEntities()
*/ */
@NotNull
public Entity getTransformedEntity() { public Entity getTransformedEntity() {
return this.converted; return this.converted;
} }
@ -57,7 +56,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable {
* *
* @return The reason for conversion that has occurred. * @return The reason for conversion that has occurred.
*/ */
@NotNull
public TransformReason getTransformReason() { public TransformReason getTransformReason() {
return this.transformReason; return this.transformReason;
} }
@ -72,13 +70,11 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable {
this.cancelled = cancel; this.cancelled = cancel;
} }
@NotNull
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers() {
return HANDLER_LIST; return HANDLER_LIST;
} }
@NotNull
public static HandlerList getHandlerList() { public static HandlerList getHandlerList() {
return HANDLER_LIST; return HANDLER_LIST;
} }

View File

@ -18,27 +18,27 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final AreaEffectCloud entity; private final AreaEffectCloud effectCloud;
private boolean allowEmptyAreaEffectCreation; private boolean allowEmptyAreaEffectCreation;
private boolean cancelled; private boolean cancelled;
@ApiStatus.Internal @ApiStatus.Internal
@Deprecated(since = "1.20.2", forRemoval = true) @Deprecated(since = "1.20.2", forRemoval = true)
public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final AreaEffectCloud entity) { public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final AreaEffectCloud effectCloud) {
this(potion, null, null, null, entity); this(potion, null, null, null, effectCloud);
} }
@ApiStatus.Internal @ApiStatus.Internal
public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @Nullable Entity hitEntity, @Nullable Block hitBlock, @Nullable BlockFace hitFace, @NotNull final AreaEffectCloud entity) { public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @Nullable Entity hitEntity, @Nullable Block hitBlock, @Nullable BlockFace hitFace, @NotNull final AreaEffectCloud effectCloud) {
super(potion, hitEntity, hitBlock, hitFace); super(potion, hitEntity, hitBlock, hitFace);
this.entity = entity; this.effectCloud = effectCloud;
} }
@NotNull @NotNull
@Override @Override
public ThrownPotion getEntity() { public ThrownPotion getEntity() {
return (ThrownPotion) super.getEntity(); return (ThrownPotion) this.entity;
} }
/** /**
@ -48,10 +48,9 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca
*/ */
@NotNull @NotNull
public AreaEffectCloud getAreaEffectCloud() { public AreaEffectCloud getAreaEffectCloud() {
return entity; return effectCloud;
} }
// Paper start
/** /**
* Sets if an Empty AreaEffectCloud may be created * Sets if an Empty AreaEffectCloud may be created
* *
@ -69,7 +68,6 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca
public boolean allowsEmptyCreation() { public boolean allowsEmptyCreation() {
return allowEmptyAreaEffectCreation; return allowEmptyAreaEffectCreation;
} }
// Paper end
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {

View File

@ -19,7 +19,9 @@ public class PlayerDeathEvent extends EntityDeathEvent {
private int newExp = 0; private int newExp = 0;
private int newLevel = 0; private int newLevel = 0;
private int newTotalExp = 0; private int newTotalExp = 0;
private boolean showDeathMessages;
private Component deathMessage; private Component deathMessage;
private Component deathScreenMessageOverride = null;
private boolean doExpDrop; private boolean doExpDrop;
private boolean keepLevel = false; private boolean keepLevel = false;
private boolean keepInventory = false; private boolean keepInventory = false;
@ -27,27 +29,28 @@ public class PlayerDeathEvent extends EntityDeathEvent {
private final List<ItemStack> itemsToKeep = new ArrayList<>(); private final List<ItemStack> itemsToKeep = new ArrayList<>();
@ApiStatus.Internal @ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final @Nullable Component deathMessage) { public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final @Nullable Component deathMessage, final boolean showDeathMessages) {
this(player, damageSource, drops, droppedExp, 0, deathMessage); this(player, damageSource, drops, droppedExp, 0, deathMessage, showDeathMessages);
} }
@ApiStatus.Internal @ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final @Nullable Component deathMessage) { public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final @Nullable Component deathMessage, final boolean showDeathMessages) {
this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage); this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage, showDeathMessages);
} }
@ApiStatus.Internal @ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage) { public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean showDeathMessages) {
this(player, damageSource, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, true); this(player, damageSource, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, showDeathMessages, true);
} }
@ApiStatus.Internal @ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean doExpDrop) { public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean showDeathMessages, final boolean doExpDrop) {
super(player, damageSource, drops, droppedExp); super(player, damageSource, drops, droppedExp);
this.newExp = newExp; this.newExp = newExp;
this.newTotalExp = newTotalExp; this.newTotalExp = newTotalExp;
this.newLevel = newLevel; this.newLevel = newLevel;
this.deathMessage = deathMessage; this.deathMessage = deathMessage;
this.showDeathMessages = showDeathMessages;
this.doExpDrop = doExpDrop; this.doExpDrop = doExpDrop;
} }
@ -76,6 +79,7 @@ public class PlayerDeathEvent extends EntityDeathEvent {
this.newExp = newExp; this.newExp = newExp;
this.newTotalExp = newTotalExp; this.newTotalExp = newTotalExp;
this.newLevel = newLevel; this.newLevel = newLevel;
this.showDeathMessages = true;
this.deathMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); this.deathMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage);
this.doExpDrop = doExpDrop; this.doExpDrop = doExpDrop;
} }
@ -86,6 +90,30 @@ public class PlayerDeathEvent extends EntityDeathEvent {
return (Player) this.entity; return (Player) this.entity;
} }
/**
* Get whether the death message should be shown.
* By default, this is determined by {@link org.bukkit.GameRule#SHOW_DEATH_MESSAGES}.
*
* @return whether the death message should be shown
* @see #deathMessage()
* @see #deathScreenMessageOverride()
*/
public boolean getShowDeathMessages() {
return showDeathMessages;
}
/**
* Set whether the death message should be shown.
* By default, this is determined by {@link org.bukkit.GameRule#SHOW_DEATH_MESSAGES}.
*
* @param displayDeathMessage whether the death message should be shown
* @see #deathMessage()
* @see #deathScreenMessageOverride()
*/
public void setShowDeathMessages(boolean displayDeathMessage) {
this.showDeathMessages = displayDeathMessage;
}
/** /**
* Clarity method for getting the player. Not really needed except * Clarity method for getting the player. Not really needed except
* for reasons of clarity. * for reasons of clarity.
@ -177,7 +205,7 @@ public class PlayerDeathEvent extends EntityDeathEvent {
/** /**
* Set the death message that will appear to everyone on the server. * Set the death message that will appear to everyone on the server.
* *
* @param deathMessage Message to appear to other players on the server. * @param deathMessage message to appear to other players on the server.
* @deprecated in favour of {@link #deathMessage(Component)} * @deprecated in favour of {@link #deathMessage(Component)}
*/ */
@Deprecated @Deprecated
@ -197,6 +225,32 @@ public class PlayerDeathEvent extends EntityDeathEvent {
return LegacyComponentSerializer.legacySection().serializeOrNull(this.deathMessage); return LegacyComponentSerializer.legacySection().serializeOrNull(this.deathMessage);
} }
/**
* Overrides the death message that will appear on the death screen of the dying player.
* By default, this is null.
* <p>
* If set to null, death screen message will be same as {@code deathMessage()}.
* <p>
* If the message exceeds 256 characters it will be truncated.
*
* @param deathScreenMessageOverride Message to appear on the death screen to the dying player.
*/
public void deathScreenMessageOverride(@Nullable Component deathScreenMessageOverride) {
this.deathScreenMessageOverride = deathScreenMessageOverride;
}
/**
* Get the death message override that will appear on the death screen of the dying player.
* By default, this is null.
* <p>
* If set to null, death screen message will be same as {@code deathMessage()}.
* <p>
* @return Message to appear on the death screen to the dying player.
*/
public @Nullable Component deathScreenMessageOverride() {
return this.deathScreenMessageOverride;
}
/** /**
* @return should experience be dropped from this death * @return should experience be dropped from this death
*/ */

View File

@ -1,5 +1,6 @@
package org.bukkit.event.player; package org.bukkit.event.player;
import io.papermc.paper.event.entity.FishHookStateChangeEvent;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.FishHook; import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -12,6 +13,8 @@ import org.jetbrains.annotations.Nullable;
/** /**
* Thrown when a player is fishing * Thrown when a player is fishing
*
* <p>If you want to monitor a fishhooks state transition, you can use {@link FishHookStateChangeEvent}.</p>
*/ */
public class PlayerFishEvent extends PlayerEvent implements Cancellable { public class PlayerFishEvent extends PlayerEvent implements Cancellable {

View File

@ -1,6 +1,7 @@
package org.bukkit.event.player; package org.bukkit.event.player;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import io.papermc.paper.event.player.AbstractRespawnEvent;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@ -15,17 +16,10 @@ import java.util.Set;
* If changing player state, see {@link com.destroystokyo.paper.event.player.PlayerPostRespawnEvent} * If changing player state, see {@link com.destroystokyo.paper.event.player.PlayerPostRespawnEvent}
* because the player is "reset" between this event and that event and some changes won't persist. * because the player is "reset" between this event and that event and some changes won't persist.
*/ */
public class PlayerRespawnEvent extends PlayerEvent { public class PlayerRespawnEvent extends AbstractRespawnEvent {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final boolean isBedSpawn;
private final boolean isAnchorSpawn;
private final boolean missingRespawnBlock;
private final RespawnReason respawnReason;
private final Set<RespawnFlag> respawnFlags;
private Location respawnLocation;
@ApiStatus.Internal @ApiStatus.Internal
@Deprecated(since = "1.16.1", forRemoval = true) @Deprecated(since = "1.16.1", forRemoval = true)
public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) {
@ -35,40 +29,16 @@ public class PlayerRespawnEvent extends PlayerEvent {
@ApiStatus.Internal @ApiStatus.Internal
@Deprecated(since = "1.19.4", forRemoval = true) @Deprecated(since = "1.19.4", forRemoval = true)
public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) {
this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, RespawnReason.PLUGIN); this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, false, RespawnReason.PLUGIN);
} }
@ApiStatus.Internal @ApiStatus.Internal
@Deprecated(forRemoval = true) public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, final boolean missingRespawnBlock, @NotNull final RespawnReason respawnReason) {
public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final RespawnReason respawnReason) { super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, missingRespawnBlock, respawnReason);
this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, false, respawnReason, com.google.common.collect.ImmutableSet.builder());
}
@ApiStatus.Internal
public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, final boolean missingRespawnBlock, @NotNull final RespawnReason respawnReason, @NotNull final com.google.common.collect.ImmutableSet.Builder<org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag> respawnFlags) {
super(respawnPlayer);
this.respawnLocation = respawnLocation;
this.isBedSpawn = isBedSpawn;
this.isAnchorSpawn = isAnchorSpawn;
this.respawnReason = respawnReason;
this.missingRespawnBlock = missingRespawnBlock;
if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); }
if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); }
this.respawnFlags = respawnFlags.build();
} }
/** /**
* Gets the current respawn location * Sets the new respawn location.
*
* @return Location current respawn location
*/
@NotNull
public Location getRespawnLocation() {
return this.respawnLocation;
}
/**
* Sets the new respawn location
* *
* @param respawnLocation new location for the respawn * @param respawnLocation new location for the respawn
*/ */
@ -79,57 +49,6 @@ public class PlayerRespawnEvent extends PlayerEvent {
this.respawnLocation = respawnLocation.clone(); this.respawnLocation = respawnLocation.clone();
} }
/**
* Gets whether the respawn location is the player's bed.
*
* @return {@code true} if the respawn location is the player's bed.
*/
public boolean isBedSpawn() {
return this.isBedSpawn;
}
/**
* Gets whether the respawn location is the player's respawn anchor.
*
* @return {@code true} if the respawn location is the player's respawn anchor.
*/
public boolean isAnchorSpawn() {
return this.isAnchorSpawn;
}
/**
* Gets whether the player is missing a valid respawn block.
* <p>
* This will occur if the players respawn block is obstructed,
* or it is the first death after it was either destroyed or
* in case of a respawn anchor, ran out of charges.
*
* @return whether the player is missing a valid respawn block
*/
public boolean isMissingRespawnBlock() {
return this.missingRespawnBlock;
}
/**
* Gets the reason this respawn event was called.
*
* @return the reason the event was called.
*/
@NotNull
public RespawnReason getRespawnReason() {
return this.respawnReason;
}
/**
* Get the set of flags that apply to this respawn.
*
* @return an immutable set of the flags that apply to this respawn
*/
@NotNull
public @Unmodifiable Set<RespawnFlag> getRespawnFlags() {
return this.respawnFlags;
}
@NotNull @NotNull
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers() {

View File

@ -1,5 +1,6 @@
package org.bukkit.event.player; package org.bukkit.event.player;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.entity.TeleportFlag; import io.papermc.paper.entity.TeleportFlag;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -121,10 +122,9 @@ public class PlayerTeleportEvent extends PlayerMoveEvent {
*/ */
END_GATEWAY, END_GATEWAY,
/** /**
* Indicates the teleportation was caused by a player consuming chorus * Indicates the teleportation was caused by a player consuming an item with a {@link ConsumeEffect.TeleportRandomly} effect
* fruit
*/ */
CHORUS_FRUIT, CONSUMABLE_EFFECT,
/** /**
* Indicates the teleportation was caused by a player exiting a vehicle * Indicates the teleportation was caused by a player exiting a vehicle
*/ */
@ -137,6 +137,14 @@ public class PlayerTeleportEvent extends PlayerMoveEvent {
* Indicates the teleportation was caused by an event not covered by * Indicates the teleportation was caused by an event not covered by
* this enum * this enum
*/ */
UNKNOWN UNKNOWN;
/**
* Indicates the teleportation was caused by a player consuming chorus
* fruit
* @deprecated in favor of {@link #CONSUMABLE_EFFECT}
*/
@Deprecated(since = "1.21.5", forRemoval = true)
public static final TeleportCause CHORUS_FRUIT = CONSUMABLE_EFFECT;
} }
} }

View File

@ -87,7 +87,7 @@ public class TabCompleteEvent extends Event implements Cancellable {
/** /**
* Set the completions offered, overriding any already set. * Set the completions offered, overriding any already set.
* <br> * <br>
* The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here * The passed collection will be cloned to a new List. You must call {@link #getCompletions()} to mutate from here
* *
* @param completions the new completions * @param completions the new completions
*/ */

View File

@ -2,6 +2,7 @@ package org.bukkit.inventory;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -321,4 +322,16 @@ public interface InventoryView {
*/ */
@Deprecated(since = "1.21.1") // Paper @Deprecated(since = "1.21.1") // Paper
public void setTitle(@NotNull String title); public void setTitle(@NotNull String title);
/**
* Gets the menu type of the inventory view if applicable.
* <p>
* Some inventory types do not support a menu type. In such cases, this method
* returns null. This typically applies to inventories belonging to entities
* like players or animals (e.g., a horse).
*
* @return the menu type of the inventory view or null if not applicable
*/
@ApiStatus.Experimental
@Nullable MenuType getMenuType();
} }

View File

@ -210,12 +210,12 @@ public interface ItemFactory {
@Deprecated(since = "1.19.3") // Paper @Deprecated(since = "1.19.3") // Paper
ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures); ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures);
// Paper start - Adventure
/** /**
* Creates a hover event for the given item. * Creates a hover event for the given item.
* *
* @param item The item * @param item The item
* @return A hover event * @return A hover event
* @throws IllegalArgumentException if the {@link ItemStack#getAmount()} is not between 1 and 99
*/ */
@NotNull @NotNull
net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op); net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op);
@ -223,12 +223,13 @@ public interface ItemFactory {
/** /**
* Get the formatted display name of the {@link ItemStack}. * Get the formatted display name of the {@link ItemStack}.
* *
* @apiNote this component include a {@link net.kyori.adventure.text.event.HoverEvent item hover event}.
* When used in chat, make sure to follow the ItemStack rules regarding amount, type, and other properties.
* @param itemStack the {@link ItemStack} * @param itemStack the {@link ItemStack}
* @return display name of the {@link ItemStack} * @return display name of the {@link ItemStack}
*/ */
@NotNull @NotNull
net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
// Paper end - Adventure
// Paper start - add getI18NDisplayName // Paper start - add getI18NDisplayName
/** /**

View File

@ -9,6 +9,7 @@ import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@ -706,6 +707,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
return Bukkit.getItemFactory().enchantWithLevels(this, levels, keySet, random); return Bukkit.getItemFactory().enchantWithLevels(this, levels, keySet, random);
} }
/**
* {@inheritDoc}
*
* @param op transformation on value
* @return a hover event
* @throws IllegalArgumentException if the {@link ItemStack#getAmount()} is not between 1 and 99
*/
@NotNull @NotNull
@Override @Override
public net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op) { public net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op) {
@ -715,6 +723,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
/** /**
* Get the formatted display name of the {@link ItemStack}. * Get the formatted display name of the {@link ItemStack}.
* *
* @apiNote this component include a {@link net.kyori.adventure.text.event.HoverEvent item hover event}.
* When used in chat, make sure to follow the ItemStack rules regarding amount, type, and other properties.
* @return display name of the {@link ItemStack} * @return display name of the {@link ItemStack}
*/ */
public net.kyori.adventure.text.@NotNull Component displayName() { public net.kyori.adventure.text.@NotNull Component displayName() {

View File

@ -5,6 +5,9 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.ItemAdventurePredicate;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Tag; import org.bukkit.Tag;
@ -1086,12 +1089,12 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
@NotNull @NotNull
ItemMeta clone(); ItemMeta clone();
// Paper start - Add an API for can-place-on/can-break adventure mode predicates
/** /**
* Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @return Set of materials * @return Set of materials
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_BREAK} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.14") @Deprecated(forRemoval = true, since = "1.14")
Set<org.bukkit.Material> getCanDestroy(); Set<org.bukkit.Material> getCanDestroy();
@ -1100,7 +1103,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @param canDestroy Set of materials * @param canDestroy Set of materials
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_BREAK} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.14") @Deprecated(forRemoval = true, since = "1.14")
void setCanDestroy(Set<org.bukkit.Material> canDestroy); void setCanDestroy(Set<org.bukkit.Material> canDestroy);
@ -1109,7 +1113,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @return Set of materials * @return Set of materials
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.14") @Deprecated(forRemoval = true, since = "1.14")
Set<org.bukkit.Material> getCanPlaceOn(); Set<org.bukkit.Material> getCanPlaceOn();
@ -1118,7 +1123,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @param canPlaceOn Set of materials * @param canPlaceOn Set of materials
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.14") @Deprecated(forRemoval = true, since = "1.14")
void setCanPlaceOn(Set<org.bukkit.Material> canPlaceOn); void setCanPlaceOn(Set<org.bukkit.Material> canPlaceOn);
@ -1127,7 +1133,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @return Set of {@link com.destroystokyo.paper.Namespaced} * @return Set of {@link com.destroystokyo.paper.Namespaced}
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_BREAK} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
@NotNull @NotNull
@ -1137,7 +1144,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced}
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_BREAK} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
void setDestroyableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canDestroy); void setDestroyableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canDestroy);
@ -1146,7 +1154,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @return Set of {@link com.destroystokyo.paper.Namespaced} * @return Set of {@link com.destroystokyo.paper.Namespaced}
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this.
*/ */
@NotNull @NotNull
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
@ -1156,7 +1165,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
* *
* @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced}
* @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
void setPlaceableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canPlaceOn); void setPlaceableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canPlaceOn);
@ -1165,7 +1175,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Checks for the existence of any keys that the item can be placed on * Checks for the existence of any keys that the item can be placed on
* *
* @return true if this item has placeable keys * @return true if this item has placeable keys
* @deprecated this API is unsupported and will be replaced * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#hasData(DataComponentType)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
boolean hasPlaceableKeys(); boolean hasPlaceableKeys();
@ -1174,9 +1185,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Checks for the existence of any keys that the item can destroy * Checks for the existence of any keys that the item can destroy
* *
* @return true if this item has destroyable keys * @return true if this item has destroyable keys
* @deprecated this API is unsupported and will be replaced * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API.
* Please use {@link ItemStack#hasData(DataComponentType)} with {@link DataComponentTypes#CAN_BREAK} instead of this.
*/ */
@Deprecated(forRemoval = true, since = "1.20.6") @Deprecated(forRemoval = true, since = "1.20.6")
boolean hasDestroyableKeys(); boolean hasDestroyableKeys();
// Paper end - Add an API for can-place-on/can-break adventure mode predicates
} }

View File

@ -8,6 +8,7 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
/** /**
* Represents a potion or item that can have custom effects. * Represents a potion or item that can have custom effects.
@ -74,6 +75,16 @@ public interface PotionMeta extends ItemMeta {
@NotNull @NotNull
List<PotionEffect> getCustomEffects(); List<PotionEffect> getCustomEffects();
/**
* All effects that this potion meta holds.
* <p>
* This is a combination of the base potion type and any custom effects.
*
* @return an unmodifiable list of all effects.
*/
@NotNull
@Unmodifiable List<PotionEffect> getAllEffects();
/** /**
* Adds a custom potion effect to this potion. * Adds a custom potion effect to this potion.
* *
@ -146,6 +157,16 @@ public interface PotionMeta extends ItemMeta {
*/ */
void setColor(@Nullable Color color); void setColor(@Nullable Color color);
/**
* Computes the effective colour of this potion meta.
* <p>
* This blends all custom effects, or uses a default fallback color.
*
* @return the effective potion color
*/
@NotNull
Color computeEffectiveColor();
/** /**
* Checks for existence of a custom potion name translation suffix. * Checks for existence of a custom potion name translation suffix.
* *

View File

@ -206,7 +206,16 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
if (result == null) { if (result == null) {
String path = name.replace('.', '/').concat(".class"); String path = name.replace('.', '/').concat(".class");
JarEntry entry = jar.getJarEntry(path); // Add details to zip file errors - help debug classloading
JarEntry entry;
try {
entry = jar.getJarEntry(path);
} catch (IllegalStateException zipFileClosed) {
if (plugin == null) {
throw zipFileClosed;
}
throw new IllegalStateException("The plugin classloader for " + plugin.getName() + " has thrown a zip file error.", zipFileClosed);
}
if (entry != null) { if (entry != null) {
byte[] classBytes; byte[] classBytes;

View File

@ -4,8 +4,12 @@ import io.papermc.generator.utils.ClassHelper;
import io.papermc.paper.datacomponent.DataComponentType; import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.registry.data.BannerPatternRegistryEntry; import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
import io.papermc.paper.registry.data.CatTypeRegistryEntry;
import io.papermc.paper.registry.data.ChickenVariantRegistryEntry;
import io.papermc.paper.registry.data.CowVariantRegistryEntry;
import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.DamageTypeRegistryEntry;
import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
import io.papermc.paper.registry.data.FrogVariantRegistryEntry;
import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry;
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -20,6 +24,8 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import io.papermc.paper.registry.data.PigVariantRegistryEntry;
import io.papermc.paper.registry.data.WolfVariantRegistryEntry;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
@ -161,18 +167,18 @@ public final class RegistryEntries {
entry(Registries.TRIM_MATERIAL, TrimMaterials.class, TrimMaterial.class).allowDirect().delayed(), entry(Registries.TRIM_MATERIAL, TrimMaterials.class, TrimMaterial.class).allowDirect().delayed(),
entry(Registries.TRIM_PATTERN, TrimPatterns.class, TrimPattern.class).allowDirect().delayed(), entry(Registries.TRIM_PATTERN, TrimPatterns.class, TrimPattern.class).allowDirect().delayed(),
entry(Registries.DAMAGE_TYPE, DamageTypes.class, DamageType.class).apiRegistryBuilder(DamageTypeRegistryEntry.Builder.class, "PaperDamageTypeRegistryEntry.PaperBuilder").delayed(), entry(Registries.DAMAGE_TYPE, DamageTypes.class, DamageType.class).apiRegistryBuilder(DamageTypeRegistryEntry.Builder.class, "PaperDamageTypeRegistryEntry.PaperBuilder").delayed(),
entry(Registries.WOLF_VARIANT, WolfVariants.class, Wolf.Variant.class).delayed(), entry(Registries.WOLF_VARIANT, WolfVariants.class, Wolf.Variant.class).apiRegistryBuilder(WolfVariantRegistryEntry.Builder.class, "PaperWolfVariantRegistryEntry.PaperBuilder").delayed(),
entry(Registries.WOLF_SOUND_VARIANT, WolfSoundVariants.class, Wolf.SoundVariant.class), entry(Registries.WOLF_SOUND_VARIANT, WolfSoundVariants.class, Wolf.SoundVariant.class),
entry(Registries.ENCHANTMENT, Enchantments.class, Enchantment.class).apiRegistryBuilder(EnchantmentRegistryEntry.Builder.class, "PaperEnchantmentRegistryEntry.PaperBuilder").serializationUpdater("ENCHANTMENT_RENAME").delayed(), entry(Registries.ENCHANTMENT, Enchantments.class, Enchantment.class).apiRegistryBuilder(EnchantmentRegistryEntry.Builder.class, "PaperEnchantmentRegistryEntry.PaperBuilder").serializationUpdater("ENCHANTMENT_RENAME").delayed(),
entry(Registries.JUKEBOX_SONG, JukeboxSongs.class, JukeboxSong.class).delayed(), entry(Registries.JUKEBOX_SONG, JukeboxSongs.class, JukeboxSong.class).delayed(),
entry(Registries.BANNER_PATTERN, BannerPatterns.class, PatternType.class).allowDirect().apiRegistryBuilder(BannerPatternRegistryEntry.Builder.class, "PaperBannerPatternRegistryEntry.PaperBuilder").delayed(), entry(Registries.BANNER_PATTERN, BannerPatterns.class, PatternType.class).allowDirect().apiRegistryBuilder(BannerPatternRegistryEntry.Builder.class, "PaperBannerPatternRegistryEntry.PaperBuilder").delayed(),
entry(Registries.PAINTING_VARIANT, PaintingVariants.class, Art.class).allowDirect().apiRegistryBuilder(PaintingVariantRegistryEntry.Builder.class, "PaperPaintingVariantRegistryEntry.PaperBuilder").apiRegistryField("ART").delayed(), entry(Registries.PAINTING_VARIANT, PaintingVariants.class, Art.class).allowDirect().apiRegistryBuilder(PaintingVariantRegistryEntry.Builder.class, "PaperPaintingVariantRegistryEntry.PaperBuilder").apiRegistryField("ART").delayed(),
entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().delayed(), entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().delayed(),
entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).delayed(), entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).apiRegistryBuilder(CatTypeRegistryEntry.Builder.class, "PaperCatTypeRegistryEntry.PaperBuilder").delayed(),
entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).delayed(), entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).apiRegistryBuilder(FrogVariantRegistryEntry.Builder.class, "PaperFrogVariantRegistryEntry.PaperBuilder").delayed(),
entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class), entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class).apiRegistryBuilder(ChickenVariantRegistryEntry.Builder.class, "PaperChickenVariantRegistryEntry.PaperBuilder"),
entry(Registries.COW_VARIANT, CowVariants.class, Cow.Variant.class), entry(Registries.COW_VARIANT, CowVariants.class, Cow.Variant.class).apiRegistryBuilder(CowVariantRegistryEntry.Builder.class, "PaperCowVariantRegistryEntry.PaperBuilder"),
entry(Registries.PIG_VARIANT, PigVariants.class, Pig.Variant.class) entry(Registries.PIG_VARIANT, PigVariants.class, Pig.Variant.class).apiRegistryBuilder(PigVariantRegistryEntry.Builder.class, "PaperPigVariantRegistryEntry.PaperBuilder")
); );
public static final List<RegistryEntry<?>> API_ONLY = List.of( public static final List<RegistryEntry<?>> API_ONLY = List.of(

View File

@ -15,7 +15,7 @@ plugins {
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies { dependencies {
mache("io.papermc:mache:1.21.5+build.1") mache("io.papermc:mache:1.21.5+build.2")
paperclip("io.papermc:paperclip:3.0.3") paperclip("io.papermc:paperclip:3.0.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.platform:junit-platform-launcher")
} }
@ -135,7 +135,7 @@ dependencies {
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ 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("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
implementation("net.minecrell:terminalconsoleappender:1.3.0") implementation("net.minecrell:terminalconsoleappender:1.3.0")
implementation("io.papermc.adventure:adventure-text-serializer-ansi:4.21.0-mc1215-SNAPSHOT") // Keep in sync with adventureVersion from Paper-API build file // FIXME back to release implementation("net.kyori:adventure-text-serializer-ansi:4.21.0") // Keep in sync with adventureVersion from Paper-API build file
runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath }) runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath })
/* /*

View File

@ -143,7 +143,7 @@ index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) { private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b..fe9b4484d683fe48f435a053c9c90557fdf80e7b 100644 index 6b67cc939851745718f919488c997eb6719a16fc..085040aa98704f2874bcd95b751b0a81dcdb15ad 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -343,7 +343,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -343,7 +343,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@ -186,7 +186,7 @@ index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent(); new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49426b581c 100644 index 9b2ee3e16e2c443e8ff03faec59dd55d729e9274..5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8 100644
--- a/net/minecraft/server/players/PlayerList.java --- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java
@@ -407,7 +407,7 @@ public abstract class PlayerList { @@ -407,7 +407,7 @@ public abstract class PlayerList {
@ -199,7 +199,7 @@ index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49
} }
// Paper end - Send empty chunk // Paper end - Send empty chunk
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd751911198 100644 index 1bb40f18b671d63719d96a58ff283767c2cfe383..ba50f21707a69bbf720345996d7c83d2064e5246 100644
--- a/net/minecraft/world/level/Level.java --- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java
@@ -132,6 +132,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl @@ -132,6 +132,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@ -209,10 +209,10 @@ index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd7
+ public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
private final CraftWorld world; private final CraftWorld world;
public boolean pvpMode; public boolean pvpMode;
public org.bukkit.generator.ChunkGenerator generator; public @Nullable org.bukkit.generator.ChunkGenerator generator;
@@ -201,7 +202,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl @@ -201,7 +202,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit @Nullable org.bukkit.generator.BiomeProvider biomeProvider, // Paper
org.bukkit.World.Environment env, // CraftBukkit org.bukkit.World.Environment environment, // Paper
java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
- io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config - io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config
+ io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, // Paper - create paper world config + io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, // Paper - create paper world config

View File

@ -3874,10 +3874,10 @@ index 0000000000000000000000000000000000000000..1c82dcd38f789707e15e8cbec72ef9cd
+} +}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd78645bbf index 0000000000000000000000000000000000000000..2d24d03bbdb5ee0d862cbfff2219f58afffafe12
--- /dev/null --- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
@@ -0,0 +1,1002 @@ @@ -0,0 +1,1006 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.level.entity; +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity;
+ +
+import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; +import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
@ -4059,6 +4059,10 @@ index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd
+ } + }
+ } + }
+ +
+ public Iterable<Entity> getAllMapped() {
+ return this.entityByUUID.values();
+ }
+
+ public int getEntityCount() { + public int getEntityCount() {
+ synchronized (this.accessibleEntities) { + synchronized (this.accessibleEntities) {
+ return this.accessibleEntities.size(); + return this.accessibleEntities.size();
@ -26798,7 +26802,7 @@ index c50a1a01d167696134bd65b2d28db323d81d6ebd..5d63bf024cbcbd2f627c64fee77553c9
} }
} }
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be98445150487982 100644 index 69fbcd734c269bbc9858b0ad0b3b268ddb81fcc6..a1ae77b70f69852d9e4332bf1cb3409c33b21de0 100644
--- a/net/minecraft/server/level/ServerEntity.java --- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java
@@ -104,6 +104,11 @@ public class ServerEntity { @@ -104,6 +104,11 @@ public class ServerEntity {
@ -26814,7 +26818,7 @@ index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be984451
if (!passengers.equals(this.lastPassengers)) { if (!passengers.equals(this.lastPassengers)) {
List<UUID> list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList(); List<UUID> list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee 100644 index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8813846a6 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -166,7 +166,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @@ -166,7 +166,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
@ -27565,10 +27569,10 @@ index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc
} }
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989acb11c638 100644 index 57af8cd7629fa14176c6e7a29956617ec9506999..63fecebe6048b0d3372ea84ac74dc74744de3273 100644
--- a/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -187,7 +187,7 @@ import net.minecraft.world.scores.Team; @@ -186,7 +186,7 @@ import net.minecraft.world.scores.Team;
import net.minecraft.world.scores.criteria.ObjectiveCriteria; import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -27577,7 +27581,7 @@ index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989a
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
@@ -423,6 +423,36 @@ public class ServerPlayer extends Player { @@ -415,6 +415,36 @@ public class ServerPlayer extends Player {
public @Nullable String clientBrandName = null; // Paper - Brand support public @Nullable String clientBrandName = null; // Paper - Brand support
public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
@ -28202,10 +28206,10 @@ index b30f56fbc1fd17259a1d05dc9155fffcab292ca1..11fed81a4696ba18440e755c3b8a5ca3
this.generatingStep = generatingStep; this.generatingStep = generatingStep;
this.cache = cache; this.cache = cache;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412eaba69af1 100644 index eda176c96bcf3d67650722ffce33863edfbdea9e..a7a07ebe6ceed99fa768b6834e350fe2f51a6950 100644
--- a/net/minecraft/server/players/PlayerList.java --- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java
@@ -1320,7 +1320,7 @@ public abstract class PlayerList { @@ -1332,7 +1332,7 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) { public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance; this.viewDistance = viewDistance;
@ -28214,7 +28218,7 @@ index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412e
for (ServerLevel serverLevel : this.server.getAllLevels()) { for (ServerLevel serverLevel : this.server.getAllLevels()) {
if (serverLevel != null) { if (serverLevel != null) {
@@ -1331,7 +1331,7 @@ public abstract class PlayerList { @@ -1343,7 +1343,7 @@ public abstract class PlayerList {
public void setSimulationDistance(int simulationDistance) { public void setSimulationDistance(int simulationDistance) {
this.simulationDistance = simulationDistance; this.simulationDistance = simulationDistance;
@ -28597,7 +28601,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting + // Paper end - block counting
} }
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e36b7294f 100644 index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be231609182970 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder;
@ -28950,7 +28954,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
} }
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) { private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2599,21 +2747,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -2616,21 +2764,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public boolean isInWall() { public boolean isInWall() {
@ -29072,7 +29076,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
} }
public InteractionResult interact(Player player, InteractionHand hand) { public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4061,15 +4298,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4078,15 +4315,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public Iterable<Entity> getIndirectPassengers() { public Iterable<Entity> getIndirectPassengers() {
@ -29098,7 +29102,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
} }
public int countPlayerPassengers() { public int countPlayerPassengers() {
@@ -4212,77 +4451,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4229,77 +4468,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(partialTick, this.yRotO, this.yRot); return Mth.lerp(partialTick, this.yRotO, this.yRot);
} }
@ -29289,7 +29293,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
public boolean touchingUnloadedChunk() { public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0); AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4437,6 +4735,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4454,6 +4752,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@ -29305,7 +29309,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
if (!checkPosition(this, x, y, z)) { if (!checkPosition(this, x, y, z)) {
return; return;
} }
@@ -4570,6 +4877,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4587,6 +4894,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override @Override
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
@ -29318,7 +29322,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) { if (this.removalReason == null) {
@@ -4580,7 +4893,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4597,7 +4910,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding(); this.stopRiding();
} }
@ -29327,7 +29331,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
this.levelCallback.onRemove(removalReason); this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason); this.onRemoval(removalReason);
// Paper start - Folia schedulers // Paper start - Folia schedulers
@@ -4614,7 +4927,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4631,7 +4944,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean shouldBeSaved() { public boolean shouldBeSaved() {
return (this.removalReason == null || this.removalReason.shouldSave()) return (this.removalReason == null || this.removalReason.shouldSave())
&& !this.isPassenger() && !this.isPassenger()
@ -29576,7 +29580,7 @@ index b766b4281aecb3b96e2c263664d81da3425e3653..c3bcb494afe464207e805f8c40b03c70
this(setDirty, true, ImmutableList.of()); this(setDirty, true, ImmutableList.of());
} }
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java
index 75bf15ccd8a12153951f886ed87be9f3bece3133..6f601a0a300bbf01f77d835576d15e25c8ba10b8 100644 index f5ce8151bb1bae9be638ced7f74899d452d517e1..5248f3c22abb608d7d7b338f169f13bfbf4cd2d6 100644
--- a/net/minecraft/world/entity/decoration/ArmorStand.java --- a/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -245,7 +245,7 @@ public class ArmorStand extends LivingEntity { @@ -245,7 +245,7 @@ public class ArmorStand extends LivingEntity {
@ -29725,7 +29729,7 @@ index 300f3ed58109219d97846082941b860585f66fed..892a7c1eb1b321ca6d5ca709142e7fea
// Paper start - Affects Spawning API // Paper start - Affects Spawning API
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d5be9e876 100644 index ba50f21707a69bbf720345996d7c83d2064e5246..e9751a95ffd88f365185d53f8764291d9d2473e2 100644
--- a/net/minecraft/world/level/Level.java --- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java
@@ -81,6 +81,7 @@ import net.minecraft.world.level.storage.LevelData; @@ -81,6 +81,7 @@ import net.minecraft.world.level.storage.LevelData;
@ -30399,7 +30403,7 @@ index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d
+ // Paper end - getblock optimisations - cache world height/sections + // Paper end - getblock optimisations - cache world height/sections
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
this.generator = gen; this.generator = generator;
@@ -281,6 +914,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl @@ -281,6 +914,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
}); });
// CraftBukkit end // CraftBukkit end

View File

@ -50,7 +50,7 @@ index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921d
ProfilerFiller profilerFiller = Profiler.get(); ProfilerFiller profilerFiller = Profiler.get();
this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings) this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c188547e04bd1 100644 index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..bfbfbaa9660d21071c420b60b10be0a02a1bc87e 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@ -64,7 +64,7 @@ index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c1885
+ } + }
+ +
+ if (doFull) { + if (doFull) {
+ this.saveLevelData(true); + this.saveLevelData(false);
+ } + }
+ // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads) + // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads)
+ // Copied from save() + // Copied from save()
@ -83,10 +83,10 @@ index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c1885
// Paper start - add close param // Paper start - add close param
this.save(progress, flush, skipSave, false); this.save(progress, flush, skipSave, false);
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e80ec50dc 100644 index 5a60f2598560571e156612bf256c1c340d92a922..57e7d0a8b5f2a5bc65b0f290fb655625b1481f31 100644
--- a/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -189,6 +189,7 @@ import org.slf4j.Logger; @@ -188,6 +188,7 @@ import org.slf4j.Logger;
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
@ -95,7 +95,7 @@ index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25; private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba95788bb18 100644 index a7a07ebe6ceed99fa768b6834e350fe2f51a6950..9ca3c55a3b5b1a532b86b08eb92460df4cb54f2a 100644
--- a/net/minecraft/server/players/PlayerList.java --- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java
@@ -486,6 +486,7 @@ public abstract class PlayerList { @@ -486,6 +486,7 @@ public abstract class PlayerList {
@ -106,7 +106,7 @@ index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba9
this.playerIo.save(player); this.playerIo.save(player);
ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) { if (serverStatsCounter != null) {
@@ -1067,9 +1068,23 @@ public abstract class PlayerList { @@ -1079,9 +1080,23 @@ public abstract class PlayerList {
} }
public void saveAll() { public void saveAll() {

View File

@ -78,10 +78,10 @@ index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378ec
profiler.popPush("tickSpawningChunks"); profiler.popPush("tickSpawningChunks");
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0..73a450e045eba5dbfc7a4e861e4c614c8f60d6b4 100644 index 4b2801749328f250ce5735fbe7f6941a6bede01a..af04fcdba1e57b4eac678235b56ad3e1c70169b7 100644
--- a/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -403,6 +403,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -395,6 +395,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public boolean queueHealthUpdatePacket; public boolean queueHealthUpdatePacket;
public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end - cancellable death event // Paper end - cancellable death event

View File

@ -60,10 +60,10 @@ index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d7
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
} else { } else {
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171f73b3d07 100644 index af04fcdba1e57b4eac678235b56ad3e1c70169b7..3781d9cc174b7aecacb9b9855d52c7b1ff05835c 100644
--- a/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -407,6 +407,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -399,6 +399,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
// Paper end - Optional per player mob spawns // Paper end - Optional per player mob spawns
@ -72,7 +72,7 @@ index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171
public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection; public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection;
public String displayName; public String displayName;
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 17b13baa3465530b11ff918c806c772eb5c39a2c..afd6da5c361e1dcf311a9afe8a7efe2faef2556a 100644 index c710e08ab48075ce7854e56826adb8f0364b025b..14a2514a408a66a83f7b5fb43b4c4dc8f23fd5f4 100644
--- a/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -279,6 +279,11 @@ public final class NaturalSpawner { @@ -279,6 +279,11 @@ public final class NaturalSpawner {

View File

@ -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 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 diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062b48d43fa 100644 index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl @@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl
@ -88,7 +88,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
} }
@Override @Override
@@ -1430,7 +1462,7 @@ public class ServerGamePacketListenerImpl @@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl
} }
} }
@ -97,7 +97,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -1469,6 +1501,7 @@ public class ServerGamePacketListenerImpl @@ -1471,6 +1503,7 @@ public class ServerGamePacketListenerImpl
boolean flag1 = this.player.verticalCollisionBelow; boolean flag1 = this.player.verticalCollisionBelow;
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
@ -105,7 +105,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
// Paper start - prevent position desync // Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) { if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions. return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1501,7 +1534,17 @@ public class ServerGamePacketListenerImpl @@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl
} }
// Paper start - Add fail move event // Paper start - Add fail move event
@ -124,7 +124,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
if (teleportBack) { if (teleportBack) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false); toX, toY, toZ, toYaw, toPitch, false);
@@ -1638,7 +1681,7 @@ public class ServerGamePacketListenerImpl @@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl
private boolean updateAwaitingTeleport() { private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) { if (this.awaitingPositionFromClient != null) {
@ -133,7 +133,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
this.awaitingTeleportTime = this.tickCount; this.awaitingTeleportTime = this.tickCount;
this.teleport( this.teleport(
this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.x,
@@ -1657,6 +1700,33 @@ public class ServerGamePacketListenerImpl @@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl
} }
} }

View File

@ -13,7 +13,7 @@
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API + public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API + public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API + public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API
+ public io.papermc.paper.command.brigadier.PluginCommandMeta pluginCommandMeta; // Paper - Brigadier Command API + public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API
+ // CraftBukkit start + // CraftBukkit start
+ public void removeCommand(String name) { + public void removeCommand(String name) {
+ this.children.remove(name); + this.children.remove(name);

View File

@ -172,7 +172,7 @@
} }
return null; return null;
@@ -359,26 +_,120 @@ @@ -359,26 +_,121 @@
} }
public void sendCommands(ServerPlayer player) { public void sendCommands(ServerPlayer player) {
@ -252,6 +252,7 @@
+ } + }
+ // Paper end - Brigadier API + // Paper end - Brigadier API
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot + if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot
+ if (commandNode.wrappedCached != null && commandNode.wrappedCached.apiCommandMeta != null && commandNode.wrappedCached.apiCommandMeta.serverSideOnly()) continue; // Paper
if (commandNode.canUse(source)) { if (commandNode.canUse(source)) {
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder(); ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
+ // Paper start + // Paper start

View File

@ -0,0 +1,10 @@
--- a/net/minecraft/core/ClientAsset.java
+++ b/net/minecraft/core/ClientAsset.java
@@ -12,6 +_,6 @@
public static final StreamCodec<ByteBuf, ClientAsset> STREAM_CODEC = StreamCodec.composite(ResourceLocation.STREAM_CODEC, ClientAsset::id, ClientAsset::new);
public ClientAsset(ResourceLocation id) {
- this(id, id.withPath(string -> "textures/" + string + ".png"));
+ this(id, id.withPath(string -> "textures/" + string + ".png")); // Paper - diff on change - io.papermc.paper.registry.data.client.ClientAssetImpl#pathFromIdentifier
}
}

View File

@ -1,33 +0,0 @@
--- a/net/minecraft/network/HashedStack.java
+++ b/net/minecraft/network/HashedStack.java
@@ -17,7 +_,7 @@
}
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return stack.isEmpty();
}
};
@@ -27,7 +_,7 @@
hashedStack -> hashedStack instanceof HashedStack.ActualItem actualItem ? Optional.of(actualItem) : Optional.empty()
);
- boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator);
+ boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching); // Paper - add flag to simplify remote matching logic
static HashedStack create(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
return (HashedStack)(stack.isEmpty()
@@ -47,10 +_,10 @@
);
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return this.count == stack.getCount()
&& this.item.equals(stack.getItemHolder())
- && this.components.matches(stack.getComponentsPatch(), hashGenerator);
+ && (simplifyMatching || this.components.matches(stack.getComponentsPatch(), hashGenerator)); // Paper - add flag to simplify remote matching logic
}
}
}

View File

@ -0,0 +1,31 @@
--- a/net/minecraft/network/syncher/EntityDataSerializers.java
+++ b/net/minecraft/network/syncher/EntityDataSerializers.java
@@ -51,10 +_,27 @@
public static final EntityDataSerializer<Optional<Component>> OPTIONAL_COMPONENT = EntityDataSerializer.forValueType(
ComponentSerialization.TRUSTED_OPTIONAL_STREAM_CODEC
);
+ // Paper start - do not obfuscate items sent as entity data
+ public static final StreamCodec<RegistryFriendlyByteBuf, ItemStack> OVERSIZED_ITEM_CODEC = new net.minecraft.network.codec.StreamCodec<>() {
+ @Override
+ public net.minecraft.world.item.ItemStack decode(final net.minecraft.network.RegistryFriendlyByteBuf buffer) {
+ return ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
+ }
+
+ @Override
+ public void encode(final net.minecraft.network.RegistryFriendlyByteBuf buffer, final net.minecraft.world.item.ItemStack value) {
+ // If the codec is called during an obfuscation session, downgrade the context's obf level to OVERSIZED if it isn't already.
+ // Entity data cannot be fully obfuscated as entities might render out specific values (e.g. count or custom name).
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.level(io.papermc.paper.util.sanitizer.ItemObfuscationSession.ObfuscationLevel.OVERSIZED))) {
+ ItemStack.OPTIONAL_STREAM_CODEC.encode(buffer, value);
+ }
+ }
+ };
+ // Paper end - do not obfuscate items sent as entity data
public static final EntityDataSerializer<ItemStack> ITEM_STACK = new EntityDataSerializer<ItemStack>() {
@Override
public StreamCodec<? super RegistryFriendlyByteBuf, ItemStack> codec() {
- return ItemStack.OPTIONAL_STREAM_CODEC;
+ return OVERSIZED_ITEM_CODEC; // Paper - do not obfuscate items sent as entity data
}
@Override

View File

@ -1,12 +1,13 @@
--- a/net/minecraft/server/ReloadableServerResources.java --- a/net/minecraft/server/ReloadableServerResources.java
+++ b/net/minecraft/server/ReloadableServerResources.java +++ b/net/minecraft/server/ReloadableServerResources.java
@@ -38,7 +_,8 @@ @@ -38,7 +_,9 @@
this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess()); this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess());
this.postponedTags = postponedTags; this.postponedTags = postponedTags;
this.recipes = new RecipeManager(registries); this.recipes = new RecipeManager(registries);
- this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures)); - this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures));
+ this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration + this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API
+ io.papermc.paper.command.PaperCommands.registerCommands(); // Paper
this.advancements = new ServerAdvancementManager(registries); this.advancements = new ServerAdvancementManager(registries);
this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher()); this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher());
} }

View File

@ -1,5 +1,13 @@
--- a/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -65,7 +_,6 @@
import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket;
import net.minecraft.network.protocol.game.ClientboundMerchantOffersPacket;
import net.minecraft.network.protocol.game.ClientboundOpenBookPacket;
-import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerCombatEndPacket;
@@ -235,7 +_,8 @@ @@ -235,7 +_,8 @@
private int levitationStartTime; private int levitationStartTime;
private boolean disconnected; private boolean disconnected;
@ -10,7 +18,7 @@
@Nullable @Nullable
private Vec3 startingToFallPosition; private Vec3 startingToFallPosition;
@Nullable @Nullable
@@ -281,6 +_,20 @@ @@ -281,6 +_,13 @@
} }
} }
@ -20,26 +28,10 @@
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy())); + ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ } + }
+ // Paper end - Sync offhand slot in menus + // Paper end - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ @Override
+ public ServerPlayer player() {
+ return ServerPlayer.this;
+ }
+ // Paper end - add flag to simplify remote matching logic
+ +
@Override @Override
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) { public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack)); ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack));
@@ -302,7 +_,7 @@
@Override
public RemoteSlot createSlot() {
- return new RemoteSlot.Synchronized(this.cache::getUnchecked);
+ return new RemoteSlot.Synchronized(this.cache::getUnchecked, ServerPlayer.this.getBukkitEntity().simplifyContainerDesyncCheck()); // Paper - add flag to simplify remote matching logic
}
};
private final ContainerListener containerListener = new ContainerListener() {
@@ -316,6 +_,32 @@ @@ -316,6 +_,32 @@
} }
} }
@ -316,12 +308,19 @@
} }
float saturationLevel = this.foodData.getSaturationLevel(); float saturationLevel = this.foodData.getSaturationLevel();
@@ -793,15 +_,84 @@ @@ -793,15 +_,36 @@
} }
private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) {
- this.getScoreboard().forAllObjectives(criteria, this, score -> score.set(points)); - this.getScoreboard().forAllObjectives(criteria, this, score -> score.set(points));
- } - }
-
- @Override
- public void die(DamageSource cause) {
- this.gameEvent(GameEvent.ENTITY_DIE);
- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
- if (_boolean) {
- Component deathMessage = this.getCombatTracker().getDeathMessage();
+ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, score -> score.set(points)); // CraftBukkit - Use our scores instead + this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, score -> score.set(points)); // CraftBukkit - Use our scores instead
+ } + }
+ +
@ -348,13 +347,24 @@
+ return false; + return false;
+ } + }
+ // Paper end - PlayerDeathEvent#getItemsToKeep + // Paper end - PlayerDeathEvent#getItemsToKeep
+ // Paper start - Expand PlayerDeathEvent API
@Override + private void sendClientboundPlayerCombatKillPacket(boolean displayMessage, Component deathMessage) {
public void die(DamageSource cause) { + if (displayMessage && deathMessage != CommonComponents.EMPTY) {
- this.gameEvent(GameEvent.ENTITY_DIE); + // Paper - moved from below die(DamageSource) method
- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); this.connection
- if (_boolean) { .send(
- Component deathMessage = this.getCombatTracker().getDeathMessage(); new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage),
@@ -818,6 +_,65 @@
}
)
);
+ } else {
+ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY));
+ }
+ }
+ // Paper end - Expand PlayerDeathEvent API
+ @Override
+ public void die(DamageSource cause) {
+ // this.gameEvent(GameEvent.ENTITY_DIE); // Paper - move below event cancellation check + // this.gameEvent(GameEvent.ENTITY_DIE); // Paper - move below event cancellation check
+ boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); final boolean showDeathMessage = _boolean; // Paper - OBFHELPER + boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); final boolean showDeathMessage = _boolean; // Paper - OBFHELPER
+ // CraftBukkit start - fire PlayerDeathEvent + // CraftBukkit start - fire PlayerDeathEvent
@ -382,7 +392,7 @@
+ +
+ String deathmessage = defaultMessage.getString(); + String deathmessage = defaultMessage.getString();
+ this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel + this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel
+ org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), keepInventory); // Paper - Adventure + org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), showDeathMessage, keepInventory); // Paper - Adventure; Expand PlayerDeathEvent API
+ // Paper start - cancellable death event + // Paper start - cancellable death event
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ // make compatible with plugins that might have already set the health in an event listener + // make compatible with plugins that might have already set the health in an event listener
@ -400,13 +410,25 @@
+ } + }
+ +
+ net.kyori.adventure.text.Component apiDeathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure + net.kyori.adventure.text.Component apiDeathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure
+ Component deathScreenMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.deathScreenMessageOverride() != null ? event.deathScreenMessageOverride() : apiDeathMessage); // Paper - Expand PlayerDeathEvent API
+ +
+ if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && showDeathMessage) { // Paper - Adventure // TODO: allow plugins to override? + if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && event.getShowDeathMessages()) { // Paper - Adventure; Expand PlayerDeathEvent API
+ Component deathMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(apiDeathMessage); // Paper - Adventure + Component deathMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(apiDeathMessage); // Paper - Adventure
+ +
this.connection + // Paper - moved up to sendClientboundPlayerCombatKillPacket()
.send( + sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent
new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage), Team team = this.getTeam();
if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) {
this.server.getPlayerList().broadcastSystemMessage(deathMessage, false);
@@ -827,7 +_,7 @@
this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage);
}
} else {
- this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY));
+ sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent
}
this.removeEntitiesOnShoulder();
@@ -835,11 +_,35 @@ @@ -835,11 +_,35 @@
this.tellNeutralMobsThatIDied(); this.tellNeutralMobsThatIDied();
} }
@ -491,7 +513,7 @@
} }
} }
@@ -914,23 +_,82 @@ @@ -914,23 +_,77 @@
} }
private boolean isPvpAllowed() { private boolean isPvpAllowed() {
@ -541,18 +563,13 @@
+ ); + );
+ +
+ // Paper start - respawn flags + // Paper start - respawn flags
+ com.google.common.collect.ImmutableSet.Builder<org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag> builder = com.google.common.collect.ImmutableSet.builder();
+ if (respawnReason == org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.END_PORTAL) {
+ builder.add(org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL);
+ }
+ org.bukkit.event.player.PlayerRespawnEvent respawnEvent = new org.bukkit.event.player.PlayerRespawnEvent( + org.bukkit.event.player.PlayerRespawnEvent respawnEvent = new org.bukkit.event.player.PlayerRespawnEvent(
+ respawnPlayer, + respawnPlayer,
+ location, + location,
+ isBedSpawn, + isBedSpawn,
+ isAnchorSpawn, + isAnchorSpawn,
+ teleportTransition.missingRespawnBlock(), + teleportTransition.missingRespawnBlock(),
+ respawnReason, + respawnReason
+ builder
+ ); + );
+ // Paper end - respawn flags + // Paper end - respawn flags
+ this.level().getCraftServer().getPluginManager().callEvent(respawnEvent); + this.level().getCraftServer().getPluginManager().callEvent(respawnEvent);

View File

@ -523,7 +523,7 @@
this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); this.player.sendSystemMessage(Component.translatable("advMode.notAllowed"));
} else { } else {
BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level()); BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level());
@@ -661,7 +_,7 @@ @@ -661,11 +_,11 @@
boolean flag = this.player.hasInfiniteMaterials() && packet.includeData(); boolean flag = this.player.hasInfiniteMaterials() && packet.includeData();
ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag); ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag);
if (!cloneItemStack.isEmpty()) { if (!cloneItemStack.isEmpty()) {
@ -532,7 +532,23 @@
addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack); addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack);
} }
@@ -698,18 +_,29 @@ - this.tryPickItem(cloneItemStack);
+ this.tryPickItem(cloneItemStack, blockPos, null, packet.includeData()); // Paper - Extend PlayerPickItemEvent API
}
}
}
@@ -689,27 +_,40 @@
if (entityOrPart != null && this.player.canInteractWithEntity(entityOrPart, 3.0)) {
ItemStack pickResult = entityOrPart.getPickResult();
if (pickResult != null && !pickResult.isEmpty()) {
- this.tryPickItem(pickResult);
+ this.tryPickItem(pickResult, null, entityOrPart, packet.includeData()); // Paper - Extend PlayerPickItemEvent API
}
}
}
- private void tryPickItem(ItemStack stack) {
+ private void tryPickItem(ItemStack stack, @Nullable BlockPos blockPos, @Nullable Entity entity, boolean includeData) { // Paper - Extend PlayerPickItemEvent API
if (stack.isItemEnabled(this.player.level().enabledFeatures())) { if (stack.isItemEnabled(this.player.level().enabledFeatures())) {
Inventory inventory = this.player.getInventory(); Inventory inventory = this.player.getInventory();
int i = inventory.findSlotMatchingItem(stack); int i = inventory.findSlotMatchingItem(stack);
@ -540,7 +556,9 @@
+ final int sourceSlot = i; + final int sourceSlot = i;
+ final int targetSlot = Inventory.isHotbarSlot(sourceSlot) ? sourceSlot : inventory.getSuitableHotbarSlot(); + final int targetSlot = Inventory.isHotbarSlot(sourceSlot) ? sourceSlot : inventory.getSuitableHotbarSlot();
+ final org.bukkit.entity.Player bukkitPlayer = this.player.getBukkitEntity(); + final org.bukkit.entity.Player bukkitPlayer = this.player.getBukkitEntity();
+ final io.papermc.paper.event.player.PlayerPickItemEvent event = new io.papermc.paper.event.player.PlayerPickItemEvent(bukkitPlayer, targetSlot, sourceSlot); + final io.papermc.paper.event.player.PlayerPickItemEvent event = entity != null
+ ? new io.papermc.paper.event.player.PlayerPickEntityEvent(bukkitPlayer, entity.getBukkitEntity(), includeData, targetSlot, sourceSlot)
+ : new io.papermc.paper.event.player.PlayerPickBlockEvent(bukkitPlayer, org.bukkit.craftbukkit.block.CraftBlock.at(this.player.level(), blockPos), includeData, targetSlot, sourceSlot);
+ if (!event.callEvent()) { + if (!event.callEvent()) {
+ return; + return;
+ } + }
@ -2468,7 +2486,7 @@
} else if (flag && flag2) { } else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) { if (this.dropSpamThrottler.isUnderThreshold()) {
this.dropSpamThrottler.increment(); this.dropSpamThrottler.increment();
@@ -1895,11 +_,24 @@ @@ -1895,15 +_,38 @@
@Override @Override
public void handleSignUpdate(ServerboundSignUpdatePacket packet) { public void handleSignUpdate(ServerboundSignUpdatePacket packet) {
@ -2494,6 +2512,20 @@
this.player.resetLastActionTime(); this.player.resetLastActionTime();
ServerLevel serverLevel = this.player.serverLevel(); ServerLevel serverLevel = this.player.serverLevel();
BlockPos pos = packet.getPos(); BlockPos pos = packet.getPos();
if (serverLevel.hasChunkAt(pos)) {
+ // Paper start - Add API for client-side signs
+ if (!new io.papermc.paper.event.packet.UncheckedSignChangeEvent(
+ this.player.getBukkitEntity(),
+ io.papermc.paper.util.MCUtil.toPosition(pos),
+ packet.isFrontText() ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ filteredText.stream().<net.kyori.adventure.text.Component>map(line -> net.kyori.adventure.text.Component.text(line.raw())).toList())
+ .callEvent()) {
+ return;
+ }
+ // Paper end - Add API for client-side signs
if (!(serverLevel.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity)) {
return;
}
@@ -1915,14 +_,32 @@ @@ -1915,14 +_,32 @@
@Override @Override
public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) {

View File

@ -9,10 +9,10 @@
+ static final java.util.regex.Pattern HOST_PATTERN = java.util.regex.Pattern.compile("[0-9a-f\\.:]{0,45}"); + static final java.util.regex.Pattern HOST_PATTERN = java.util.regex.Pattern.compile("[0-9a-f\\.:]{0,45}");
+ static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}"); + static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}");
+ // Spigot end + // Spigot end
+ // CraftBukkit start - add fields + // Paper start - Connection throttle
+ private static final java.util.HashMap<java.net.InetAddress, Long> throttleTracker = new java.util.HashMap<>(); + private static final java.util.Map<java.net.InetAddress, Long> throttleTracker = new java.util.HashMap<>();
+ private static int throttleCounter = 0; + private static int throttleCounter = 0;
+ // CraftBukkit end + // Paper end - Connection throttle
+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper + private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper
private final MinecraftServer server; private final MinecraftServer server;
private final Connection connection; private final Connection connection;
@ -29,7 +29,7 @@
switch (packet.intention()) { switch (packet.intention()) {
case LOGIN: case LOGIN:
this.beginLogin(packet, false); this.beginLogin(packet, false);
@@ -50,22 +_,117 @@ @@ -50,22 +_,118 @@
default: default:
throw new UnsupportedOperationException("Invalid intention " + packet.intention()); throw new UnsupportedOperationException("Invalid intention " + packet.intention());
} }
@ -42,17 +42,18 @@
private void beginLogin(ClientIntentionPacket packet, boolean transferred) { private void beginLogin(ClientIntentionPacket packet, boolean transferred) {
this.connection.setupOutboundProtocol(LoginProtocols.CLIENTBOUND); this.connection.setupOutboundProtocol(LoginProtocols.CLIENTBOUND);
+ // CraftBukkit start - Connection throttle + // Paper start - Connection throttle
+ try { + try {
+ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket + final long connectionThrottle = this.server.server.getConnectionThrottle();
+ final boolean isUnixDomainSocket = this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress; // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket
+ if (connectionThrottle > 0 && !isUnixDomainSocket && this.connection.getRemoteAddress() instanceof java.net.InetSocketAddress socketAddress && !socketAddress.isUnresolved() && !socketAddress.getAddress().isLoopbackAddress()) {
+ long currentTime = System.currentTimeMillis(); + long currentTime = System.currentTimeMillis();
+ long connectionThrottle = this.server.server.getConnectionThrottle(); + java.net.InetAddress address = socketAddress.getAddress();
+ java.net.InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress();
+ +
+ synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) {
+ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
+ ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime);
+ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle); // Paper - Configurable connection throttle kick message + Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle);
+ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
+ this.connection.disconnect(chatmessage); + this.connection.disconnect(chatmessage);
+ return; + return;
@ -67,11 +68,11 @@
+ ServerHandshakePacketListenerImpl.throttleTracker.values().removeIf(time -> time > connectionThrottle); + ServerHandshakePacketListenerImpl.throttleTracker.values().removeIf(time -> time > connectionThrottle);
+ } + }
+ } + }
+ } // Paper - Unix domain socket support + }
+ } catch (Throwable t) { + } catch (Throwable t) {
+ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); + org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t);
+ } + }
+ // CraftBukkit end + // Paper end - Connection throttle
if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
- Component component; - Component component;
- if (packet.protocolVersion() < 754) { - if (packet.protocolVersion() < 754) {

View File

@ -524,7 +524,7 @@
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress); IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason()); MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
if (ipBanListEntry.getExpires() != null) { if (ipBanListEntry.getExpires() != null) {
@@ -381,69 +_,130 @@ @@ -381,69 +_,131 @@
); );
} }
@ -649,6 +649,7 @@
+ // Paper start - Add PlayerPostRespawnEvent + // Paper start - Add PlayerPostRespawnEvent
+ boolean isBedSpawn = false; + boolean isBedSpawn = false;
+ boolean isRespawn = false; + boolean isRespawn = false;
+ boolean isAnchorSpawn = false;
+ // Paper end - Add PlayerPostRespawnEvent + // Paper end - Add PlayerPostRespawnEvent
+ +
+ // CraftBukkit start - fire PlayerRespawnEvent + // CraftBukkit start - fire PlayerRespawnEvent
@ -714,13 +715,17 @@
serverPlayer.setHealth(serverPlayer.getHealth()); serverPlayer.setHealth(serverPlayer.getHealth());
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig(); ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
if (!keepInventory && respawnConfig != null) { if (!keepInventory && respawnConfig != null) {
@@ -477,8 +_,41 @@ @@ -477,8 +_,52 @@
) )
); );
} }
+ // Paper start - Add PlayerPostRespawnEvent + // Paper start - Add PlayerPostRespawnEvent
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) { + if (!teleportTransition.missingRespawnBlock()) {
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS)) {
+ isBedSpawn = true; + isBedSpawn = true;
+ } else if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
+ isAnchorSpawn = true;
+ }
+ } + }
+ // Paper end - Add PlayerPostRespawnEvent + // Paper end - Add PlayerPostRespawnEvent
} }
@ -748,7 +753,14 @@
+ +
+ // Paper start - Add PlayerPostRespawnEvent + // Paper start - Add PlayerPostRespawnEvent
+ if (isRespawn) { + if (isRespawn) {
+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(player.getBukkitEntity(), location, isBedSpawn)); + new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(
+ player.getBukkitEntity(),
+ location,
+ isBedSpawn,
+ isAnchorSpawn,
+ teleportTransition.missingRespawnBlock(),
+ eventReason
+ ).callEvent();
+ } + }
+ // Paper end - Add PlayerPostRespawnEvent + // Paper end - Add PlayerPostRespawnEvent
+ +

View File

@ -1,16 +1,22 @@
--- a/net/minecraft/util/datafix/DataFixers.java --- a/net/minecraft/util/datafix/DataFixers.java
+++ b/net/minecraft/util/datafix/DataFixers.java +++ b/net/minecraft/util/datafix/DataFixers.java
@@ -541,6 +_,18 @@ @@ -541,6 +_,24 @@
Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED); Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED);
builder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); builder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
Schema schema45 = builder.addSchema(1458, V1458::new); Schema schema45 = builder.addSchema(1458, V1458::new);
+ // CraftBukkit start + // CraftBukkit start
+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { + // API allows setting player custom names, so we need to convert them.
+ // This does *not* handle upgrades in any other version, but generally those shouldn't need conversion.
+ builder.addFixer(new DataFix(schema45, false) {
+ @Override + @Override
+ protected com.mojang.datafixers.TypeRewriteRule makeRule() { + protected TypeRewriteRule makeRule() {
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), (typed) -> { + return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), typed -> {
+ return typed.update(DSL.remainderFinder(), (dynamic) -> { + return typed.update(DSL.remainderFinder(), dynamic -> {
+ return EntityCustomNameToComponentFix.fixCustomName(dynamic.getOps(), dynamic.get("CustomName").asString(""), "minecraft:player"); + final String customName = dynamic.get("CustomName").asString("");
+ if (customName.isEmpty()) {
+ return dynamic.remove("CustomName");
+ }
+ return dynamic.set("CustomName", LegacyComponentDataFixUtils.createPlainTextComponent(dynamic.getOps(), customName));
+ }); + });
+ }); + });
+ } + }

View File

@ -0,0 +1,10 @@
--- a/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java
+++ b/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java
@@ -39,6 +_,6 @@
.renameField("PostRaidTicks", "post_raid_ticks")
.renameField("TotalHealth", "total_health")
.renameField("NumGroups", "group_count")
- .renameField("Status", "status");
+ .renameField("Status", "status").renameField("HeroesOfTheVillage", "heroes_of_the_village"); // Paper - Add missing rename
}
}

View File

@ -0,0 +1,41 @@
--- a/net/minecraft/world/damagesource/CombatTracker.java
+++ b/net/minecraft/world/damagesource/CombatTracker.java
@@ -29,15 +_,24 @@
private int combatEndTime;
public boolean inCombat;
public boolean takingDamage;
+ public final io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper paperCombatTracker; // Paper - Combat tracker API
public CombatTracker(LivingEntity mob) {
this.mob = mob;
+ this.paperCombatTracker = new io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper(this); // Paper - Combat tracker API
}
public void recordDamage(DamageSource source, float damage) {
this.recheckStatus();
FallLocation currentFallLocation = FallLocation.getCurrentFallLocation(this.mob);
CombatEntry combatEntry = new CombatEntry(source, damage, currentFallLocation, (float)this.mob.fallDistance);
+ // Paper start - Combat tracker API
+ recordDamageAndCheckCombatState(combatEntry);
+ }
+
+ public void recordDamageAndCheckCombatState(final CombatEntry combatEntry) {
+ final DamageSource source = combatEntry.source();
+ // Paper end - Combat tracker API
this.entries.add(combatEntry);
this.lastDamageTime = this.mob.tickCount;
this.takingDamage = true;
@@ -147,6 +_,13 @@
public void recheckStatus() {
int i = this.inCombat ? 300 : 100;
if (this.takingDamage && (!this.mob.isAlive() || this.mob.tickCount - this.lastDamageTime > i)) {
+ // Paper start - Combat tracker API
+ resetCombatState();
+ }
+ }
+
+ public void resetCombatState() {{
+ // Paper end - Combat tracker API
boolean flag = this.inCombat;
this.takingDamage = false;
this.inCombat = false;

View File

@ -126,6 +126,15 @@
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0}; private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
private long pistonDeltasGameTime; private long pistonDeltasGameTime;
private EntityDimensions dimensions; private EntityDimensions dimensions;
@@ -251,7 +_,7 @@
private boolean onGroundNoBlocks = false;
private float crystalSoundIntensity;
private int lastCrystalSoundPlayTick;
- public boolean hasVisualFire;
+ public net.kyori.adventure.util.TriState visualFire = net.kyori.adventure.util.TriState.NOT_SET; // Paper - improve visual fire API
@Nullable
private BlockState inBlockState = null;
private final List<List<Entity.Movement>> movementThisTick = new ObjectArrayList<>();
@@ -259,6 +_,41 @@ @@ -259,6 +_,41 @@
private final LongSet visitedBlocks = new LongOpenHashSet(); private final LongSet visitedBlocks = new LongOpenHashSet();
private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector(); private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector();
@ -392,7 +401,12 @@
} }
this.checkBelowWorld(); this.checkBelowWorld();
@@ -504,7 +_,12 @@ @@ -500,11 +_,16 @@
}
public void setSharedFlagOnFire(boolean isOnFire) {
- this.setSharedFlag(0, isOnFire || this.hasVisualFire);
+ this.setSharedFlag(0, this.visualFire.toBooleanOrElse(isOnFire)); // Paper - improve visual fire API
} }
public void checkBelowWorld() { public void checkBelowWorld() {
@ -694,7 +708,7 @@
return true; return true;
} }
} }
@@ -1805,14 +_,34 @@ @@ -1805,14 +_,35 @@
} }
public CompoundTag saveWithoutId(CompoundTag compound) { public CompoundTag saveWithoutId(CompoundTag compound) {
@ -715,6 +729,7 @@
} }
+ } // CraftBukkit + } // CraftBukkit
+ this.setDeltaMovement(io.papermc.paper.util.MCUtil.sanitizeNanInf(this.deltaMovement, 0D)); // Paper - remove NaN values before usage in saving
compound.store("Motion", Vec3.CODEC, this.getDeltaMovement()); compound.store("Motion", Vec3.CODEC, this.getDeltaMovement());
+ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero + // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero
+ // TODO: make sure this is the best way to address this. + // TODO: make sure this is the best way to address this.
@ -760,6 +775,21 @@
Component customName = this.getCustomName(); Component customName = this.getCustomName();
if (customName != null) { if (customName != null) {
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE); RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
@@ -1848,9 +_,12 @@
compound.putInt("TicksFrozen", this.getTicksFrozen());
}
- if (this.hasVisualFire) {
- compound.putBoolean("HasVisualFire", this.hasVisualFire);
+ // Paper start - improve visual fire API
+ if (this.visualFire.equals(net.kyori.adventure.util.TriState.TRUE)) {
+ compound.putBoolean("HasVisualFire", true);
}
+ compound.putString("Paper.FireOverride", visualFire.name());
+ // Paper end
if (!this.tags.isEmpty()) {
compound.store("Tags", TAG_LIST_CODEC, List.copyOf(this.tags));
@@ -1860,13 +_,13 @@ @@ -1860,13 +_,13 @@
compound.store("data", CustomData.CODEC, this.customData); compound.store("data", CustomData.CODEC, this.customData);
} }
@ -810,6 +840,37 @@
return compound; return compound;
} catch (Throwable var8) { } catch (Throwable var8) {
CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT"); CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT");
@@ -1888,7 +_,7 @@
public void load(CompoundTag compound) {
try {
Vec3 vec3 = compound.read("Pos", Vec3.CODEC).orElse(Vec3.ZERO);
- Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO);
+ Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO); vec31 = io.papermc.paper.util.MCUtil.sanitizeNanInf(vec31, 0D); // Paper - avoid setting NaN values
Vec2 vec2 = compound.read("Rotation", Vec2.CODEC).orElse(Vec2.ZERO);
this.setDeltaMovement(Math.abs(vec31.x) > 10.0 ? 0.0 : vec31.x, Math.abs(vec31.y) > 10.0 ? 0.0 : vec31.y, Math.abs(vec31.z) > 10.0 ? 0.0 : vec31.z);
this.hasImpulse = true;
@@ -1921,7 +_,20 @@
this.setNoGravity(compound.getBooleanOr("NoGravity", false));
this.setGlowingTag(compound.getBooleanOr("Glowing", false));
this.setTicksFrozen(compound.getIntOr("TicksFrozen", 0));
- this.hasVisualFire = compound.getBooleanOr("HasVisualFire", false);
+ // Paper start - improve visual fire API
+ compound.getString("Paper.FireOverride").ifPresentOrElse(
+ override -> {
+ try {
+ this.visualFire = net.kyori.adventure.util.TriState.valueOf(override);
+ } catch (final Exception ignored) {
+ LOGGER.error("Unknown fire override {} for {}", override, this);
+ }
+ },
+ () -> this.visualFire = compound.getBoolean("HasVisualFire")
+ .map(net.kyori.adventure.util.TriState::byBoolean)
+ .orElse(net.kyori.adventure.util.TriState.NOT_SET)
+ );
+ // Paper end
this.customData = compound.read("data", CustomData.CODEC).orElse(CustomData.EMPTY);
this.tags.clear();
compound.read("Tags", TAG_LIST_CODEC).ifPresent(this.tags::addAll);
@@ -1932,6 +_,67 @@ @@ -1932,6 +_,67 @@
} else { } else {
throw new IllegalStateException("Entity has invalid rotation"); throw new IllegalStateException("Entity has invalid rotation");

View File

@ -97,7 +97,7 @@
Vec3 vec3 = new Vec3( Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(), this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(), this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -161,16 +_,27 @@ @@ -161,18 +_,29 @@
} }
public static void award(ServerLevel level, Vec3 pos, int amount) { public static void award(ServerLevel level, Vec3 pos, int amount) {
@ -124,9 +124,17 @@
private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) { private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) {
+ // Paper - TODO some other event for this kind of merge + // Paper - TODO some other event for this kind of merge
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0); AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
int randomInt = level.getRandom().nextInt(40); - int randomInt = level.getRandom().nextInt(40);
+ int randomInt = level.getRandom().nextInt(io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA)); // Paper - Configure how many orb groups per area
List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount)); List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount));
@@ -193,9 +_,14 @@ if (!entities.isEmpty()) {
ExperienceOrb experienceOrb = entities.get(0);
@@ -189,13 +_,18 @@
}
private static boolean canMerge(ExperienceOrb orb, int amount, int other) {
- return !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.getValue() == other;
+ return !orb.isRemoved() && (orb.getId() - amount) % io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA) == 0 && orb.getValue() == other; // Paper - Configure how many orbs will merge together
} }
private void merge(ExperienceOrb orb) { private void merge(ExperienceOrb orb) {

View File

@ -198,7 +198,7 @@
} }
return true; return true;
@@ -400,31 +_,34 @@ @@ -400,31 +_,42 @@
float health = this.getHealth(); float health = this.getHealth();
health -= damageAmount; health -= damageAmount;
if (health <= 0.5F) { if (health <= 0.5F) {
@ -231,13 +231,24 @@
+ // this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down + // this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) { for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY); - ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY);
+ ItemStack itemStack = this.equipment.get(equipmentSlot); // Paper - move equipment removal past event call
if (!itemStack.isEmpty()) { if (!itemStack.isEmpty()) {
- Block.popResource(this.level(), this.blockPosition().above(), itemStack); - Block.popResource(this.level(), this.blockPosition().above(), itemStack);
- }
- }
+ this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly} + this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly}
} + }
} + }
+ return this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved from above // Paper + // Paper start - move equipment removal past event call
+ org.bukkit.event.entity.EntityDeathEvent event = this.dropAllDeathLoot(level, damageSource);
+ if (!event.isCancelled()) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ this.equipment.set(equipmentSlot, ItemStack.EMPTY);
+ }
+ }
+ return event;
+ // Paper end - move equipment removal past event call
} }
private void playBrokenSound() { private void playBrokenSound() {

View File

@ -48,7 +48,7 @@
double squareRoot = Math.sqrt(d * d + d2 * d2); double squareRoot = Math.sqrt(d * d + d2 * d2);
if (this.level() instanceof ServerLevel serverLevel) { if (this.level() instanceof ServerLevel serverLevel) {
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - improve entity shoot bow event, add arrow stack to event + org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, distanceFactor, true); // Paper - improve entity shoot bow event, add arrow stack to event
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ event.getProjectile().remove(); + event.getProjectile().remove();
+ return; + return;

View File

@ -56,7 +56,20 @@
this.setTarget(null); this.setTarget(null);
this.teleport(); this.teleport();
} }
@@ -369,11 +_,13 @@ @@ -359,21 +_,25 @@
AbstractThrownPotion abstractThrownPotion1 = damageSource.getDirectEntity() instanceof AbstractThrownPotion abstractThrownPotion
? abstractThrownPotion
: null;
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) {
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) { // Paper - EndermanEscapeEvent - diff on change - below logic relies on this path covering non-projectile damage.
boolean flag = super.hurtServer(level, damageSource, amount);
if (!(damageSource.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) {
+ if (this.tryEscape(damageSource.is(net.minecraft.tags.DamageTypeTags.IS_DROWNING) ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.CRITICAL_HIT)) { // Paper - EndermanEscapeEvent
this.teleport();
+ } // Paper - EndermanEscapeEvent
}
return flag;
} else { } else {
boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount); boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount);

View File

@ -5,7 +5,7 @@
double squareRoot = Math.sqrt(d * d + d2 * d2); double squareRoot = Math.sqrt(d * d + d2 * d2);
if (this.level() instanceof ServerLevel serverLevel) { if (this.level() instanceof ServerLevel serverLevel) {
+ // Paper start - EntityShootBowEvent + // Paper start - EntityShootBowEvent
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), 0.8F, true); + org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), distanceFactor, true);
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ event.getProjectile().remove(); + event.getProjectile().remove();
+ return; + return;

View File

@ -66,7 +66,7 @@
+ // CraftBukkit end + // CraftBukkit end
+ } + }
+ // CraftBukkit start + // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { + if (!slimes.isEmpty() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { // check for empty converted entities or cancel event
+ super.remove(reason, eventCause); // add Bukkit remove cause + super.remove(reason, eventCause); // add Bukkit remove cause
+ return; + return;
+ } + }

View File

@ -42,6 +42,29 @@
return; return;
} }
} else { } else {
@@ -166,12 +_,14 @@
if (this.currentState == FishingHook.FishHookState.FLYING) {
if (this.hookedIn != null) {
this.setDeltaMovement(Vec3.ZERO);
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.HOOKED_ENTITY).callEvent(); // Paper - Add FishHookStateChangeEvent. #HOOKED_ENTITY
this.currentState = FishingHook.FishHookState.HOOKED_IN_ENTITY;
return;
}
if (flag) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.3, 0.2, 0.3));
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.BOBBING).callEvent(); // Paper - Add FishHookStateChangeEvent. #BOBBING
this.currentState = FishingHook.FishHookState.BOBBING;
return;
}
@@ -184,6 +_,7 @@
this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8), this.hookedIn.getZ());
} else {
this.setHookedEntity(null);
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.UNHOOKED).callEvent(); // Paper - Add FishHookStateChangeEvent. #UNHOOKED
this.currentState = FishingHook.FishHookState.FLYING;
}
}
@@ -247,14 +_,14 @@ @@ -247,14 +_,14 @@
if (!player.isRemoved() && player.isAlive() && (isFishingRod || isFishingRod1) && !(this.distanceToSqr(player) > 1024.0)) { if (!player.isRemoved() && player.isAlive() && (isFishingRod || isFishingRod1) && !(this.distanceToSqr(player) > 1024.0)) {
return false; return false;

View File

@ -13,11 +13,12 @@
public static final SpawnPlacementType RAVAGER_SPAWN_PLACEMENT_TYPE = SpawnPlacements.getPlacementType(EntityType.RAVAGER); public static final SpawnPlacementType RAVAGER_SPAWN_PLACEMENT_TYPE = SpawnPlacements.getPlacementType(EntityType.RAVAGER);
public static final MapCodec<Raid> MAP_CODEC = RecordCodecBuilder.mapCodec( public static final MapCodec<Raid> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group( instance -> instance.group(
@@ -74,6 +_,7 @@ @@ -74,6 +_,8 @@
Raid.RaidStatus.CODEC.fieldOf("status").forGetter(raid -> raid.status), Raid.RaidStatus.CODEC.fieldOf("status").forGetter(raid -> raid.status),
BlockPos.CODEC.fieldOf("center").forGetter(raid -> raid.center), BlockPos.CODEC.fieldOf("center").forGetter(raid -> raid.center),
UUIDUtil.CODEC_SET.fieldOf("heroes_of_the_village").forGetter(raid -> raid.heroesOfTheVillage) UUIDUtil.CODEC_SET.fieldOf("heroes_of_the_village").forGetter(raid -> raid.heroesOfTheVillage)
+ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).fieldOf(PDC_NBT_KEY).forGetter(raid -> raid.persistentDataContainer) + , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).lenientOptionalFieldOf(PDC_NBT_KEY) // Paper - add persistent data container
+ .forGetter(raid -> raid.persistentDataContainer.isEmpty() ? java.util.Optional.empty() : java.util.Optional.of(raid.persistentDataContainer)) // Paper - add persistent data container
) )
.apply(instance, Raid::new) .apply(instance, Raid::new)
); );
@ -33,7 +34,7 @@
Raid.RaidStatus status, Raid.RaidStatus status,
BlockPos center, BlockPos center,
Set<UUID> heroesOfTheVillage Set<UUID> heroesOfTheVillage
+ , final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer // Paper - add persistent data container + , final Optional<org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer> persistentDataContainer // Paper - add persistent data container
) { ) {
this.started = started; this.started = started;
this.active = active; this.active = active;
@ -41,7 +42,7 @@
this.numGroups = numGroups; this.numGroups = numGroups;
this.status = status; this.status = status;
this.heroesOfTheVillage.addAll(heroesOfTheVillage); this.heroesOfTheVillage.addAll(heroesOfTheVillage);
+ this.persistentDataContainer = persistentDataContainer; // Paper - add persistent data container + this.persistentDataContainer = persistentDataContainer.orElseGet(() -> new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY)); // Paper - add persistent data container
} }
public boolean isOver() { public boolean isOver() {

Some files were not shown because too many files have changed in this diff Show More