diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 201a542db..3aa49b98f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -194,7 +194,7 @@ public class BukkitPlayer extends AbstractPlayerActor { } @Override - public void setPosition(Vector3 pos, float pitch, float yaw) { + public void trySetPosition(Vector3 pos, float pitch, float yaw) { org.bukkit.World world = player.getWorld(); if (pos instanceof com.sk89q.worldedit.util.Location) { com.sk89q.worldedit.util.Location loc = (com.sk89q.worldedit.util.Location) pos; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java index 32f49f891..0dfbf5d70 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java @@ -36,6 +36,8 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.internal.util.DeprecationUtil; +import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; @@ -301,8 +303,40 @@ public interface Player extends Entity, Actor { * @param pos where to move them * @param pitch the pitch (up/down) of the player's view in degrees * @param yaw the yaw (left/right) of the player's view in degrees + * @deprecated This method may fail without indication. Use + * {@link #trySetPosition(Vector3, float, float)} instead */ - void setPosition(Vector3 pos, float pitch, float yaw); + @Deprecated + default void setPosition(Vector3 pos, float pitch, float yaw) { + trySetPosition(pos, pitch, yaw); + } + + /** + * Attempt to move the player. + * + *
+ * This action may fail, due to other mods cancelling the move. + * If so, this method will return {@code false}. + *
+ * + * @param pos where to move them + * @param pitch the pitch (up/down) of the player's view in degrees + * @param yaw the yaw (left/right) of the player's view in degrees + * @return if the move was able to occur + * @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility} + * for details + */ + @NonAbstractForCompatibility( + delegateName = "setPosition", + delegateParams = { Vector3.class, float.class, float.class } + ) + default boolean trySetPosition(Vector3 pos, float pitch, float yaw) { + DeprecationUtil.checkDelegatingOverride(getClass()); + + setPosition(pos, pitch, yaw); + + return true; + } /** * Sends a fake block to the client. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index 4419f34f6..3e6f65648 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -65,11 +65,14 @@ import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.BlockMaterial; + import java.io.File; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + /** * An abstract implementation of both a {@link Actor} and a {@link Player} * that is intended for implementations of WorldEdit to use to wrap @@ -179,8 +182,13 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { } if (free == 2) { + boolean worked = true; + if (y - 1 != origY) { - setPosition(Vector3.at(x + 0.5, y - 2 + 1, z + 0.5)); + worked = trySetPosition(Vector3.at(x + 0.5, y - 2 + 1, z + 0.5)); + } + + if (worked) { return; } } @@ -199,8 +207,8 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { while (y >= 0) { final BlockVector3 pos = BlockVector3.at(x, y, z); final BlockState id = world.getBlock(pos); - if (id.getBlockType().getMaterial().isMovementBlocker()) { - setPosition(Vector3.at(x + 0.5, y + +BlockTypeUtil.centralTopLimit(id), z + 0.5)); + if (id.getBlockType().getMaterial().isMovementBlocker() + && trySetPosition(Vector3.at(x + 0.5, y + +BlockTypeUtil.centralTopLimit(id), z + 0.5))) { return; } @@ -213,6 +221,26 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { findFreePosition(getBlockLocation()); } + private boolean isBadSpaceForStanding(BlockVector3 location) { + BlockType type = getWorld().getBlock(location).getBlockType(); + return type.getMaterial().isMovementBlocker() || type == BlockTypes.LAVA; + } + + /** + * @param location where the player would be placed (not Y offset) + * @return if the player can stand at the location + */ + private boolean isLocationGoodForStanding(BlockVector3 location) { + if (isBadSpaceForStanding(location.add(0, 1, 0))) { + return false; + } + if (isBadSpaceForStanding(location)) { + return false; + } + return getWorld().getBlock(location.add(0, -1, 0)).getBlockType().getMaterial() + .isMovementBlocker(); + } + @Override public boolean ascendLevel() { final Location pos = getBlockLocation(); @@ -254,9 +282,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { double bottomLimit = BlockTypeUtil.centralBottomLimit(state); double space = level + bottomLimit - freeStart; if (space >= height) { - setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); - return true; - } + trySetPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); + return true; + } // Not enough room, reset the free position if (bottomLimit != 1) { freeStart = -1; @@ -312,9 +340,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { double freeStart = level + topLimit; double space = freeEnd - freeStart; if (space >= height) { - setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); - return true; - } + trySetPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); + return true; + } // Not enough room, reset the free position if (topLimit != 0) { freeEnd = -1; @@ -577,9 +605,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { } @Override - public void setPosition(Vector3 pos) { + public boolean trySetPosition(Vector3 pos) { final Location location = getLocation(); - setPosition(pos, location.getPitch(), location.getYaw()); + return trySetPosition(pos, location.getPitch(), location.getYaw()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Locatable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Locatable.java index cc25ab5c7..9690b48d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Locatable.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Locatable.java @@ -54,9 +54,27 @@ public interface Locatable { * Sets the position of this actor. * * @param pos where to move them + * @deprecated This method may fail without indication. Use {@link #trySetPosition(Vector3)} + * instead */ + @Deprecated default void setPosition(Vector3 pos) { - setLocation(new Location(getExtent(), pos)); + trySetPosition(pos); + } + + /** + * Attempts to set the position of this actor. + * + *+ * This action may fail, due to other mods cancelling the move. + * If so, this method will return {@code false}. + *
+ * + * @param pos the position to set + * @return if the position was able to be set + */ + default boolean trySetPosition(Vector3 pos) { + return setLocation(new Location(getExtent(), pos)); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index 6cd5dfa5f..d76960cb8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -131,8 +131,8 @@ public class PlayerProxy extends AbstractPlayerActor { } @Override - public void setPosition(Vector3 pos, float pitch, float yaw) { - basePlayer.setPosition(pos, pitch, yaw); + public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { + return basePlayer.trySetPosition(pos, pitch, yaw); } @Override diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 1ee00d311..cae7cb1dd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -172,8 +172,9 @@ public class FabricPlayer extends AbstractPlayerActor { } @Override - public void setPosition(Vector3 pos, float pitch, float yaw) { + public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { this.player.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); + return true; } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 289ed5c75..647bee1eb 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -168,8 +168,9 @@ public class ForgePlayer extends AbstractPlayerActor { } @Override - public void setPosition(Vector3 pos, float pitch, float yaw) { + public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); + return true; } @Override diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java index 6603a5bd4..1681c1df9 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java @@ -165,12 +165,12 @@ public class SpongePlayer extends AbstractPlayerActor { } @Override - public void setPosition(Vector3 pos, float pitch, float yaw) { + public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { org.spongepowered.api.world.Location