Stop update from being sent to the player when the player places a block on themselves (#939)

This commit is contained in:
iam 2022-04-17 16:02:24 -04:00 committed by GitHub
parent e57e3ff305
commit bb236b34b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 11 deletions

View File

@ -329,7 +329,7 @@ final class BlockCollision {
Vec.ZERO, finalResult.collidedShapePosition, finalResult.blockType);
}
static boolean canPlaceBlockAt(Instance instance, Point blockPos, Block b) {
static Entity canPlaceBlockAt(Instance instance, Point blockPos, Block b) {
for (Entity entity : instance.getNearbyEntities(blockPos, 3)) {
final EntityType type = entity.getEntityType();
if (type == EntityType.ITEM)
@ -348,9 +348,9 @@ final class BlockCollision {
} else {
intersects = b.registry().collisionShape().intersectBox(entity.getPosition().sub(blockPos), entity.getBoundingBox());
}
if (intersects) return false;
if (intersects) return entity;
}
return true;
return null;
}
/**

View File

@ -80,7 +80,7 @@ public final class CollisionUtils {
return handlePhysics(entity, entityVelocity, null);
}
public static boolean canPlaceBlockAt(Instance instance, Point blockPos, Block b) {
public static Entity canPlaceBlockAt(Instance instance, Point blockPos, Block b) {
return BlockCollision.canPlaceBlockAt(instance, blockPos, b);
}

View File

@ -3,6 +3,7 @@ package net.minestom.server.listener;
import net.minestom.server.MinecraftServer;
import net.minestom.server.collision.CollisionUtils;
import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
@ -105,9 +106,18 @@ public class BlockPlacementListener {
}
final Block placedBlock = useMaterial.block();
if (!CollisionUtils.canPlaceBlockAt(instance, placementPosition, placedBlock)) {
Entity collisionEntity = CollisionUtils.canPlaceBlockAt(instance, placementPosition, placedBlock);
if (collisionEntity != null) {
// If a player is trying to place a block on themselves, the client will send a block change but will not set the block on the client
// For this reason, the block doesn't need to be updated for the client
// Client also doesn't predict placement of blocks on entities, but we need to refresh for cases where bounding boxes on the server don't match the client
if (collisionEntity != player)
refresh(player, chunk);
return;
}
// BlockPlaceEvent check
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand());
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);

View File

@ -9,8 +9,7 @@ import net.minestom.server.entity.EntityType;
import net.minestom.server.instance.block.Block;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
@EnvTest
public class PlacementCollisionIntegrationTest {
@ -18,27 +17,27 @@ public class PlacementCollisionIntegrationTest {
@Test
public void empty(Env env) {
var instance = env.createFlatInstance();
assertTrue(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE));
assertNull(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE));
}
@Test
public void entityBlock(Env env) {
var instance = env.createFlatInstance();
new Entity(EntityType.ZOMBIE).setInstance(instance, new Pos(0, 40, 0)).join();
assertFalse(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE));
assertNotNull(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE));
}
@Test
public void slab(Env env) {
var instance = env.createFlatInstance();
new Entity(EntityType.ZOMBIE).setInstance(instance, new Pos(0, 40.75, 0)).join();
assertTrue(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE_SLAB));
assertNull(BlockCollision.canPlaceBlockAt(instance, new Vec(0, 40, 0), Block.STONE_SLAB));
}
@Test
public void belowPlayer(Env env) {
var instance = env.createFlatInstance();
env.createPlayer(instance, new Pos(5.7, -8, 6.389));
assertTrue(BlockCollision.canPlaceBlockAt(instance, new Vec(5, -9, 6), Block.STONE));
assertNull(BlockCollision.canPlaceBlockAt(instance, new Vec(5, -9, 6), Block.STONE));
}
}