Skip to content

Add methods for CreakingHeart #12095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c1f8d36
add methods for CreakingHeart
Doc94 Feb 10, 2025
3359c43
missing behaviour for make the creaking protect the block
Doc94 Feb 10, 2025
7588ff9
fix typo in precondition
Doc94 Feb 10, 2025
c898ee0
add CreakingHeart#spreadResin()
Doc94 Feb 10, 2025
16cecff
add methods for max distance of Creaking attached
Doc94 Feb 10, 2025
58888fe
handle spawn with the limits of distance for avoid bucle of spawn-dea…
Doc94 Feb 10, 2025
5a54251
remove new line in final
Doc94 Feb 10, 2025
433bc1e
fix CreakingHeart#spawnCreaking() annotation
Doc94 Feb 10, 2025
0306df1
update logic for spawn creaking protector in creaking heart
Doc94 Feb 10, 2025
47b97d0
Revert "update logic for spawn creaking protector in creaking heart"
Doc94 Feb 10, 2025
a6681d7
use correct tag definition and only save if value its not default van…
Doc94 Feb 10, 2025
0f0986a
add apinote to CreakingHeart#spreadResin() for events being called
Doc94 Feb 10, 2025
de1eeb0
[ci skip] rename api method for removal distance
Doc94 Apr 29, 2025
1fa85b6
Merge branch 'main' of github.com:PaperMC/Paper into feature/creaking…
Doc94 Apr 29, 2025
6b38857
Rename methods for Creaking remove distance
Doc94 Apr 29, 2025
64a5272
Fix 1.21.5 renames
Doc94 Apr 29, 2025
63714bd
Better check for null level in spawnCreaking
Doc94 Apr 29, 2025
f1d7c36
Allow 0 for the CreakingRemovalDistance
Doc94 Apr 29, 2025
083707c
Use requirePlaced
Doc94 Apr 29, 2025
3c9e92f
Reduce added methods in NMS patches
Doc94 Apr 29, 2025
1ea7432
Merge branch 'main' of github.com:PaperMC/Paper into feature/creaking…
Doc94 May 1, 2025
9d00d07
Add fallback distanceCreakingTooFar when tag is missing
Doc94 May 1, 2025
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 @@ -592,6 +592,10 @@ public net.minecraft.world.level.block.entity.ConduitBlockEntity destroyTargetUU
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.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()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
54 changes: 54 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,61 @@
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 don't have 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
*/
void setCreaking(@Nullable Creaking creaking);

/**
* Gets the max distance between the Creaking Heart and the Creaking before to remove.
*
* @return the max distance
*/
int getMaxDistanceForCreaking();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like this method name.
Especially when we also might add API for the creaking spawn distance.

getProtectorSurvivalRange
setProtectorSurvivalRange
getProtectorSpawnRange
setProtectorSpawnRange
might work, more peoples input tho pls.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the lasts ones not like just becauuse that value its not for spawn.. its for limit the max distance where a creaking can "live"

maybe the first can work.. but not sure..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last ones were for the new API regarding the replacement for scaling, sorry xD
But yea, more people time chime in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCreakingRemovalDistance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCreakingRemovalDistance?

not sounds bad... maybe can use that then (based in not another comments xd)


/**
* Sets the max distance between the Creaking Heart and the Creaking before to remove.
*
* @param distance the max distance
* @throws IllegalArgumentException if the distance is negative
*/
void setMaxDistanceForCreaking(int distance);

