From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Hugo Manrique Date: Mon, 23 Jul 2018 14:22:26 +0200 Subject: [PATCH] Vanished players don't have rights diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java index 8af1571c614a39c9673e0dc90e3aa9a89a367e34..daa55eed9cf385c7e2cdd0a5dceaf0a719652213 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java @@ -209,7 +209,14 @@ public abstract class Projectile extends Entity { if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { Entity entity1 = this.getOwner(); + // Paper start - Cancel hit for vanished players + if (entity1 instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer) { + org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); + org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); + if (!shooter.canSee(collided)) return false; + } return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); + // Paper end } else { return false; } diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java index 8cf2dc21bcc2547b5af5501e60be39ca18a0e9f2..d36e73cfab79960bf4d778ea01a684b9b6af39d7 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -195,7 +195,8 @@ public class BlockItem extends Item { Player entityhuman = context.getPlayer(); CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); // CraftBukkit start - store default return - boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); + Level world = context.getLevel(); // Paper + boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index d49ce298219dd2144ca1357ab9f158455187c985..17f596e6059334114ce3ee17fbde1ce3d14c5ca1 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -71,6 +71,10 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.scores.Scoreboard; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -249,6 +253,45 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); } + // Paper start + // ret true if no collision + public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, + BlockPos position, boolean checkCanSee) { + // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) + VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); + if (voxelshape.isEmpty()) { + return true; + } + + voxelshape = voxelshape.move((double) position.getX(), (double) position.getY(), (double) position.getZ()); + if (voxelshape.isEmpty()) { + return true; + } + + List entities = this.getEntities(null, voxelshape.bounds()); + for (int i = 0, len = entities.size(); i < len; ++i) { + Entity entity = entities.get(i); + + if (checkCanSee && source instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer + && !((net.minecraft.server.level.ServerPlayer) source).getBukkitEntity().canSee(((net.minecraft.server.level.ServerPlayer) entity).getBukkitEntity())) { + continue; + } + + // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); + // elide the last check since vanilla calls with entity = null + // only we care about the source for the canSee check + if (entity.isRemoved() || !entity.blocksBuilding) { + continue; + } + + if (Shapes.joinIsNotEmpty(voxelshape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) { + return false; + } + } + + return true; + } + // Paper end @Override public boolean isClientSide() { return this.isClientSide; diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index 8e0b6910c97789b4d03ae62723dceb962487fc5a..4faf98079a6a6af662e11050a0088578ba65a5eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1229,6 +1229,14 @@ public class CraftEventFactory { Projectile projectile = (Projectile) entity.getBukkitEntity(); org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); + + if (projectile.getShooter() instanceof Player && collided instanceof Player) { + if (!((Player) projectile.getShooter()).canSee((Player) collided)) { + event.setCancelled(true); + return event; + } + } + Bukkit.getPluginManager().callEvent(event); return event; }