Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4612a03
add methods for CreakingHeart
Doc94 Feb 10, 2025
118322a
missing behaviour for make the creaking protect the block
Doc94 Feb 10, 2025
e6c49d6
fix typo in precondition
Doc94 Feb 10, 2025
f4da53b
add CreakingHeart#spreadResin()
Doc94 Feb 10, 2025
b0208e3
add methods for max distance of Creaking attached
Doc94 Feb 10, 2025
b140241
handle spawn with the limits of distance for avoid bucle of spawn-dea…
Doc94 Feb 10, 2025
0fdd0d6
remove new line in final
Doc94 Feb 10, 2025
3b3e4ea
fix CreakingHeart#spawnCreaking() annotation
Doc94 Feb 10, 2025
0e41c51
update logic for spawn creaking protector in creaking heart
Doc94 Feb 10, 2025
668816f
Revert "update logic for spawn creaking protector in creaking heart"
Doc94 Feb 10, 2025
c720b5c
use correct tag definition and only save if value its not default van…
Doc94 Feb 10, 2025
970fe67
add apinote to CreakingHeart#spreadResin() for events being called
Doc94 Feb 10, 2025
274c9db
[ci skip] rename api method for removal distance
Doc94 Apr 29, 2025
15856eb
Rename methods for Creaking remove distance
Doc94 Apr 29, 2025
3e7ebfb
Fix 1.21.5 renames
Doc94 Apr 29, 2025
5207493
Better check for null level in spawnCreaking
Doc94 Apr 29, 2025
667a741
Allow 0 for the CreakingRemovalDistance
Doc94 Apr 29, 2025
c7250e4
Use requirePlaced
Doc94 Apr 29, 2025
a317f6d
Reduce added methods in NMS patches
Doc94 Apr 29, 2025
ab301a2
Add fallback distanceCreakingTooFar when tag is missing
Doc94 May 1, 2025
179a9a0
CreakingHeartBlockEntity.java.patch fix for renames
Doc94 Nov 22, 2025
75c07d9
Merge branch 'main' of github.com:PaperMC/Paper into feature/creaking…
Doc94 Feb 9, 2026
d7064ca
Fix spreadResin method signature
Doc94 Feb 9, 2026
4c7dcbb
Remove the reason why this was stuck in first place
Doc94 Feb 9, 2026
2480369
Handle changes since last update
Doc94 Feb 9, 2026
d469eb5
Merge branch 'main' of github.com:PaperMC/Paper into feature/creaking…
Doc94 Feb 28, 2026
a7c8d23
Cleanup for CraftCreakingHeart
Doc94 Feb 28, 2026
1ba6628
minor tweaks
Warriorrrr Feb 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build-data/paper.at
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,10 @@ public net.minecraft.world.level.block.entity.ConduitBlockEntity effectBlocks
public net.minecraft.world.level.block.entity.ConduitBlockEntity getDestroyRangeAABB(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/AABB;
public net.minecraft.world.level.block.entity.ConduitBlockEntity updateDestroyTarget(Lnet/minecraft/world/entity/EntityReference;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Z)Lnet/minecraft/world/entity/EntityReference;
public net.minecraft.world.level.block.entity.CrafterBlockEntity craftingTicksRemaining
public net.minecraft.world.level.block.entity.CreakingHeartBlockEntity clearCreakingInfo()V
public net.minecraft.world.level.block.entity.CreakingHeartBlockEntity getCreakingProtector()Ljava/util/Optional;
public net.minecraft.world.level.block.entity.CreakingHeartBlockEntity spawnProtector(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/CreakingHeartBlockEntity;)Lnet/minecraft/world/entity/monster/creaking/Creaking;
public net.minecraft.world.level.block.entity.CreakingHeartBlockEntity spreadResin(Lnet/minecraft/server/level/ServerLevel;)Ljava/util/Optional;
public net.minecraft.world.level.block.entity.DecoratedPotBlockEntity decorations
public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter
public net.minecraft.world.level.block.entity.HopperBlockEntity cooldownTime
Expand Down
39 changes: 39 additions & 0 deletions paper-api/src/main/java/org/bukkit/block/CreakingHeart.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
package org.bukkit.block;

import org.bukkit.Location;
import org.bukkit.entity.Creaking;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* Represents a captured state of a creaking heart.
*/
@NullMarked
public interface CreakingHeart extends TileState {

/**
* Gets the creaking protecting this creaking heart.
*
* @return the creaking or null if this creaking heart doesn't have a protector.
*/
@Nullable Creaking getCreaking();

/**
* Sets the creaking protecting this creaking heart.
*
* @param creaking the creaking or null for make this creaking heart don't have protector
* @throws IllegalArgumentException if the creaking passed it's in another world
* @throws IllegalStateException if this block state is not placed
*/
void setCreaking(@Nullable Creaking creaking);

/**
* Attempts to spawn a creaking to protect this creaking heart.
*
* @return the {@link Creaking} for protect the creaking heart or null if fails
Comment thread
Doc94 marked this conversation as resolved.
* @throws IllegalStateException if this block state is not placed
*/
@Nullable Creaking spawnCreaking();

/**
* Attempts to spread resin to adjacent blocks.
*
* @apiNote This method triggers events related to a block being modified
* @return the location of spread resin or null if it cannot spread
Comment thread
Doc94 marked this conversation as resolved.
* @throws IllegalStateException if this block state is not placed
*/
@Nullable Location spreadResin();
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
package org.bukkit.craftbukkit.block;

import com.google.common.base.Preconditions;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.block.entity.CreakingHeartBlockEntity;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreakingHeart;
import org.bukkit.craftbukkit.entity.CraftCreaking;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.Creaking;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
public class CraftCreakingHeart extends CraftBlockEntityState<CreakingHeartBlockEntity> implements CreakingHeart {

public CraftCreakingHeart(World world, CreakingHeartBlockEntity blockEntity) {
super(world, blockEntity);
}

protected CraftCreakingHeart(CraftCreakingHeart state, Location location) {
protected CraftCreakingHeart(CraftCreakingHeart state, @Nullable Location location) {
super(state, location);
}

Expand All @@ -24,4 +34,54 @@ public CraftCreakingHeart copy() {
public CraftCreakingHeart copy(Location location) {
return new CraftCreakingHeart(this, location);
}

@Override
public @Nullable Creaking getCreaking() {
if (!this.isPlaced()) {
return null;
}
return this.getBlockEntity().getCreakingProtector().map(creaking -> ((Creaking) creaking.getBukkitEntity())).orElse(null);
}

@Override
public void setCreaking(final @Nullable Creaking creaking) {
this.requirePlaced();
if (creaking == null) {
this.getBlockEntity().clearCreakingInfo();
} else {
Preconditions.checkArgument(this.getLocation().getWorld().equals(creaking.getLocation().getWorld()), "the location of the creaking must be in the same world as this CreakingHeart");
this.getBlockEntity().setCreakingInfo(((CraftCreaking) creaking).getHandle());
}
}

@Nullable
@Override
public Creaking spawnCreaking() {
this.requirePlaced();
if (!(this.getBlockEntity().getLevel() instanceof ServerLevel serverLevel)) {
return null;
}

final net.minecraft.world.entity.monster.creaking.Creaking creaking = CreakingHeartBlockEntity.spawnProtector(serverLevel, this.getBlockEntity());
if (creaking == null) {
return null;
}

this.getBlockEntity().setCreakingInfo(creaking);
creaking.makeSound(SoundEvents.CREAKING_SPAWN);
serverLevel.playSound(null, this.getBlockEntity().getBlockPos(), SoundEvents.CREAKING_HEART_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);

return (Creaking) creaking.getBukkitEntity();
}

@Nullable
@Override
public Location spreadResin() {
this.requirePlaced();
if (!(this.getBlockEntity().getLevel() instanceof ServerLevel serverLevel)) {
return null;
}

return this.getBlockEntity().spreadResin(serverLevel).map(blockPos -> CraftLocation.toBukkit(blockPos, this.getWorld())).orElse(null);
}
}
Loading