Fixes instant killing of a player with an arrow
opened this issue · comments
package f3f5.bowbombpatch;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.SpectralArrow;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.plugin.java.JavaPlugin;
public final class BowBombPatch extends JavaPlugin implements Listener {
@eventhandler
public void onArrow(ProjectileLaunchEvent evt) {
if (evt.getEntity() instanceof Arrow || evt.getEntity() instanceof SpectralArrow) {
evt.setCancelled(true);
}
}
}
Additional context
Add any other context or screenshots about the feature request here.
This just.. disables using arrows?
This just.. disables using arrows?
yes((((((((((
Clamp the velocity
Can't we clamp the damage and velocity?
What causes this is the ability for a player to increase their server-side motX and motZ far beyond legitimate amounts by sprinting and then triggering the Spigot jump event over and over in the course of one tick.
This then gets added to the velocity of any projectiles thrown by they player when they are thrown.
A more effective way to patch this exploit would be to simply not add these motX and motZ values if the entity firing the projectile is a player.
A more effective way to patch this exploit would be to simply not add these motX and motZ values if the entity firing the projectile is a player.
Wouldn't this affect damage from sprint-jumping when firing an arrow? I know it's a small thing but that is vanilla behavior.
Simply clamping them at their theoretical "normal" maximums would be sufficient.
@5HT2 It seems that https://github.com/PaperMC/Paper/blob/7f3d2ff50330f6a703032cc8fe68cd05409d75b4/patches/server/0322-Configurable-projectile-relative-velocity.patch helps with the problem.
Also I heard that it was fixed in upstream paper from Wurst-Imperium/Wurst7@fd5915b.
public void onProjectileLaunch(ProjectileLaunchEvent event) {
if (event.getEntity().getShooter() instanceof CraftPlayer) {
Vector velocity = event.getEntity().getVelocity();
if (velocity.lengthSquared() > plugin.getConfig().getInt("BowExploit.maxBowSquaredVelocity", 15)) {
event.setCancelled(true);
Log.info("Cancelled high velocity " + event.getEntityType().name() + " of " + ((CraftPlayer) event.getEntity().getShooter()).getName() + ".", getClass(), false);
}
}
}
While this could easily be done with plugins, too, there are multiple problems:
P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity
from the projectile's velocity, the projectile's velocity would be different.
As there's no way to detect whether the projectile's velocity has already been
adjusted to ignore the player's velocity, plugins can't not do it if it's not
necessary.
P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while
using an elytra. Checking for those inconsistencies is possible, but not as
efficient as just not applying the velocity in the first place.
P3) Solutions for 1) and especially 2) might not be future-proof, while this
server-internal fix makes this change future-proof.
@5HT2 @RemainingToast I find that this is resolved in PaperMC/Paper@bb397ba, maybe it is these lines that solved the problem?
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 1018f4640bab5876c5e0afb5b88f71437fb79662..cbdff14b26f67b5040c13659f9d64d9ec4c7eaed 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -2571,15 +2571,27 @@ public abstract class LivingEntity extends Entity {
return this.hasEffect(MobEffects.JUMP) ? (double) (0.1F * (float) (this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D;
}
+ protected long lastJumpTime = 0L; // Paper - add critical damage API
protected void jumpFromGround() {
double d0 = (double) this.getJumpPower() + this.getJumpBoostPower();
Vec3 vec3d = this.getDeltaMovement();
+ // Paper start - add critical damage API
+ long time = System.nanoTime();
+ boolean canCrit = true;
+ if (this instanceof net.minecraft.world.entity.player.Player) {
+ canCrit = false;
+ if (time - this.lastJumpTime > (long)(0.250e9)) {
+ this.lastJumpTime = time;
+ canCrit = true;
+ }
+ }
+ // Paper end - add critical damage API
this.setDeltaMovement(vec3d.x, d0, vec3d.z);
if (this.isSprinting()) {
float f = this.getYRot() * 0.017453292F;
- this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F)));
+ if (canCrit) this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F))); // Paper - add critical damage API
}
this.hasImpulse = true;
Likely because the exploit is from spamming jump packets
using real system time
ew