Fix position issue when cancelling the breaking of a block just below the player

This commit is contained in:
themode 2020-09-25 21:50:50 +02:00
parent e6764ce6f7
commit ce81c3a85d
4 changed files with 46 additions and 16 deletions

View File

@ -212,8 +212,12 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
Check.stateCondition(instance == null, "You need to use Entity#setInstance before teleporting an entity!");
final Runnable runnable = () -> {
refreshPosition(position.getX(), position.getY(), position.getZ());
refreshView(position.getYaw(), position.getPitch());
if (!this.position.isSimilar(position)) {
refreshPosition(position.getX(), position.getY(), position.getZ());
}
if (!this.position.hasSimilarView(position)) {
refreshView(position.getYaw(), position.getPitch());
}
sendSynchronization();
if (callback != null)
callback.run();

View File

@ -310,8 +310,8 @@ public class InstanceContainer extends Instance {
PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(player, blockPosition, blockStateId, customBlock, (short) 0, (short) 0);
player.callEvent(PlayerBlockBreakEvent.class, blockBreakEvent);
final boolean result = !blockBreakEvent.isCancelled();
if (result) {
final boolean allowed = !blockBreakEvent.isCancelled();
if (allowed) {
// Break or change the broken block based on event result
setSeparateBlocks(x, y, z, blockBreakEvent.getResultBlockStateId(), blockBreakEvent.getResultCustomBlockId());
@ -330,11 +330,19 @@ public class InstanceContainer extends Instance {
});
} else {
// Cancelled so we need to refresh player chunk section
final int section = ChunkUtils.getSectionAt(blockPosition.getY());
chunk.sendChunkSectionUpdate(section, player);
final boolean solid = Block.fromStateId(blockStateId).isSolid();
if (solid) {
final BlockPosition playerBlockPosition = player.getPosition().toBlockPosition();
// Teleport the player back if he broke a solid block just below him
if (playerBlockPosition.subtract(0, 1, 0).equals(blockPosition)) {
player.teleport(player.getPosition());
}
}
}
return result;
return allowed;
}
@Override

View File

@ -40,7 +40,7 @@ public class PlayerDiggingListener {
Block.fromStateId(blockStateId).breaksInstantaneously();
if (instantBreak) {
breakBlock(instance, player, blockPosition);
breakBlock(instance, player, blockPosition, blockStateId);
} else {
final CustomBlock customBlock = instance.getCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
if (customBlock != null) {
@ -76,7 +76,7 @@ public class PlayerDiggingListener {
ClientPlayerDiggingPacket.Status.CANCELLED_DIGGING, true);
break;
case FINISHED_DIGGING:
breakBlock(instance, player, blockPosition);
breakBlock(instance, player, blockPosition, blockStateId);
break;
case DROP_ITEM_STACK:
final ItemStack droppedItemStack = player.getInventory().getItemInMainHand().clone();
@ -117,16 +117,21 @@ public class PlayerDiggingListener {
}
}
private static void breakBlock(Instance instance, Player player, BlockPosition blockPosition) {
private static void breakBlock(Instance instance, Player player, BlockPosition blockPosition, int blockStateId) {
// Finished digging, remove effect if any
player.resetTargetBlock();
// Unverified block break, client is fully responsive
instance.breakBlock(player, blockPosition);
final boolean result = instance.breakBlock(player, blockPosition);
// Send acknowledge packet to confirm the digging process
sendAcknowledgePacket(player, blockPosition, 0,
ClientPlayerDiggingPacket.Status.FINISHED_DIGGING, true);
final int updatedBlockId = result ? 0 : blockStateId;
final ClientPlayerDiggingPacket.Status status = result ?
ClientPlayerDiggingPacket.Status.FINISHED_DIGGING :
ClientPlayerDiggingPacket.Status.CANCELLED_DIGGING;
// Send acknowledge packet to allow or cancel the digging process
sendAcknowledgePacket(player, blockPosition, updatedBlockId,
status, result);
}
private static void dropItem(Player player, ItemStack droppedItem, ItemStack handItem) {

View File

@ -196,7 +196,20 @@ public class Position {
* @return true if the two positions are similar
*/
public boolean isSimilar(Position position) {
return position.x == x && position.y == y && position.z == z;
return Float.compare(position.x, x) == 0 &&
Float.compare(position.y, y) == 0 &&
Float.compare(position.z, z) == 0;
}
/**
* Check if two positions have a similar view (yaw/pitch)
*
* @param position the position to compare
* @return true if the two positions have the same view
*/
public boolean hasSimilarView(Position position) {
return Float.compare(position.yaw, yaw) == 0 &&
Float.compare(position.pitch, pitch) == 0;
}
@Override