diff --git a/paper-server/patches/sources/net/minecraft/world/damagesource/DamageSource.java.patch b/paper-server/patches/sources/net/minecraft/world/damagesource/DamageSource.java.patch index b7a60501b4..1cfa141a77 100644 --- a/paper-server/patches/sources/net/minecraft/world/damagesource/DamageSource.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/damagesource/DamageSource.java.patch @@ -121,3 +121,22 @@ public String toString() { return "DamageSource (" + this.type().msgId() + ")"; } +@@ -163,4 +276,18 @@ + public Holder typeHolder() { + return this.type; + } ++ ++ // Paper start - add critical damage API ++ private boolean critical; ++ public boolean isCritical() { ++ return this.critical; ++ } ++ public DamageSource critical() { ++ return this.critical(true); ++ } ++ public DamageSource critical(boolean critical) { ++ this.critical = critical; ++ return this; ++ } ++ // Paper end - add critical damage API + } diff --git a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch index 2863d42c46..77dab02fd7 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch @@ -338,15 +338,17 @@ flag1 = true; } else { flag1 = false; -@@ -1168,6 +1259,7 @@ +@@ -1168,7 +1259,9 @@ f += itemstack.getItem().getAttackDamageBonus(target, f, damagesource); boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity && !this.isSprinting(); + flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits if (flag2) { ++ damagesource = damagesource.critical(true); // Paper start - critical damage API f *= 1.5F; } -@@ -1202,13 +1294,17 @@ + +@@ -1202,13 +1295,17 @@ if (target instanceof LivingEntity) { LivingEntity entityliving1 = (LivingEntity) target; @@ -366,14 +368,14 @@ } LivingEntity entityliving2; -@@ -1223,8 +1319,13 @@ +@@ -1223,8 +1320,13 @@ if (entityliving2 != this && entityliving2 != target && !this.isAlliedTo((Entity) entityliving2) && (!(entityliving2 instanceof ArmorStand) || !((ArmorStand) entityliving2).isMarker()) && this.distanceToSqr((Entity) entityliving2) < 9.0D) { float f7 = this.getEnchantedDamage(entityliving2, f6, damagesource) * f2; - entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); - entityliving2.hurt(damagesource, f7); + // CraftBukkit start - Only apply knockback if the damage hits -+ if (!entityliving2.hurtServer((ServerLevel) this.level(), this.damageSources().playerAttack(this).sweep(), f7)) { ++ if (!entityliving2.hurtServer((ServerLevel) this.level(), this.damageSources().playerAttack(this).sweep().critical(flag2), f7)) { // Paper - add critical damage API + continue; + } + // CraftBukkit end @@ -382,7 +384,7 @@ Level world = this.level(); if (world instanceof ServerLevel) { -@@ -1235,26 +1336,43 @@ +@@ -1235,26 +1337,43 @@ } } @@ -430,7 +432,7 @@ } } -@@ -1308,9 +1426,14 @@ +@@ -1308,9 +1427,14 @@ } } @@ -447,7 +449,7 @@ } } -@@ -1351,7 +1474,14 @@ +@@ -1351,7 +1475,14 @@ @Override public void remove(Entity.RemovalReason reason) { @@ -463,7 +465,7 @@ this.inventoryMenu.removed(this); if (this.containerMenu != null && this.hasContainerOpen()) { this.doCloseContainer(); -@@ -1391,7 +1521,13 @@ +@@ -1391,7 +1522,13 @@ } public Either startSleepInBed(BlockPos pos) { @@ -478,7 +480,7 @@ this.sleepCounter = 0; return Either.right(Unit.INSTANCE); } -@@ -1545,12 +1681,24 @@ +@@ -1545,12 +1682,24 @@ } public void startFallFlying() { @@ -504,7 +506,7 @@ } @Override -@@ -1664,11 +1812,30 @@ +@@ -1664,11 +1813,30 @@ public int getXpNeededForNextLevel() { return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); } @@ -536,7 +538,7 @@ } } -@@ -1748,13 +1915,20 @@ +@@ -1748,13 +1916,20 @@ @Override public void setItemSlot(EquipmentSlot slot, ItemStack stack) { @@ -564,7 +566,7 @@ } } -@@ -1798,26 +1972,55 @@ +@@ -1798,26 +1973,55 @@ public void removeEntitiesOnShoulder() { if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { @@ -627,7 +629,7 @@ } @Override -@@ -2003,20 +2206,31 @@ +@@ -2003,20 +2207,31 @@ @Override public ImmutableList getDismountPoses() { return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); diff --git a/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch index dda4a1fe3c..b4f04e3bf6 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch @@ -49,7 +49,7 @@ + // CraftBukkit start - handle the owner before the rest of things + this(type, x, y, z, world, stack, weapon, null); + } -+ + + protected AbstractArrow(EntityType entitytypes, double d0, double d1, double d2, Level world, ItemStack itemstack, @Nullable ItemStack itemstack1, @Nullable LivingEntity ownerEntity) { + this(entitytypes, world); + this.setOwner(ownerEntity); @@ -57,7 +57,7 @@ + this.pickupItemStack = itemstack.copy(); + this.setCustomName((Component) itemstack.get(DataComponents.CUSTOM_NAME)); + Unit unit = (Unit) itemstack.remove(DataComponents.INTANGIBLE_PROJECTILE); - ++ if (unit != null) { this.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; } @@ -147,7 +147,12 @@ return; } -@@ -444,7 +469,13 @@ +@@ -440,11 +465,18 @@ + entityliving.setLastHurtMob(entity); + } + ++ if (this.isCritArrow()) damagesource = damagesource.critical(); // Paper - add critical damage API + boolean flag = entity.getType() == EntityType.ENDERMAN; int k = entity.getRemainingFireTicks(); if (this.isOnFire() && !flag) { @@ -162,7 +167,7 @@ } if (entity.hurtOrSimulate(damagesource, (float) i)) { -@@ -490,7 +521,7 @@ +@@ -490,7 +522,7 @@ this.playSound(this.soundEvent, 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F)); if (this.getPierceLevel() <= 0) { @@ -171,7 +176,7 @@ } } else { entity.setRemainingFireTicks(k); -@@ -506,7 +537,7 @@ +@@ -506,7 +538,7 @@ this.spawnAtLocation(worldserver2, this.getPickupItem(), 0.1F); } @@ -180,7 +185,7 @@ } } } -@@ -538,7 +569,7 @@ +@@ -538,7 +570,7 @@ Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale(d0 * 0.6D * d1); if (vec3d.lengthSqr() > 0.0D) { @@ -189,7 +194,7 @@ } } -@@ -675,7 +706,7 @@ +@@ -675,7 +707,7 @@ } if (nbt.contains("weapon", 10)) { @@ -198,7 +203,7 @@ } else { this.firedFromWeapon = null; } -@@ -688,34 +719,31 @@ +@@ -688,34 +720,31 @@ Entity entity1 = entity; byte b0 = 0; @@ -245,7 +250,7 @@ } this.pickup = entityarrow_pickupstatus; -@@ -724,9 +752,24 @@ +@@ -724,9 +753,24 @@ @Override public void playerTouch(Player player) { if (!this.level().isClientSide && (this.isInGround() || this.isNoPhysics()) && this.shakeTime <= 0) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index 24f8672401..a5285a8952 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1078,7 +1078,7 @@ public class CraftEventFactory { return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled); } DamageCause damageCause = (damager.getBukkitEntity() instanceof org.bukkit.entity.TNTPrimed) ? DamageCause.BLOCK_EXPLOSION : DamageCause.ENTITY_EXPLOSION; - return CraftEventFactory.callEntityDamageEvent(damager, entity, damageCause, bukkitDamageSource, modifiers, modifierFunctions, cancelled); + return CraftEventFactory.callEntityDamageEvent(damager, entity, damageCause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API } else if (damager != null || source.getDirectEntity() != null) { DamageCause cause = (source.isSweep()) ? DamageCause.ENTITY_SWEEP_ATTACK : DamageCause.ENTITY_ATTACK; @@ -1104,7 +1104,7 @@ public class CraftEventFactory { cause = DamageCause.MAGIC; } - return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled); + return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API } else if (source.is(DamageTypes.FELL_OUT_OF_WORLD)) { return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.VOID, bukkitDamageSource, modifiers, modifierFunctions, cancelled); } else if (source.is(DamageTypes.LAVA)) { @@ -1164,13 +1164,13 @@ public class CraftEventFactory { cause = DamageCause.CUSTOM; } - return CraftEventFactory.callEntityDamageEvent((Entity) null, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled); + return CraftEventFactory.callEntityDamageEvent((Entity) null, entity, cause, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API } - private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map modifiers, Map> modifierFunctions, boolean cancelled) { + private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, org.bukkit.damage.DamageSource bukkitDamageSource, Map modifiers, Map> modifierFunctions, boolean cancelled, boolean critical) { // Paper - add critical damage API EntityDamageEvent event; if (damager != null) { - event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions); + event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical); } else { event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions); }