5959
6060public class CommonPlayerTickHandler {
6161
62- /**
63- * From {@link LivingEntity#calculateFallDamage(float, float)}, distance above this amount causes fall damage
64- */
65- private static final float MIN_FALL_HURT = 3.0F ;
66-
6762 public static boolean isOnGroundOrSleeping (Player player ) {
6863 return player .onGround () || player .isSleeping () || player .getAbilities ().flying ;
6964 }
@@ -215,13 +210,22 @@ public void onEntityAttacked(LivingIncomingDamageEvent event) {
215210 }
216211 }
217212
213+ /**
214+ * Based on the values and calculations that happen in {@link LivingEntity#calculateFallDamage(float, float)}
215+ */
218216 @ SubscribeEvent
219217 public void livingFall (LivingFallEvent event ) {
220- float fallDamage = Math .max (event .getDistance () - MIN_FALL_HURT , 0 );
221- if (fallDamage <= Mth .EPSILON ) {
218+ LivingEntity entity = event .getEntity ();
219+ float safeFallDistance = (float ) entity .getAttributeValue (Attributes .SAFE_FALL_DISTANCE );
220+ float fallDistance = Math .max (event .getDistance () - safeFallDistance , 0 );
221+ if (fallDistance <= Mth .EPSILON ) {
222+ return ;
223+ }
224+ double damageMultiplier = event .getDamageMultiplier () * entity .getAttributeValue (Attributes .FALL_DAMAGE_MULTIPLIER );
225+ int fallDamage = Mth .ceil (fallDistance * damageMultiplier );
226+ if (fallDamage <= 0 ) {//This may be the case for things like slime blocks that have a damage multiplier of zero
222227 return ;
223228 }
224- LivingEntity entity = event .getEntity ();
225229 FallEnergyInfo info = getFallAbsorptionEnergyInfo (entity );
226230 if (info != null && info .container != null ) {
227231 float absorption = info .damageRatio .getAsFloat ();
@@ -233,16 +237,25 @@ public void livingFall(LivingFallEvent event) {
233237 // or how small the amount to absorb is
234238 ratioAbsorbed = absorption ;
235239 } else {
236- ratioAbsorbed = absorption * info .container .extract (energyRequirement , Action .EXECUTE , AutomationType .MANUAL ).divide (amount ).floatValue ();
240+ FloatingLong extracted = info .container .extract (energyRequirement , Action .EXECUTE , AutomationType .MANUAL );
241+ ratioAbsorbed = absorption * extracted .divide (energyRequirement ).floatValue ();
237242 }
238243 if (ratioAbsorbed > 0 ) {
239244 float damageRemaining = fallDamage * Math .max (0 , 1 - ratioAbsorbed );
240245 if (damageRemaining <= Mth .EPSILON ) {
241246 event .setCanceled (true );
242- SoundType soundtype = entity .getBlockStateOn ().getSoundType (entity .level (), entity .getOnPos (), entity );
243- entity .playSound (soundtype .getStepSound (), soundtype .getVolume () * 0.15F , soundtype .getPitch ());
247+ BlockPos posOn = entity .getOnPos ();
248+ BlockState stateOn = entity .level ().getBlockState (posOn );
249+ if (entity instanceof Player player ) {
250+ player .playStepSound (posOn , stateOn );
251+ } else {
252+ //Fallback to default implementation
253+ SoundType soundtype = stateOn .getSoundType (entity .level (), posOn , entity );
254+ entity .playSound (soundtype .getStepSound (), soundtype .getVolume () * 0.15F , soundtype .getPitch ());
255+ }
244256 } else {
245- event .setDistance (damageRemaining + MIN_FALL_HURT );
257+ float distanceRemaining = (float ) (damageRemaining / damageMultiplier );
258+ event .setDistance (distanceRemaining + safeFallDistance );
246259 }
247260 }
248261 }
0 commit comments