Replace setPosition with trySetPosition (#1403)

Allows cancellation information to be fed back into the ascend/descend
algorithms.

(cherry picked from commit 71e104bcb187a5313e88dda5df79059c8ffbc1fe)
This commit is contained in:
Octavia Togami 2020-07-01 11:24:58 -04:00 committed by MattBDev
parent c82fec931a
commit 4c299bc0b8
8 changed files with 103 additions and 21 deletions

View File

@ -194,7 +194,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
} }
@Override @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(); org.bukkit.World world = player.getWorld();
if (pos instanceof com.sk89q.worldedit.util.Location) { if (pos instanceof com.sk89q.worldedit.util.Location) {
com.sk89q.worldedit.util.Location loc = (com.sk89q.worldedit.util.Location) pos; com.sk89q.worldedit.util.Location loc = (com.sk89q.worldedit.util.Location) pos;

View File

@ -36,6 +36,8 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask; 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.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -301,8 +303,40 @@ public interface Player extends Entity, Actor {
* @param pos where to move them * @param pos where to move them
* @param pitch the pitch (up/down) of the player's view in degrees * @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 * @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.
*
* <p>
* This action may fail, due to other mods cancelling the move.
* If so, this method will return {@code false}.
* </p>
*
* @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. * Sends a fake block to the client.

View File

@ -65,11 +65,14 @@ import com.sk89q.worldedit.world.gamemode.GameModes;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.registry.BlockMaterial; import com.sk89q.worldedit.world.registry.BlockMaterial;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
/** /**
* An abstract implementation of both a {@link Actor} and a {@link Player} * An abstract implementation of both a {@link Actor} and a {@link Player}
* that is intended for implementations of WorldEdit to use to wrap * 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) { if (free == 2) {
boolean worked = true;
if (y - 1 != origY) { 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; return;
} }
} }
@ -199,8 +207,8 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
while (y >= 0) { while (y >= 0) {
final BlockVector3 pos = BlockVector3.at(x, y, z); final BlockVector3 pos = BlockVector3.at(x, y, z);
final BlockState id = world.getBlock(pos); final BlockState id = world.getBlock(pos);
if (id.getBlockType().getMaterial().isMovementBlocker()) { if (id.getBlockType().getMaterial().isMovementBlocker()
setPosition(Vector3.at(x + 0.5, y + +BlockTypeUtil.centralTopLimit(id), z + 0.5)); && trySetPosition(Vector3.at(x + 0.5, y + +BlockTypeUtil.centralTopLimit(id), z + 0.5))) {
return; return;
} }
@ -213,6 +221,26 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
findFreePosition(getBlockLocation()); 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 @Override
public boolean ascendLevel() { public boolean ascendLevel() {
final Location pos = getBlockLocation(); final Location pos = getBlockLocation();
@ -254,7 +282,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
double bottomLimit = BlockTypeUtil.centralBottomLimit(state); double bottomLimit = BlockTypeUtil.centralBottomLimit(state);
double space = level + bottomLimit - freeStart; double space = level + bottomLimit - freeStart;
if (space >= height) { if (space >= height) {
setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); trySetPosition(Vector3.at(x + 0.5, freeStart, z + 0.5));
return true; return true;
} }
// Not enough room, reset the free position // Not enough room, reset the free position
@ -312,7 +340,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
double freeStart = level + topLimit; double freeStart = level + topLimit;
double space = freeEnd - freeStart; double space = freeEnd - freeStart;
if (space >= height) { if (space >= height) {
setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); trySetPosition(Vector3.at(x + 0.5, freeStart, z + 0.5));
return true; return true;
} }
// Not enough room, reset the free position // Not enough room, reset the free position
@ -577,9 +605,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
} }
@Override @Override
public void setPosition(Vector3 pos) { public boolean trySetPosition(Vector3 pos) {
final Location location = getLocation(); final Location location = getLocation();
setPosition(pos, location.getPitch(), location.getYaw()); return trySetPosition(pos, location.getPitch(), location.getYaw());
} }
@Override @Override

View File

@ -54,9 +54,27 @@ public interface Locatable {
* Sets the position of this actor. * Sets the position of this actor.
* *
* @param pos where to move them * @param pos where to move them
* @deprecated This method may fail without indication. Use {@link #trySetPosition(Vector3)}
* instead
*/ */
@Deprecated
default void setPosition(Vector3 pos) { default void setPosition(Vector3 pos) {
setLocation(new Location(getExtent(), pos)); trySetPosition(pos);
}
/**
* Attempts to set the position of this actor.
*
* <p>
* This action may fail, due to other mods cancelling the move.
* If so, this method will return {@code false}.
* </p>
*
* @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));
} }
/** /**

View File

@ -131,8 +131,8 @@ public class PlayerProxy extends AbstractPlayerActor {
} }
@Override @Override
public void setPosition(Vector3 pos, float pitch, float yaw) { public boolean trySetPosition(Vector3 pos, float pitch, float yaw) {
basePlayer.setPosition(pos, pitch, yaw); return basePlayer.trySetPosition(pos, pitch, yaw);
} }
@Override @Override

View File

@ -172,8 +172,9 @@ public class FabricPlayer extends AbstractPlayerActor {
} }
@Override @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); this.player.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
return true;
} }
@Override @Override

View File

@ -168,8 +168,9 @@ public class ForgePlayer extends AbstractPlayerActor {
} }
@Override @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); this.player.connection.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
return true;
} }
@Override @Override

View File

@ -165,12 +165,12 @@ public class SpongePlayer extends AbstractPlayerActor {
} }
@Override @Override
public void setPosition(Vector3 pos, float pitch, float yaw) { public boolean trySetPosition(Vector3 pos, float pitch, float yaw) {
org.spongepowered.api.world.Location<World> loc = new org.spongepowered.api.world.Location<>( org.spongepowered.api.world.Location<World> loc = new org.spongepowered.api.world.Location<>(
this.player.getWorld(), pos.getX(), pos.getY(), pos.getZ() this.player.getWorld(), pos.getX(), pos.getY(), pos.getZ()
); );
this.player.setLocationAndRotation(loc, new Vector3d(pitch, yaw, 0)); return this.player.setLocationAndRotation(loc, new Vector3d(pitch, yaw, 0));
} }
@Override @Override