Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.papermc.paper.block.bed;

import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.Nullable;

/**
* An action type that represents the action that will happen after
* {@link org.bukkit.event.player.PlayerBedEnterEvent} and that is
* happening during {@link io.papermc.paper.event.player.PlayerBedFailEnterEvent}
*/
@ApiStatus.NonExtendable
@ApiStatus.Experimental
public interface BedEnterAction {

/**
* Gets if the player is allowed to sleep in the bed.
* This can be {@link BedRuleResult#ALLOWED} at the same time as {@link #canSetSpawn()}
* <p>
* It is advised to check for {@link BedEnterProblem}s first, as if it returns anything but {@code null}
* the bed interaction is prevented
*
* @return whether the player is allowed to sleep
*/
BedRuleResult canSleep();

/**
* Gets if the player is allowed to save its spawn point in the bed.
* This can be {@link BedRuleResult#ALLOWED} at the same time as {@link #canSleep()}
* <p>
* It is advised to check for {@link BedEnterProblem}s first, as if it returns anything but {@code null}
* the bed interaction is prevented
*
* @return whether the player is allowed to save its spawn point
*/
BedRuleResult canSetSpawn();

/**
* A problem is an issue that prevents the player from sleeping and from saving its spawn point.
* No problem being found doesn't mean the player successfully slept or set its spawn point,
* see {@link #canSleep()} and {@link #canSetSpawn()} for individual successes
*
* @return any of {@link BedEnterProblem}s if one is found, otherwise {@code null}
*/
@Nullable
BedEnterProblem problem();

/**
* Returns the default error message to be shown as an actionbar message to the player
*
* @return the error message
*/
@Nullable
Component errorMessage();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.papermc.paper.block.bed;

import java.util.Optional;
import java.util.ServiceLoader;
import org.jetbrains.annotations.ApiStatus;

/**
* @hidden
*/
@ApiStatus.Internal
public interface BedEnterActionBridge {

static BedEnterActionBridge instance() {
final class Holder {
static final Optional<BedEnterActionBridge> INSTANCE = ServiceLoader.load(BedEnterActionBridge.class, BedEnterActionBridge.class.getClassLoader()).findFirst();
}
return Holder.INSTANCE.orElseThrow();
}

BedEnterProblem createTooFarAwayProblem();

BedEnterProblem createObstructedProblem();

BedEnterProblem createNotSafeProblem();

BedEnterProblem createExplosionProblem();

BedEnterProblem createOtherProblem();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.papermc.paper.block.bed;

import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.Nullable;

/**
* Represents a problem that prevents a player from continuing
* the sleeping process, preventing it from sleeping and from setting
* its spawn point
*/
@ApiStatus.NonExtendable
@ApiStatus.Experimental
public interface BedEnterProblem {

/**
* Happens when the bed is too far away from the player.
* Makes no explosion and has an error message
*
* @see #errorMessage()
*/
BedEnterProblem TOO_FAR_AWAY = BedEnterActionBridge.instance().createTooFarAwayProblem();

/**
* Happens when the bed has blocks one block above it.
* Makes no explosion and has an error message
*
* @see #errorMessage()
*/
BedEnterProblem OBSTRUCTED = BedEnterActionBridge.instance().createObstructedProblem();

/**
* Happens when there are monsters in a 16x10x16 box centered on the bed's head
* and the player is not in creative mode. Makes no explosion and has an error message
*
* @see #errorMessage()
*/
BedEnterProblem NOT_SAFE = BedEnterActionBridge.instance().createNotSafeProblem();

/**
* Happens when the bed is set to explode. This is defined in the environment attributes of the world.
* This doesn't have a fixed error message, see {@link BedEnterAction#errorMessage()}
*/
BedEnterProblem EXPLOSION = BedEnterActionBridge.instance().createExplosionProblem();

/**
* Happens when a player tries to sleep when an invalid state, for example when a player tries
* to sleep but is already sleeping or is dead.
* This doesn't have an error message at all, the interaction is simply discarded
*/
BedEnterProblem OTHER = BedEnterActionBridge.instance().createOtherProblem();

/**
* Returns the error message associated with this problem, if any.
* This component is sent to the client as an actionbar message
* when this problem occur
*
* @return the error message
*/
@Nullable
Component errorMessage();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.papermc.paper.block.bed;

import org.jetbrains.annotations.ApiStatus;

/**
* Represents the result of a bed rule during {@link org.bukkit.event.player.PlayerBedEnterEvent}
* and {@link io.papermc.paper.event.player.PlayerBedFailEnterEvent}. Bed rules are responsible
* for allowing players to sleep and to set their spawn point
*/
@ApiStatus.Experimental
public sealed interface BedRuleResult permits BedRuleResultImpl {

/**
* Used when the bed rule is allowed
*/
BedRuleResult ALLOWED = new BedRuleResultImpl(true);

/**
* Used when the bed rule is denied due to there
* being too much light. This is the case during
* daytime without thunderstorms
*/
BedRuleResult TOO_MUCH_LIGHT = new BedRuleResultImpl(false);

/**
* Used when the bed rule is set to always be denied
*/
BedRuleResult NEVER = new BedRuleResultImpl(false);

/**
* Returns {@code true} if this result is a success
*
* @return whether this result is a success
*/
boolean success();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.papermc.paper.block.bed;

import org.jetbrains.annotations.ApiStatus;

/**
* @hidden
*/
@ApiStatus.Internal
record BedRuleResultImpl(
boolean success
) implements BedRuleResult {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@NullMarked
package io.papermc.paper.block.bed;

import org.jspecify.annotations.NullMarked;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.papermc.paper.event.player;

import io.papermc.paper.block.bed.BedEnterAction;
import net.kyori.adventure.text.Component;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
Expand All @@ -15,26 +16,43 @@ public class PlayerBedFailEnterEvent extends PlayerEvent implements Cancellable

private static final HandlerList HANDLER_LIST = new HandlerList();

private final FailReason failReason;
private final @Deprecated(since = "1.21.11") FailReason failReason;
private final Block bed;
private final BedEnterAction enterAction;
private boolean willExplode;
private @Nullable Component message;

private boolean cancelled;

@ApiStatus.Internal
public PlayerBedFailEnterEvent(final Player player, final FailReason failReason, final Block bed, final boolean willExplode, final @Nullable Component message) {
public PlayerBedFailEnterEvent(final Player player, final FailReason failReason, final Block bed, final boolean willExplode, final @Nullable Component message, BedEnterAction enterAction) {
super(player);
this.failReason = failReason;
this.bed = bed;
this.enterAction = enterAction;
this.willExplode = willExplode;
this.message = message;
}

/**
* @deprecated This enum has been replaced with a system that better
* represents how beds work. See {@link #enterAction}
*/
@Deprecated(since = "1.21.11")
public FailReason getFailReason() {
return this.failReason;
}

/**
* This describes the default outcome of this event.
*
* @return the action representing the default outcome of this event
*/
@ApiStatus.Experimental
public BedEnterAction enterAction() {
return this.enterAction;
}

public Block getBed() {
return this.bed;
}
Expand Down Expand Up @@ -80,14 +98,17 @@ public static HandlerList getHandlerList() {
return HANDLER_LIST;
}

/**
* @deprecated Enums no longer represents reliably how beds work and fail. This has been
* replaced with {@link BedEnterAction} that better fits the new beds
*/
@Deprecated(since = "1.21.11")
public enum FailReason {
/**
* The world doesn't allow sleeping (ex. Nether or The End). Entering
* the bed is prevented and the bed explodes.
*
* @deprecated TODO - snapshot - no longer exists in vanilla
* the bed is prevented but the bed doesn't explode. When the bed
* explodes, {@link #EXPLOSION} is used instead.
*/
@Deprecated(since = "1.21.11")
NOT_POSSIBLE_HERE,
/**
* Entering the bed is prevented due to it not being night nor
Expand All @@ -96,10 +117,7 @@ public enum FailReason {
* If the event is forcefully allowed during daytime, the player will
* enter the bed (and set its bed location), but might get immediately
* thrown out again.
*
* @deprecated TODO - snapshot - no longer exists in vanilla
*/
@Deprecated(since = "1.21.11")
NOT_POSSIBLE_NOW,
/**
* Entering the bed is prevented due to the player being too far away.
Expand All @@ -116,6 +134,10 @@ public enum FailReason {
/**
* Entering the bed is prevented due to there being monsters nearby.
*/
NOT_SAFE
NOT_SAFE,
/**
* Entering the bed is prevented and the bed explodes.
*/
EXPLOSION
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it still worth to add new values to deprecated things anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't think so but since It was added before the API rework I left it there. I'm conflicted between "it's done so we may let it be" and "there's a rework so no need to modify deprecated things". I'm fine with both on this one honestly, whatever fits the needs best for the team

}
}
15 changes: 8 additions & 7 deletions paper-api/src/main/java/org/bukkit/World.java
Original file line number Diff line number Diff line change
Expand Up @@ -2793,23 +2793,24 @@ default double getHumidity(int x, int z) {

/**
* Gets if this world is natural.
*
* When false, compasses spin randomly, and using a bed to set the respawn
* point or sleep, is disabled. When true, nether portals can spawn
* zombified piglins.
* <p>
* When false, the moon is not visible and eyeblossoms do not open/close
*
* @return true if world is natural
*/
public boolean isNatural();

/**
* Gets if beds work in this world.
*
* A non-working bed will blow up when trying to sleep. {@link #isNatural()}
* defines if a bed can be used to set spawn point.
* <p>
* A non-working bed can blow up when trying to sleep, but that may
* not always be the case.
*
* @return true if beds work in this world
* @deprecated Due to 1.21.11 beds changes, a boolean no longer
* represents if they work. There is no replacement API yet
*/
@Deprecated(since = "1.21.11")
public boolean isBedWorks();

/**
Expand Down
Loading
Loading