/**
* Attempts to spawn a creaking for protect this creaking heart.
*
* @return the {@link Creaking} for protect the creaking heart or null if fails
*/
@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
*/
@Nullable
Location spreadResin();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
--- a/net/minecraft/world/level/block/entity/CreakingHeartBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/CreakingHeartBlockEntity.java
@@ -120,7 +_,7 @@
Optional<Creaking> creakingProtector = creakingHeart.getCreakingProtector();
if (creakingProtector.isPresent()) {
Creaking creaking = creakingProtector.get();
- if (!CreakingHeartBlock.isNaturalNight(level) || creakingHeart.distanceToCreaking() > 34.0 || creaking.playerIsStuckInYou()) {
+ if (!CreakingHeartBlock.isNaturalNight(level) || creakingHeart.distanceToCreaking() > creakingHeart.getDistanceCreakingTooFar() || creaking.playerIsStuckInYou()) { // Paper - custom distance for creaking
creakingHeart.removeProtector(null);
return;
}
@@ -187,9 +_,10 @@

@Nullable
public static Creaking spawnProtector(ServerLevel level, CreakingHeartBlockEntity creakingHeart) {
+ if (creakingHeart.getDistanceCreakingTooFar() <= 0) return null; // Paper - avoid spawn if the max distance is 0
BlockPos blockPos = creakingHeart.getBlockPos();
Optional<Creaking> optional = SpawnUtil.trySpawnMob(
- EntityType.CREAKING, EntitySpawnReason.SPAWNER, level, blockPos, 5, 16, 8, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER_NO_LEAVES, true
+ EntityType.CREAKING, EntitySpawnReason.SPAWNER, level, blockPos, 5, Math.min(SPAWN_RANGE_XZ, creakingHeart.getDistanceCreakingTooFar()), Math.min(SPAWN_RANGE_Y, creakingHeart.getDistanceCreakingTooFar()), SpawnUtil.Strategy.ON_TOP_OF_COLLIDER_NO_LEAVES, true // Paper - handle too far distance for avoid spawn out of limits
);
if (optional.isEmpty()) {
return null;
@@ -335,6 +_,7 @@
} else {
this.clearCreakingInfo();
}
+ this.distanceCreakingTooFar = tag.contains(PAPER_CREAKING_MAX_DISTANCE_TAG, net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) ? tag.getInt(PAPER_CREAKING_MAX_DISTANCE_TAG) : DISTANCE_CREAKING_TOO_FAR; // Paper - Custom max distance for Creaking
}

@Override
@@ -343,5 +_,23 @@
if (this.creakingInfo != null) {
tag.putUUID("creaking", this.creakingInfo.map(Entity::getUUID, uuid -> (UUID)uuid));
}
- }
+ if (this.distanceCreakingTooFar != DISTANCE_CREAKING_TOO_FAR) tag.putInt(PAPER_CREAKING_MAX_DISTANCE_TAG, this.distanceCreakingTooFar); // Paper - Custom max distance for Creaking
+ }
+
+ // Paper start - Custom Properties
+ private final String PAPER_CREAKING_MAX_DISTANCE_TAG = "Paper.CreakingMaxDistance";
+ private int distanceCreakingTooFar = DISTANCE_CREAKING_TOO_FAR;
+
+ public int getDistanceCreakingTooFar() {
+ return this.distanceCreakingTooFar;
+ }
+
+ public void setDistanceCreakingTooFar(int distance) {
+ this.distanceCreakingTooFar = distance;
+ }
+
+ public void resetEffectRange() {
+ this.distanceCreakingTooFar = DISTANCE_CREAKING_TOO_FAR;
+ }
+ // Paper end
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package org.bukkit.craftbukkit.block;

import com.google.common.base.Preconditions;
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 tileEntity) {
Expand All @@ -24,4 +33,48 @@ public CraftCreakingHeart copy() {
public CraftCreakingHeart copy(Location location) {
return new CraftCreakingHeart(this, location);
}

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

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

@Override
public int getMaxDistanceForCreaking() {
return this.getSnapshot().getDistanceCreakingTooFar();
}

@Override
public void setMaxDistanceForCreaking(final int distance) {
Preconditions.checkArgument(distance >= 0, "the distance must be >= 0");
this.getSnapshot().setDistanceCreakingTooFar(distance);
}

@Nullable
@Override
public Creaking spawnCreaking() {
net.minecraft.world.entity.monster.creaking.Creaking creaking = CreakingHeartBlockEntity.spawnProtector(this.getTileEntity().getLevel().getMinecraftWorld(), this.getTileEntity());
if (creaking != null) {
this.getTileEntity().setCreakingInfo(creaking);
creaking.makeSound(SoundEvents.CREAKING_SPAWN);
this.getTileEntity().getLevel().playSound(null, this.getTileEntity().getBlockPos(), SoundEvents.CREAKING_HEART_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return creaking != null ? ((Creaking) creaking.getBukkitEntity()) : null;
}

@Nullable
@Override
public Location spreadResin() {
return this.getTileEntity().spreadResin().map(blockPos -> CraftLocation.toBukkit(blockPos, this.getWorld())).orElse(null);
}
}
Loading