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 b09f52330b50879d5594b21302e70ca676b60951..d7d4aa7ed2f321df8099adb97a3c699ed38ae6fc 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 86d245c9a817be5fd2be7f331d3a3a5f3169e8c2..44b28773fe8e79931e738d493bd9405e0ee3dca9 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -191,7 +191,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 a84c8e135511eed9db5895bdf7fc68b3952a5521..1fef077a6d5efc8bdc171b5c6e2a49129f8589ce 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 e9a7c4a29491b4281f7c96c002bf405b10eb97a2..5d2e1c12feac542463edc7b0e44501c241812310 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1206,6 +1206,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; }