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 e9ae25a70c747c173ebd2e393818d205527d5314..f49dd279ba9e8970f116f956466feb072c4f8420 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java @@ -217,6 +217,15 @@ public abstract class Projectile extends Entity implements TraceableEntity { } else { 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; + } + } + // Paper end return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); } } diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java index a6638e626600e4304a973497a39e3fac52203b16..e68b7a1b03783e4f9de24c5ae8773fc359bd2d37 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -197,7 +197,8 @@ public class BlockItem extends Item { Player entityhuman = context.getPlayer(); CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(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 823121fdfe99db01e3e995a50dbc8e241bcebe9c..99bc511425cf079303716a5b12c913bc48ce775a 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -273,6 +273,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, net.minecraft.world.phys.shapes.CollisionContext voxelshapedcollision, + BlockPos position, boolean checkCanSee) { + // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) + net.minecraft.world.phys.shapes.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 (net.minecraft.world.phys.shapes.Shapes.joinIsNotEmpty(voxelshape, net.minecraft.world.phys.shapes.Shapes.create(entity.getBoundingBox()), net.minecraft.world.phys.shapes.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 116d3af618351cfec7dc172ba8e5170453b7226d..b77fefc9cf30fd438f557e5b56efb4c0251cb17a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1298,6 +1298,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; }