DescentAnimationType enum

Пакет: com.hypixel.hytale.server.npc.movement.controllers

Файл: com/hypixel/hytale/server/npc/movement/controllers/MotionControllerWalk.java

implements: Supplier<String>

Поля (1)

МодификаторыТипИмя
private final String description

Методы (2)

МодификаторыВозвратСигнатура
abstract Idle Idle("Play idle animation")
public String getpublic String get()

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.npc.movement.controllers;

class="kw">import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.math.shape.Box;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.math.util.TrigMathUtil;
class="kw">import com.hypixel.hytale.math.vector.Rotation3f;
class="kw">import com.hypixel.hytale.math.vector.Vector3dUtil;
class="kw">import com.hypixel.hytale.protocol.BlockMaterial;
class="kw">import com.hypixel.hytale.protocol.MovementStates;
class="kw">import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
class="kw">import com.hypixel.hytale.server.core.asset.type.fluidfx.config.FluidFX;
class="kw">import com.hypixel.hytale.server.core.asset.type.model.config.Model;
class="kw">import com.hypixel.hytale.server.core.modules.blockset.BlockSetModule;
class="kw">import com.hypixel.hytale.server.core.modules.collision.BlockCollisionData;
class="kw">import com.hypixel.hytale.server.core.modules.collision.BoxBlockIntersectionEvaluator;
class="kw">import com.hypixel.hytale.server.core.modules.collision.CollisionConfig;
class="kw">import com.hypixel.hytale.server.core.modules.collision.CollisionMath;
class="kw">import com.hypixel.hytale.server.core.modules.collision.CollisionModule;
class="kw">import com.hypixel.hytale.server.core.modules.collision.CollisionResult;
class="kw">import com.hypixel.hytale.server.core.modules.collision.WorldUtil;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.PositionDataComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
class="kw">import com.hypixel.hytale.server.core.modules.physics.component.Velocity;
class="kw">import com.hypixel.hytale.server.core.modules.physics.util.PhysicsMath;
class="kw">import com.hypixel.hytale.server.core.modules.splitvelocity.VelocityConfig;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.util.FillerBlockUtil;
class="kw">import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
class="kw">import com.hypixel.hytale.server.npc.entities.NPCEntity;
class="kw">import com.hypixel.hytale.server.npc.movement.MotionKind;
class="kw">import com.hypixel.hytale.server.npc.movement.MovementMode;
class="kw">import com.hypixel.hytale.server.npc.movement.Steering;
class="kw">import com.hypixel.hytale.server.npc.movement.constraints.RelaxedConstraint;
class="kw">import com.hypixel.hytale.server.npc.movement.controllers.builders.BuilderMotionControllerWalk;
class="kw">import com.hypixel.hytale.server.npc.role.Role;
class="kw">import com.hypixel.hytale.server.npc.util.NPCPhysicsMath;
class="kw">import java.util.EnumSet;
class="kw">import java.util.Set;
class="kw">import java.util.function.IntPredicate;
class="kw">import java.util.function.Predicate;
class="kw">import java.util.function.Supplier;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector2d;
class="kw">import org.joml.Vector3d;
class="kw">import org.joml.Vector3dc;

class="kw">public class MotionControllerWalk class="kw">extends MotionControllerBase {
   class="kw">public class="kw">static class="kw">final String TYPE = "Walk";
   class="kw">public class="kw">static class="kw">final Set<MovementMode> SUPPORTED_MOVEMENT_MODES = Set.of(MovementMode.WALK, MovementMode.WADE, MovementMode.UNDERWATER_WALK);
   class="kw">public class="kw">static class="kw">final double CLIMB_FORWARD_DISTANCE = 0.1;
   class="kw">public class="kw">static class="kw">final double CLIMB_FORWARD_DISTANCE_SQUARED = 0.010000000000000002;
   class="kw">public class="kw">static class="kw">final double JUMP_FORWARD_DISTANCE = 0.5;
   class="kw">public class="kw">static class="kw">final double ONE_PLUS_THRESHOLD = 1.00001;
   class="kw">public class="kw">static class="kw">final double MIN_SAFETY_DISTANCE = 0.05;
   class="kw">public class="kw">static class="kw">final double EDGE_MARGIN_BBOX_FACTOR = 0.1;
   class="kw">public class="kw">static class="kw">final double MIN_SEPARATION_STEERING = 1.0E-5;
   class="kw">protected class="kw">static class="kw">final EnumSet<MotionKind> STATE_CAN_HOVER = EnumSet.of(MotionKind.MOVING, MotionKind.STANDING);
   class="kw">protected class="kw">static class="kw">final EnumSet<MotionKind> VALID_MOTIONS = EnumSet.of(
      MotionKind.ASCENDING, MotionKind.DESCENDING, MotionKind.DROPPING, MotionKind.STANDING, MotionKind.MOVING
   );
   class="kw">protected class="kw">static class="kw">final int COLLISION_MATERIALS = 4;
   class="kw">protected class="kw">static class="kw">final int WALKING_MATERIALS = 5;
   class="kw">protected class="kw">static class="kw">final int WALKING_MATERIALS_RELAXED = 13;
   class="kw">protected class="kw">final double minHorizontalSpeed;
   class="kw">protected class="kw">final double maxVerticalSpeed;
   class="kw">protected class="kw">final double maxVerticalSpeedFluid;
   class="kw">protected class="kw">final double acceleration;
   class="kw">protected class="kw">final double maxRotationSpeed;
   class="kw">protected class="kw">final float maxMoveTurnAngle;
   class="kw">protected class="kw">final float blendRestTurnAngle;
   class="kw">protected class="kw">final double blendRestRelativeSpeed;
   class="kw">protected class="kw">final double maxClimbHeight;
   class="kw">protected class="kw">final double jumpHeight;
   class="kw">protected class="kw">final double minJumpHeight;
   class="kw">protected class="kw">final double minJumpDistance;
   class="kw">protected class="kw">final double jumpForce;
   class="kw">protected class="kw">final double jumpDescentSteepness;
   class="kw">protected class="kw">final double jumpBlending;
   class="kw">protected class="kw">final double jumpDescentBlending;
   class="kw">protected class="kw">final double climbSpeedMult;
   class="kw">protected class="kw">final double climbSpeedPow;
   class="kw">protected class="kw">final double climbSpeedConst;
   class="kw">protected class="kw">final double maxDropHeight;
   class="kw">protected class="kw">final double maxDropHeightRelaxed;
   class="kw">protected class="kw">final double minDescentAnimationHeight;
   class="kw">protected class="kw">final double descendFlatness;
   class="kw">protected class="kw">final double descendSpeedCompensation;
   class="kw">protected class="kw">final double descentSteepness;
   class="kw">protected class="kw">final double descentBlending;
   class="kw">protected class="kw">final MotionControllerWalk.DescentAnimationType descentAnimationType;
   class="kw">protected class="kw">final MotionControllerWalk.AscentAnimationType ascentAnimationType;
   class="kw">protected class="kw">final double maxWalkSpeedAfterHitMultiplier;
   class="kw">protected class="kw">final int fenceBlockSet;
   class="kw">protected class="kw">final double minHover;
   class="kw">protected class="kw">final double maxHover;
   class="kw">protected class="kw">final double hoverFreq;
   class="kw">protected class="kw">final float hoverCycle;
   class="kw">protected class="kw">final double minHoverClimb;
   class="kw">protected class="kw">final double minHoverDrop;
   class="kw">protected class="kw">final boolean floatsDown;
   class="kw">protected boolean onGround;
   class="kw">protected boolean inWater;
   class="kw">protected double horizontalSpeedMultiplier;
   class="kw">protected double fallStartHeight;
   class="kw">protected double fallSpeed;
   class="kw">protected double currentRelativeSpeed;
   class="kw">protected boolean isFullyRotated = true;
   @Nullable
   class="kw">protected BlockType belowBlockType;
   class="kw">protected int belowBlockTypeId = 0;
   class="kw">protected int[] footingBlocks;
   class="kw">protected short[] footingFillers;
   class="kw">protected byte[] footingRotations;
   class="kw">protected class="kw">final Vector3d footingPosition = new Vector3d();
   class="kw">protected boolean footingBlocksValid;
   class="kw">protected double breathingDepth;
   class="kw">protected double constraintDepth;
   class="kw">protected double climbUpDistance;
   class="kw">protected double currentJumpHeight;
   class="kw">protected double jumpDropHeight;
   class="kw">protected double jumpBlockHeight;
   class="kw">protected double predictedFallHeight;
   class="kw">protected class="kw">final Vector3d jumpDropDirection = new Vector3d();
   class="kw">protected class="kw">final Vector3d climbUpDirection = new Vector3d();
   class="kw">protected double currentClimbForwardDistance;
   class="kw">protected double maxClimbForwardDistance;
   class="kw">protected double totalDropDistance;
   class="kw">protected class="kw">final Vector3d climbForwardDirection = new Vector3d();
   class="kw">protected double climbSpeed;
   class="kw">protected boolean jumping;
   class="kw">protected class="kw">final MotionController.VerticalRange verticalRange = new MotionController.VerticalRange();
   class="kw">protected class="kw">final Vector3d tmpClimbPosition = new Vector3d();
   class="kw">protected class="kw">final Vector3d tmpClimbMovement = new Vector3d();
   class="kw">protected class="kw">final Vector3d tmpMovePosition = new Vector3d();
   class="kw">protected class="kw">final CollisionResult tmpResults = new CollisionResult();
   class="kw">protected class="kw">final Vector2d tmpClimbHeightResults = new Vector2d();
   @Nullable
   class="kw">private Predicate<CollisionConfig> activeProbeBlockCollisionFilter;
   @Nullable
   class="kw">private IntPredicate activeProbeBreathableBlockOverride;
   class="kw">private class="kw">final EnumSet<RelaxedConstraint> effectiveMoveConstraints = EnumSet.noneOf(RelaxedConstraint.class);

   class="kw">public MotionControllerWalk(@Nonnull BuilderMotionControllerWalk var1, @Nonnull BuilderSupport var2) {
      super(var2, var1);
      this.setGravity(var1.getGravity());
      this.minHorizontalSpeed = var1.getMinHorizontalSpeed();
      this.maxVerticalSpeed = var1.getMaxVerticalSpeed();
      this.maxVerticalSpeedFluid = var1.getMaxVerticalSpeedFluid();
      this.acceleration = var1.getAcceleration(var2);
      this.maxRotationSpeed = var1.getMaxRotationSpeed(var2);
      this.maxMoveTurnAngle = var1.getMaxMoveTurnAngle(var2);
      this.blendRestTurnAngle = var1.getBlendRestTurnAngle(var2);
      this.blendRestRelativeSpeed = var1.getBlendRestRelativeSpeed(var2);
      this.maxClimbHeight = var1.getMaxClimbHeight(var2);
      this.jumpHeight = var1.getJumpHeight(var2);
      this.minJumpHeight = var1.getMinJumpHeight(var2);
      this.minJumpDistance = var1.getMinJumpDistance(var2);
      this.jumpForce = var1.getJumpForce(var2);
      this.jumpDescentSteepness = var1.getJumpDescentSteepness(var2);
      this.jumpBlending = var1.getJumpBlending(var2);
      this.jumpDescentBlending = var1.getJumpDescentBlending(var2);
      this.ascentAnimationType = var1.getAscentAnimationType(var2);
      this.climbSpeedMult = var1.getClimbSpeedMult(var2);
      this.climbSpeedPow = var1.getClimbSpeedPow(var2);
      this.climbSpeedConst = var1.getClimbSpeedConst(var2);
      this.minDescentAnimationHeight = var1.getMinDescentAnimationHeight(var2);
      this.descendFlatness = var1.getDescendForwardAmount(var2);
      this.descendSpeedCompensation = var1.getDescendSpeedCompensation(var2);
      this.maxDropHeight = var1.getMaxDropHeight(var2);
      this.maxDropHeightRelaxed = this.maxDropHeight + var1.getMaxDropHeightRelaxedAdjustment(var2);
      this.fenceBlockSet = var1.getFenceBlockSet();
      this.minHover = var1.getMinHover();
      this.maxHover = var1.getMaxHover();
      this.minHoverClimb = var1.getMinHoverClimb();
      this.minHoverDrop = var1.getMinHoverDrop();
      this.floatsDown = var1.isFloatsDown();
      this.hoverFreq = var1.getHoverFreq();
      this.hoverCycle = this.hoverFreq > 0.0 ? 1.0F / (float)this.hoverFreq : 0.0F;
      this.maxWalkSpeedAfterHitMultiplier = var1.getMaxWalkSpeedAfterHitMultiplier();
      this.descentAnimationType = var1.getDescentAnimationType(var2);
      this.descentSteepness = var1.getDescentSteepness(var2);
      this.descentBlending = var1.getDescentBlending(var2);
   }

   @Nonnull
   @Override
   class="kw">public String getType() {
      class="kw">return "Walk";
   }

   @Nonnull
   @Override
   class="kw">public Set<MovementMode> getSupportedMovementModes() {
      class="kw">return SUPPORTED_MOVEMENT_MODES;
   }

   @Nonnull
   @Override
   class="kw">public Set<MovementMode> getDefaultSpawnMovementModes() {
      assert this.role != null;
      if (this.role.isBreathesInAir()) {
         class="kw">return Set.of(MovementMode.WALK);
      }

      assert this.role.isBreathesInWater();
      class="kw">return Set.of(MovementMode.UNDERWATER_WALK);
   }

   @Override
   class="kw">public void spawned() {
      this.position.y = this.position.y + this.minHover;
   }

   @Override
   class="kw">public double getWanderVerticalMovementRatio() {
      class="kw">return 0.0;
   }

   @Nonnull
   @Override
   class="kw">public MotionController.VerticalRange getDesiredVerticalRange(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      TransformComponent var3 = var2.getComponent(var1, TransformComponent.getComponentType());
      assert var3 != null;
      this.verticalRange.set(var3.getPosition().y(), 0.0, 320.0);
      class="kw">return this.verticalRange;
   }

   @Override
   class="kw">protected void adjustReadPosition(Ref<EntityStore> var1, ComponentAccessor<EntityStore> var2) {
      NPCEntity var3 = var2.getComponent(var1, NPCEntity.getComponentType());
      assert var3 != null;
      this.position.y = this.position.y - var3.getHoverHeight();
   }

   @Override
   class="kw">protected void adjustWritePosition(Ref<EntityStore> var1, double var2, @Nonnull ComponentAccessor<EntityStore> var4) {
      NPCEntity var5 = var4.getComponent(var1, NPCEntity.getComponentType());
      assert var5 != null;
      if (this.maxHover > 0.0 && this.hoverCycle > 0.0F && var2 > 0.0) {
         double var6 = var5.getHoverHeight();
         float var8 = var5.getHoverPhase();
         if (this.switchedToMotionKind(MotionKind.DROPPING) || this.switchedToMotionKind(MotionKind.DESCENDING)) {
            double var14 = this.maxHover - var6;
            double var15 = this.dropDistance(this.position, var14, var4);
            if (var15 < var14) {
               var14 = var15;
            } else {
               var8 = this.hoverCycle / 2.0F;
            }

            var6 += var14;
            this.position.y -= var14;
         } else if (this.switchedToMotionKind(MotionKind.ASCENDING)) {
            double var9 = var6 - this.minHoverClimb;
            if (var9 > this.climbUpDistance) {
               var9 = this.climbUpDistance;
            } else {
               var8 = 0.0F;
            }

            var6 -= var9;
            this.position.y += var9;
            this.climbUpDistance -= var9;
         } else if (var6 < this.minHover) {
            var6 += var2 * this.computeClimbSpeed(this.moveSpeed);
            if (var6 >= this.minHover) {
               var6 = this.minHover;
               var8 = 0.0F;
            }
         } else if (STATE_CAN_HOVER.contains(this.getMotionKind())) {
            var8 = (var8 + (float)var2) % this.hoverCycle;
            double var13 = (float) (Math.PI * 2) / this.hoverCycle;
            double var11 = TrigMathUtil.cos(var13 * var8 - (float) (Math.PI / 2)) * var13;
            var6 += var2 * var11 * (this.maxHover - this.minHover) / 2.0;
            if (var6 <= this.minHover) {
               var6 = this.minHover;
               var8 = 0.0F;
            } else if (var6 >= this.maxHover) {
               var6 = this.maxHover;
               var8 = this.hoverCycle / 2.0F;
            }
         }

         var5.setHoverPhase(var8);
         var5.setHoverHeight(var6);
      }

      this.position.y = this.position.y + var5.getHoverHeight();
   }

   @Override
   class="kw">protected void updateAscendingStates(
      @Nonnull Ref<EntityStore> var1, @Nonnull MovementStates var2, boolean var3, boolean var4, @Nonnull ComponentAccessor<EntityStore> var5
   ) {
      if (!this.jumping) {
         class="kw">switch (this.ascentAnimationType) {
            case Walk:
               var2.jumping = false;
               var2.idle = false;
               var2.flying = false;
               break;
            case Jump:
               var2.jumping = true;
               var2.idle = false;
               var2.flying = false;
               break;
            case Climb:
               var2.jumping = false;
               var2.idle = false;
               var2.flying = false;
               var2.climbing = true;
               break;
            case Fly:
               var2.jumping = false;
               var2.idle = false;
               var2.flying = true;
               break;
            case Idle:
               var2.jumping = false;
               var2.idle = true;
               var2.flying = false;
         }
      } else {
         NPCEntity var6 = var5.getComponent(var1, NPCEntity.getComponentType());
         assert var6 != null;
         var2.jumping = this.jumping;
         var2.idle = false;
         var2.flying = var6.getHoverHeight() > 0.0;
      }

      var2.horizontalIdle = var4;
      var2.falling = false;
      var2.running = var3;
      var2.walking = !var3;
      var2.sprinting = false;
      var2.swimming = false;
   }

   @Override
   class="kw">protected void updateDescendingStates(
      @Nonnull Ref<EntityStore> var1, @Nonnull MovementStates var2, boolean var3, boolean var4, @Nonnull ComponentAccessor<EntityStore> var5
   ) {
      if (this.predictedFallHeight >= this.minDescentAnimationHeight - 1.0E-5) {
         class="kw">switch (this.descentAnimationType) {
            case Walk:
               var2.falling = false;
               var2.idle = false;
               var2.running = var3;
               var2.walking = !var3;
               var2.flying = var4;
               break;
            case Fall:
               var2.falling = true;
               var2.idle = false;
               var2.running = false;
               var2.walking = false;
               var2.flying = false;
               break;
            case Idle:
               var2.falling = false;
               var2.idle = true;
               var2.running = false;
               var2.walking = false;
               var2.flying = var4;
         }
      } else {
         var2.falling = false;
         var2.idle = false;
         var2.running = var3;
         var2.walking = !var3;
         var2.flying = var4;
      }

      var2.horizontalIdle = false;
      var2.swimming = false;
      var2.jumping = false;
      var2.sprinting = false;
   }

   @Override
   class="kw">public boolean isFastMotionKind(double var1) {
      boolean var3 = this.fastMotionKind;
      if (this.jumping && this.getMotionKind() == MotionKind.ASCENDING) {
         class="kw">return var3;
      }

      double var4;
      if (var3) {
         var4 = this.fastMotionThreshold - this.fastMotionThresholdRange;
      } else {
         var4 = this.fastMotionThreshold + this.fastMotionThresholdRange;
      }

      var4 *= this.maxHorizontalSpeed;
      class="kw">return var1 > var4;
   }

   @Override
   class="kw">public boolean isInProgress() {
      MotionKind var1 = this.getMotionKind();
      class="kw">return var1 == MotionKind.ASCENDING || var1 == MotionKind.DESCENDING || var1 == MotionKind.DROPPING;
   }

   class="kw">private boolean isOnSolidGround() {
      class="kw">return this.onGround && this.belowBlockType != null && this.belowBlockType.getMaterial() == BlockMaterial.Solid;
   }

   @Override
   class="kw">public boolean canSteer(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      class="kw">return super.canSteer(var1, var2) && this.isOnSolidGround();
   }

   @Nullable
   @Override
   class="kw">public String canSteerFailReason(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      String var3 = super.canSteerFailReason(var1, var2);
      if (var3 != null) {
         class="kw">return var3;
      } else if (!this.onGround) {
         class="kw">return "OFF_GROUND";
      } else if (this.belowBlockType == null) {
         class="kw">return "NO_BLOCK_BELOW";
      } else {
         class="kw">return this.belowBlockType.getMaterial() != BlockMaterial.Solid ? "NO_SOLID_BLOCK_BELOW" : null;
      }
   }

   @Override
   class="kw">public void updateModelParameters(Ref<EntityStore> var1, Model var2, @Nonnull Box var3, ComponentAccessor<EntityStore> var4) {
      super.updateModelParameters(var1, var2, var3, var4);
      float var5 = var2 != null ? var2.getEyeHeight(var1, var4) : 0.0F;
      this.collisionBoundingBox.max.y = this.collisionBoundingBox.max.y + this.maxHover;
      this.breathingDepth = 1.0E-5 + var5;
      if (this.role.isBreathesInAir() && this.role.isBreathesInWater()) {
         this.constraintDepth = this.breathingDepth;
      } else if (this.role.isBreathesInAir()) {
         this.constraintDepth = Math.min(0.25, this.breathingDepth / 2.0);
      } else {
         this.constraintDepth = 1.0E-5;
      }

      int var6 = (int)(MathUtil.fastCeil(this.collisionBoundingBox.width() + 1.0) * MathUtil.fastCeil(this.collisionBoundingBox.depth() + 1.0));
      this.footingBlocks = new int[var6];
      this.footingFillers = new short[var6];
      this.footingRotations = new byte[var6];
      this.footingBlocksValid = false;
   }

   @Override
   class="kw">public void constrainRotations(Role var1, @Nonnull TransformComponent var2) {
      Rotation3f var3 = var2.getRotation();
      var3.setPitch(0.0F);
      var3.setRoll(0.0F);
   }

   @Override
   class="kw">public void setVelocity(@Nonnull Vector3dc var1, VelocityConfig var2, boolean var3) {
      super.setVelocity(var1, var2, var3);
      this.onGround = false;
   }

   @Override
   class="kw">public boolean inAir() {
      class="kw">return !this.onGround && !this.inWater;
   }

   @Override
   class="kw">public boolean onGround() {
      class="kw">return this.onGround;
   }

   @Override
   class="kw">public boolean standingOnBlockOfType(int var1) {
      class="kw">return BlockSetModule.getInstance().blockInSet(var1, this.belowBlockType);
   }

   @Override
   class="kw">public boolean inWater() {
      class="kw">return this.inWater;
   }

   @Override
   class="kw">public boolean touchesWater(boolean var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      class="kw">return this.inWater;
   }

   @Override
   class="kw">public double getCurrentSpeed() {
      class="kw">return this.moveSpeed;
   }

   @Override
   class="kw">public double getCurrentTurnRadius() {
      class="kw">return 0.0;
   }

   @Override
   class="kw">public float getMaxClimbAngle() {
      class="kw">return 0.0F;
   }

   @Override
   class="kw">public float getMaxSinkAngle() {
      class="kw">return 0.0F;
   }

   @Override
   class="kw">public double getMaxClimbHeight() {
      class="kw">return this.maxClimbHeight;
   }

   @Override
   class="kw">public double getMaxDropHeight() {
      class="kw">return this.maxDropHeight;
   }

   @Override
   class="kw">public double getMaximumSpeed() {
      class="kw">return this.maxHorizontalSpeed * this.horizontalSpeedMultiplier * this.effectHorizontalSpeedMultiplier;
   }

   @Override
   class="kw">public boolean is2D() {
      class="kw">return true;
   }

   @Override
   class="kw">public boolean canRestAtPlace() {
      class="kw">return true;
   }

   @Override
   class="kw">public double getDesiredAltitudeWeight() {
      class="kw">return 0.0;
   }

   @Override
   class="kw">public double getHeightOverGround() {
      class="kw">return 0.0;
   }

   @Override
   class="kw">public boolean estimateVelocity(@Nonnull Steering var1, @Nonnull Vector3d var2) {
      if (var1.hasTranslation()) {
         var2.set(var1.getTranslation()).mul(this.getCurrentSpeed());
         class="kw">return true;
      } else {
         var2.zero();
         class="kw">return false;
      }
   }

   @Override
   class="kw">public void setMotionKind(MotionKind var1) {
      if (!VALID_MOTIONS.contains(var1)) {
         var1 = MotionKind.STANDING;
      }

      super.setMotionKind(var1);
   }

   @Override
   class="kw">public void postReadPosition(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      if (!this.footingPosition.equals(this.position)) {
         this.footingBlocksValid = false;
         this.footingPosition.set(this.position);
      }

      World var3 = var2.getExternalData().getWorld();
      boolean var4 = this.onGround;
      double var5 = this.position.y + this.collisionBoundingBox.min.y;
      int var7 = MathUtil.floor(var5);
      if (var5 - var7 < 1.0E-5) {
         var7--;
      }

      if (var7 >= 0 && var7 <= 319) {
         double var8 = this.position.x > 0.0 ? this.position.x + MathUtil.EPSILON_DOUBLE : this.position.x - MathUtil.EPSILON_DOUBLE;
         double var10 = this.position.z > 0.0 ? this.position.z + MathUtil.EPSILON_DOUBLE : this.position.z - MathUtil.EPSILON_DOUBLE;
         long var12 = MathUtil.fastFloor(var8 + this.collisionBoundingBox.min.x);
         long var14 = MathUtil.fastFloor(var8 + this.collisionBoundingBox.max.x);
         long var16 = MathUtil.fastFloor(var10 + this.collisionBoundingBox.min.z);
         long var18 = MathUtil.fastFloor(var10 + this.collisionBoundingBox.max.z);
         int var20 = ChunkUtil.chunkCoordinate(var12);
         int var21 = ChunkUtil.chunkCoordinate(var14);
         int var22 = ChunkUtil.chunkCoordinate(var16);
         int var23 = ChunkUtil.chunkCoordinate(var18);
         boolean var24 = !this.footingBlocksValid;
         int var25 = 0;
         this.footingBlocksValid = true;
         ChunkStore var26 = var3.getChunkStore();
         Store var27 = var26.getStore();

         label279:
         for (int var28 = var20; var28 <= var21; var28++) {
            for (int var29 = var22; var29 <= var23; var29++) {
               Ref var30 = var26.getChunkReference(ChunkUtil.indexChunk(var28, var29));
               BlockChunk var31 = var30 != null && var30.isValid() ? var27.getComponent(var30, BlockChunk.getComponentType()) : null;
               if (var31 == null) {
                  this.footingBlocksValid = false;
                  this.belowBlockType = null;
                  this.belowBlockTypeId = 0;
                  this.onGround = false;
                  break label279;
               }

               int var32 = var28 == var20 ? ChunkUtil.localCoordinate(var12) : 0;
               int var33 = var28 == var21 ? ChunkUtil.localCoordinate(var14) : 31;
               int var34 = var29 == var22 ? ChunkUtil.localCoordinate(var16) : 0;
               int var35 = var29 == var23 ? ChunkUtil.localCoordinate(var18) : 31;
               BlockSection var36 = var31.getSectionAtBlockY(var7);

               for (int var37 = var32; var37 <= var33; var37++) {
                  for (int var38 = var34; var38 <= var35; var38++) {
                     int var39 = var36.get(var37, var7, var38);
                     if (var24 || var39 != this.footingBlocks[var25]) {
                        this.footingBlocks[var25] = var39;
                        this.footingFillers[var25] = (short)var36.getFiller(var37, var7, var38);
                        this.footingRotations[var25] = (byte)var36.getRotationIndex(var37, var7, var38);
                        var24 = true;
                     }

                     var25++;
                  }
               }
            }
         }

         if (var24 && this.footingBlocksValid) {
            this.belowBlockType = null;
            this.onGround = false;
            this.belowBlockTypeId = 0;
            BoxBlockIntersectionEvaluator var66 = this.collisionResult.getBoxBlockIntersection();
            var66.setBox(this.collisionBoundingBox, this.footingPosition);
            Vector3dc var67 = var66.getWorldUp();
            int var68;
            if (var67.y() != 0.0) {
               var68 = 40;
            } else if (var67.x() != 0.0) {
               var68 = 48;
            } else {
               var68 = 24;
            }

            var25 = 0;

            label241:
            for (int var69 = var20; var69 <= var21; var69++) {
               int var70 = ChunkUtil.minBlock(var69);

               for (int var71 = var22; var71 <= var23; var71++) {
                  int var72 = ChunkUtil.minBlock(var71);
                  int var73 = var69 == var20 ? ChunkUtil.localCoordinate(var12) : 0;
                  int var74 = var69 == var21 ? ChunkUtil.localCoordinate(var14) : 31;
                  int var75 = var71 == var22 ? ChunkUtil.localCoordinate(var16) : 0;
                  int var76 = var71 == var23 ? ChunkUtil.localCoordinate(var18) : 31;

                  for (int var77 = var73; var77 <= var74; var77++) {
                     for (int var40 = var75; var40 <= var76; var40++) {
                        int var41 = this.footingRotations[var25];
                        int var42 = this.footingFillers[var25];
                        int var43 = this.footingBlocks[var25++];
                        if (var43 != 0) {
                           BlockType var44 = BlockType.getAssetMap().getAsset(var43);
                           int var45 = var70 + var77;
                           int var46 = var72 + var40;
                           int var47 = var7;
                           if (var42 != 0) {
                              var45 -= FillerBlockUtil.unpackX(var42);
                              var47 -= FillerBlockUtil.unpackY(var42);
                              var46 -= FillerBlockUtil.unpackZ(var42);
                           }

                           BlockMaterial var48 = var44.getMaterial();
                           if (var48 == BlockMaterial.Solid) {
                              BlockBoundingBoxes var49 = BlockBoundingBoxes.getAssetMap().getAsset(var44.getHitboxTypeIndex());
                              BlockBoundingBoxes.RotatedVariantBoxes var50 = var49.get(var41);
                              int var51 = var66.intersectBoxComputeOnGround(var50.getBoundingBox(), var45, var47, var46);
                              if (!CollisionMath.isDisjoint(var51)) {
                                 if (var50.hasDetailBoxes()) {
                                    for (Box var55 : var50.getDetailBoxes()) {
                                       var51 = var66.intersectBoxComputeOnGround(var55, var45, var47, var46);
                                       if (var66.isOnGround() && (var51 & var68) == var68) {
                                          this.belowBlockType = var44;
                                          this.belowBlockTypeId = var43;
                                          this.onGround = true;
                                          break label241;
                                       }
                                    }
                                 } else if (var66.isOnGround() && (var51 & var68) == var68) {
                                    this.belowBlockType = var44;
                                    this.belowBlockTypeId = var43;
                                    this.onGround = true;
                                    break label241;
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      } else {
         this.footingBlocksValid = false;
         this.belowBlockType = null;
         this.belowBlockTypeId = 0;
         this.onGround = false;
      }

      if (this.shouldDebugMove(this.translation) && var4 != this.onGround) {
         LOGGER.at(Level.INFO).log("eid=%d PostReadPosition: OnGround was changed from %s to %s", this.debugEntityId, var4, this.onGround);
      }

      int var56 = MathUtil.floor(this.position.x);
      int var9 = MathUtil.floor(this.position.y + this.collisionBoundingBox.min.y);
      int var57 = MathUtil.floor(this.position.z);
      TransformComponent var11 = var2.getComponent(var1, TransformComponent.getComponentType());
      assert var11 != null;
      Ref var13 = var11.getSectionRef();
      Fluid var58;
      if (var13 != null && var13.isValid()) {
         Store var59 = var3.getChunkStore().getStore();
         FluidSection var15 = var59.getComponent(var13, FluidSection.getComponentType());
         assert var15 != null;
         var58 = Fluid.getAssetMap().getAsset(var15.getFluidId(var56, var9, var57));
      } else {
         var58 = null;
      }

      this.inWater = var58 != null && !var58.equals(Fluid.EMPTY);
      this.horizontalSpeedMultiplier = 1.0;
      if (this.inWater) {
         int var60 = var58.getFluidFXIndex();
         if (var60 != 0) {
            FluidFX var62 = FluidFX.getAssetMap().getAsset(var60);
            this.horizontalSpeedMultiplier = var62 != null && var62.getMovementSettings() != null ? var62.getMovementSettings().horizontalSpeedMultiplier : 1.0;
         }
      }

      if (var13 != null && var13.isValid()) {
         PositionDataComponent var61 = var2.getComponent(var1, PositionDataComponent.getComponentType());
         assert var61 != null;
         Store var63 = var3.getChunkStore().getStore();
         BlockSection var64 = var63.getComponent(var13, BlockSection.getComponentType());
         assert var64 != null;
         var61.setInsideBlockTypeId(var64.get(var56, var9, var57));
         var61.setStandingOnBlockTypeId(this.belowBlockTypeId);
      }
   }

   @Override
   class="kw">public boolean translateToAccessiblePosition(@Nonnull Vector3d var1, @Nullable Box var2, double var3, double var5, ComponentAccessor<EntityStore> var7) {
      if (var5 < var3) {
         class="kw">return false;
      }

      if (var3 < 0.0) {
         var3 = 0.0;
      }

      if (var5 > 320.0) {
         var5 = 320.0;
      }

      if (var2 == null) {
         class="kw">return translateToAccessiblePosition(var1, var3, var5, var7) > 0;
      }

      int var8 = MathUtil.floor(var2.min.x + var1.x);
      int var9 = MathUtil.floor(var2.max.x + var1.x);
      int var10 = MathUtil.floor(var2.min.z + var1.z);
      int var11 = MathUtil.floor(var2.max.z + var1.z);
      double var12 = var1.y;
      double var14 = var1.y + var2.min.y;
      double var16 = -1.0;
      if (var9 - var8 > 2 || var11 - var10 > 2) {
         var1.y = var14;
         int var18 = translateToAccessiblePosition(var1, var3, var5, var7);
         if (var18 < 0) {
            var1.y = var12;
            class="kw">return false;
         }

         if (var18 > 0 && var1.y > var16) {
            var16 = var1.y;
            var3 = var16;
            if (var16 > var14) {
               var14 = var16;
            }
         }
      }

      for (int var19 = var8; var19 <= var9; var19++) {
         for (int var20 = var10; var20 <= var11; var20++) {
            var1.y = var14;
            int var21 = translateToAccessiblePosition(var1, var3, var5, var7);
            if (var21 < 0) {
               var1.y = var12;
               class="kw">return false;
            }

            if (var21 > 0 && var1.y > var16) {
               var16 = var1.y;
               var3 = var16;
               if (var16 > var14) {
                  var14 = var16;
               }
            }
         }
      }

      if (var16 < 0.0) {
         var1.y = var12;
         class="kw">return false;
      } else {
         var1.y = var16 - var2.min.y;
         class="kw">return true;
      }
   }

   class="kw">public class="kw">static int translateToAccessiblePosition(@Nonnull Vector3d var0, double var1, double var3, @Nonnull ComponentAccessor<EntityStore> var5) {
      if (var0.y() < 0.0) {
         class="kw">return -1;
      }

      World var6 = var5.getExternalData().getWorld();
      long var7 = ChunkUtil.indexChunkFromBlock(var0.x(), var0.z());
      ChunkStore var9 = var6.getChunkStore();
      Ref var10 = var9.getChunkReference(var7);
      if (var10 != null && var10.isValid()) {
         Store var11 = var9.getStore();
         WorldChunk var12 = var11.getComponent(var10, WorldChunk.getComponentType());
         if (var12 == null) {
            class="kw">return -1;
         }

         BlockChunk var13 = var11.getComponent(var10, BlockChunk.getComponentType());
         if (var13 == null) {
            class="kw">return -1;
         }

         BlockTypeAssetMap var14 = BlockType.getAssetMap();
         int var15 = MathUtil.floor(var0.x());
         int var16 = MathUtil.floor(var0.y());
         int var17 = MathUtil.floor(var0.z());
         if (var16 < 320) {
            int var18 = var13.getBlock(var15, var16, var17);
            if (var18 != 0) {
               BlockType var19 = var14.getAsset(var18);
               int var20 = var12.getFiller(var15, var16, var17);
               boolean var21 = var20 != 0;
               if (var21 || var19.getMaterial() == BlockMaterial.Solid) {
                  int var22;
                  for (var22 = MathUtil.ceil(var3); var16 < var22; var16++) {
                     var18 = var13.getBlock(var15, var16, var17);
                     if (var18 == 0) {
                        break;
                     }

                     var19 = var14.getAsset(var18);
                     var20 = var12.getFiller(var15, var16, var17);
                     if (var19.getMaterial() != BlockMaterial.Solid) {
                        break;
                     }
                  }

                  if (var16 == var22) {
                     class="kw">return 0;
                  }

                  var19 = var12.getBlockType(var15, --var16, var17);
                  int var23 = var12.getRotationIndex(var15, var16, var17);
                  BlockBoundingBoxes var26 = BlockBoundingBoxes.getAssetMap().getAsset(var19.getHitboxTypeIndex());
                  BlockBoundingBoxes.RotatedVariantBoxes var27 = var26.get(var23);
                  double var24;
                  if (var20 != 0) {
                     var24 = var16 - FillerBlockUtil.unpackY(var20) + var27.getBoundingBox().max.y;
                  } else {
                     var24 = var16 + var27.getBoundingBox().max.y;
                  }

                  if (var24 > var3) {
                     class="kw">return 0;
                  }

                  var0.y = var24;
                  class="kw">return 1;
               }
            }
         } else {
            var16 = 319;
         }

         int var31 = ChunkUtil.indexSection(var16);

         while (var31 >= 0) {
            BlockSection var34 = var13.getSectionAtIndex(var31);
            if (var34.isSolidAir()) {
               var16 = 32 * var31 - 1;
               if (var16 < var1) {
                  class="kw">return 0;
               }

               var31--;
            } else {
               int var35 = 32 * var31--;

               while (var16 >= var35) {
                  if (var16 < var1) {
                     class="kw">return 0;
                  }

                  int var36 = var34.getRotationIndex(var15, var16, var17);
                  int var37 = var34.getFiller(var15, var16, var17);
                  int var38 = var34.get(var15, var16--, var17);
                  if (var38 != 0) {
                     BlockType var39 = var14.getAsset(var38);
                     if (var37 != 0) {
                        if (var39.getMaterial() == BlockMaterial.Solid) {
                           BlockBoundingBoxes var25 = BlockBoundingBoxes.getAssetMap().getAsset(var39.getHitboxTypeIndex());
                           BlockBoundingBoxes.RotatedVariantBoxes var41 = var25.get(var36);
                           double var43 = var16 + 1 - FillerBlockUtil.unpackY(var37) + var41.getBoundingBox().max.y;
                           if (var43 < var1) {
                              class="kw">return 0;
                           }

                           var0.y = var43;
                           class="kw">return 1;
                        }
                     } else if (var39.getMaterial() == BlockMaterial.Solid) {
                        BlockBoundingBoxes var40 = BlockBoundingBoxes.getAssetMap().getAsset(var39.getHitboxTypeIndex());
                        BlockBoundingBoxes.RotatedVariantBoxes var42 = var40.get(var36);
                        double var44 = var16 + 1 + var42.getBoundingBox().max.y;
                        if (var44 < var1) {
                           class="kw">return 0;
                        }

                        var0.y = var44;
                        class="kw">return 1;
                     }
                  }
               }
            }
         }

         class="kw">return 0;
      } else {
         class="kw">return -1;
      }
   }

   @Override
   class="kw">protected double computeMove(
      @Nonnull Ref<EntityStore> var1,
      @Nonnull Role var2,
      @Nonnull Steering var3,
      double var4,
      @Nonnull Vector3d var6,
      @Nonnull ComponentAccessor<EntityStore> var7
   ) {
      NPCEntity var8 = var7.getComponent(var1, NPCEntity.getComponentType());
      assert var8 != null;
      this.saveMotionKind();
      this.isFullyRotated = true;
      Vector3d var9 = var3.getTranslation();
      var9.y = 0.0;
      this.currentRelativeSpeed = var9.length();
      if (!var3.hasPitch()) {
         var3.setPitch(0.0F);
      }

      double var10 = this.inWater() ? this.maxVerticalSpeedFluid : this.maxVerticalSpeed;
      double var12 = this.getMaximumSpeed();
      boolean var14 = !this.isAlive(var1, var7);
      if (var14 && !this.isForcePushed()) {
         this.climbUpDistance = 0.0;
         this.currentClimbForwardDistance = 0.0;
         this.maxClimbForwardDistance = 0.0;
         var3.setYaw(this.getYaw());
         if (this.onGround) {
            var6.zero();
            var3.setPitch(0.0F);
         } else {
            var3.setPitch(this.getPitch());
            Velocity var31 = var7.getComponent(var1, Velocity.getComponentType());
            Vector3d var39 = var31.getVelocity();
            var6.set(var39);
         }

         var6.y = this.computeNewFallSpeed(var4, var6.y);
         var6.mul(var4);
         this.validateTranslation(var6, "Death");
         class="kw">return var4;
      } else if (this.isForcePushed()) {
         this.climbUpDistance = 0.0;
         this.currentClimbForwardDistance = 0.0;
         this.maxClimbForwardDistance = 0.0;
         var6.set(this.externalVelocity);

         for (int var28 = 0; var28 < this.appliedVelocities.size(); var28++) {
            MotionControllerBase.AppliedVelocity var37 = this.appliedVelocities.get(var28);
            if (var37.velocity.y + this.externalVelocity.y <= 0.0 || var37.velocity.y < 0.0) {
               var37.canClear = true;
            }

            if (this.onGround && var37.canClear) {
               var37.velocity.y = 0.0;
            }

            var6.add(var37.velocity);
         }

         var6.mul(var4);
         if (!this.onGround || !(this.externalVelocity.y < 0.0)) {
            this.externalVelocity.y = this.computeNewFallSpeed(var4, this.externalVelocity.y);
         } else if (var6.y < 0.0) {
            var6.y = 0.0;
            this.externalVelocity.y = 0.0;
         }

         if (!this.appliedVelocity.equals(Vector3dUtil.ZERO)) {
            if (this.moveSpeed > 0.0) {
               float var29 = PhysicsMath.headingX(this.getYaw());
               float var38 = PhysicsMath.headingZ(this.getYaw());
               double var40 = this.appliedVelocity.x * this.appliedVelocity.x + this.appliedVelocity.z * this.appliedVelocity.z;
               double var51 = var40 > 0.0 ? (var29 * this.appliedVelocity.x + var38 * this.appliedVelocity.z) / Math.sqrt(var40) : 0.0;
               var51 = Math.min((var51 + 1.0) / 2.0, this.maxWalkSpeedAfterHitMultiplier);
               this.moveSpeed *= var51;
               if (this.moveSpeed > this.minHorizontalSpeed) {
                  var6.add(this.moveSpeed * var4 * var29, 0.0, this.moveSpeed * var4 * var38);
                  this.currentRelativeSpeed = this.moveSpeed;
               } else {
                  this.moveSpeed = 0.0;
               }
            }

            if (this.maxHover > 0.0) {
               var8.setHoverHeight(var6.y <= 0.0 ? this.minHoverDrop : this.maxHover);
            }

            this.appliedVelocity.zero();
         }

         if (this.onGround && this.ignoreDamping) {
            double var30 = this.externalVelocity.length() - var4 * this.inertia * this.acceleration * 5.0;
            if (var30 > 0.0) {
               this.externalVelocity.normalize(var30);
            } else {
               this.externalVelocity.zero();
            }
         }

         var3.setYaw(this.getYaw());
         this.validateTranslation(var6, "ExtForce");
         class="kw">return var4;
      } else {
         if (this.cachedMovementBlocked) {
            class="kw">return var4;
         }

         float var15 = this.getYaw();
         if (this.getMotionKind() == MotionKind.ASCENDING) {
            if (this.isRequiresPreciseMovement() && this.havePreciseMovementTarget) {
               double var33 = this.waypointDistance(this.preciseMovementTarget, this.position) + this.currentClimbForwardDistance;
               if (var33 < this.maxClimbForwardDistance) {
                  this.maxClimbForwardDistance = var33;
               }
            }

            double var34 = var4 * this.climbSpeed;
            if (this.jumping) {
               if (this.climbUpDistance > 0.0) {
                  var34 *= Math.max(Math.pow(this.climbUpDistance * this.climbUpDistance * this.jumpForce, this.jumpBlending), 1.0);
                  this.climbUpDistance = this.computeClimbMove(this.climbUpDirection, this.climbUpDistance, var34, var6);
               } else if (this.jumpDropHeight > 0.0) {
                  double var44 = this.currentJumpHeight - this.jumpDropHeight;
                  var34 *= Math.max(Math.pow(var44 * var44 * this.jumpDescentSteepness, this.jumpDescentBlending), 1.0);
                  this.jumpDropHeight = this.computeClimbMove(this.jumpDropDirection, this.jumpDropHeight, var34, var6);
               } else {
                  this.setMotionKind(MotionKind.DROPPING);
               }

               double var45 = this.currentJumpHeight - this.climbUpDistance - var6.y;
               double var57 = 0.0;
               if (var45 > this.jumpBlockHeight) {
                  double var62;
                  if (this.climbUpDistance > 0.0) {
                     var62 = (var45 - this.jumpBlockHeight) / var45 / 2.0;
                  } else {
                     var62 = 0.5 + (1.0 - this.jumpDropHeight / (this.currentJumpHeight - this.jumpBlockHeight)) / 2.0;
                  }

                  double var24 = this.maxClimbForwardDistance * var62;
                  if (var24 > this.maxClimbForwardDistance) {
                     var24 = this.maxClimbForwardDistance;
                  }

                  var57 = var24 - this.currentClimbForwardDistance;
                  if (var57 < 0.0) {
                     var57 = 0.0;
                  }

                  this.currentClimbForwardDistance = var24;
                  var6.add(this.climbForwardDirection.x * var57, 0.0, this.climbForwardDirection.z * var57);
               }

               if (this.isBlendingHeading) {
                  var15 = this.computeBlendHeading(
                     var15,
                     NPCPhysicsMath.headingFromDirection(this.climbForwardDirection.x, this.climbForwardDirection.z, var15),
                     var4,
                     var57 / var4,
                     var3.getRelativeTurnSpeed()
                  );
               }

               this.lockOrientation(var3, var6, var15);
               this.fallSpeed = 0.0;
               this.onGround = false;
               this.validateTranslation(var6, "AscendingJump");
               class="kw">return var4;
            } else {
               double var43;
               if (this.climbUpDistance > 0.0) {
                  double var55 = this.climbUpDistance;
                  this.climbUpDistance = this.computeClimbMove(this.climbUpDirection, var55, var34, var6);
                  var43 = var55 - this.climbUpDistance;
               } else if (this.currentClimbForwardDistance < this.maxClimbForwardDistance) {
                  double var56 = this.maxClimbForwardDistance - this.currentClimbForwardDistance;
                  if (var34 < var56) {
                     double var22 = var56 - var34;
                     var43 = var22 <= 1.0E-5 ? var56 : var34;
                  } else {
                     var43 = var56;
                  }

                  this.currentClimbForwardDistance += var43;
                  var6.set(this.climbForwardDirection).mul(var43);
                  this.onGround = false;
               } else {
                  this.setMotionKind(MotionKind.DROPPING);
                  var43 = 0.0;
               }

               if (this.isBlendingHeading) {
                  var15 = this.computeBlendHeading(
                     var15,
                     NPCPhysicsMath.headingFromDirection(this.climbForwardDirection.x, this.climbForwardDirection.z, var15),
                     var4,
                     var43 / var4,
                     var3.getRelativeTurnSpeed()
                  );
               }

               this.lockOrientation(var3, var6, var15);
               this.fallSpeed = 0.0;
               this.onGround = false;
               this.validateSpeeds(var1, "Ascending", var7);
               this.validateTranslation(var6, "Ascending");
               class="kw">return var4;
            }
         } else if (this.getMotionKind() == MotionKind.DESCENDING) {
            double var32 = this.currentRelativeSpeed * var12;
            if (this.isRequiresPreciseMovement() && this.havePreciseMovementTarget) {
               double var41 = this.waypointDistance(this.position, this.preciseMovementTarget);
               if (var41 < var32 * var4) {
                  var32 = var41 / var4;
               }
            }

            this.fallSpeed = MathUtil.maxValue(0.0, NPCPhysicsMath.accelerateDragCapped(this.fallSpeed, 5.0 * this.gravity, var4, var10));
            this.moveSpeed = MathUtil.clamp(var32, 0.0, this.moveSpeed + var4 * this.acceleration);
            if (this.moveSpeed > var12) {
               this.moveSpeed = var12;
            }

            if (this.moveSpeed <= 0.3 * this.maxHorizontalSpeed) {
               this.setMotionKind(MotionKind.DROPPING);
            }

            double var42 = this.climbForwardDirection.y;
            if (this.predictedFallHeight > 0.0) {
               this.totalDropDistance = this.totalDropDistance + Math.abs(this.climbForwardDirection.y * this.moveSpeed * var4);
               double var54 = Math.min(this.totalDropDistance / this.predictedFallHeight, 1.0);
               var42 *= Math.pow(this.descentSteepness, this.descentBlending) * Math.pow(var54, this.descentBlending);
            }

            var6.set(this.climbForwardDirection.x, var42, this.climbForwardDirection.z);
            var6.mul(this.moveSpeed * var4);
            var6.y = Math.min(var6.y, -this.fallSpeed * var4);
            Vector3dUtil.clipToZero(var6, this.getEpsilonSpeed());
            if (this.isBlendingHeading) {
               var15 = this.computeBlendHeading(
                  var15,
                  NPCPhysicsMath.headingFromDirection(this.climbForwardDirection.x, this.climbForwardDirection.z, var15),
                  var4,
                  this.moveSpeed,
                  var3.getRelativeTurnSpeed()
               );
            }

            this.lockOrientation(var3, var6, var15);
            this.validateSpeeds(var1, "Descending", var7);
            this.validateTranslation(var6, "Descending");
            class="kw">return var4;
         } else {
            this.validateSpeeds(var1, "Enter Walk/Drop", var7);
            boolean var16 = this.canSteer(var1, var7);
            boolean var18 = false;
            float var17;
            if (var16) {
               var17 = NPCPhysicsMath.headingFromDirection(var9.x, var9.z, var15);
               if (this.isRequiresPreciseMovement() && !this.isBlendingHeading) {
                  float var19 = NPCPhysicsMath.turnAngle(var15, var17);
                  float var20 = this.getEpsilonAngle();
                  if (var19 < -var20 || var19 > var20) {
                     float var21 = (float)MathUtil.clamp(var4 * this.getCurrentMaxBodyRotationSpeed() * var3.getRelativeTurnSpeed(), 0.0, (float) (Math.PI / 2));
                     var19 = MathUtil.clamp(var19, -var21, var21);
                     var15 = PhysicsMath.normalizeTurnAngle(var15 + var19);
                     var6.set(0.0, 0.0, 0.0);
                     var3.setYaw(var15);
                     this.isFullyRotated = false;
                     class="kw">return var4;
                  }

                  var15 = var17;
               }

               this.moveSpeed = MathUtil.clamp(this.currentRelativeSpeed * var12, 0.0, this.moveSpeed + var4 * this.acceleration);
               if (this.fallSpeed > 0.0) {
                  this.fallSpeed = 0.0;
               }

               if (this.moveSpeed < this.getEpsilonSpeed()) {
                  this.moveSpeed = 0.0;
               } else if (this.moveSpeed < this.minHorizontalSpeed) {
                  this.moveSpeed = this.minHorizontalSpeed;
               }

               if (this.isBlendingHeading) {
                  if (this.blendRestTurnAngle > 0.0F) {
                     float var46 = this.computeBlendTurnAngle(var15, var17);
                     if (Math.abs(var46) > this.blendRestTurnAngle) {
                        var18 = true;
                     }

                     var15 = this.computeBlendHeading(var15, var17, var4, this.moveSpeed, var46, var3.getRelativeTurnSpeed());
                  } else {
                     var15 = this.computeBlendHeading(var15, var17, var4, this.moveSpeed, var3.getRelativeTurnSpeed());
                  }

                  var3.setYaw(var15);
                  this.isFullyRotated = true;
               } else if (var3.hasYawOrDirection()) {
                  float var47 = var3.getYawOrDirection();
                  var15 = this.computeHeading(var47, var3.getRelativeTurnSpeed(), var15, var4, false, false);
                  var3.setYaw(var15);
               } else if (this.moveSpeed != 0.0) {
                  var15 = this.computeHeading(var17, var3.getRelativeTurnSpeed(), var15, var4, true, true);
                  var17 = var15;
                  var3.setYaw(var15);
               }

               if (this.debugModeSteer) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d === Compute = t =%.4f v =%.4f h =%.4f mh=%.4f",
                        this.debugEntityId,
                        var4,
                        this.moveSpeed,
                        (180.0F / (float)Math.PI) * var15,
                        (180.0F / (float)Math.PI) * var17
                     );
               }
            } else {
               Velocity var49 = var7.getComponent(var1, Velocity.getComponentType());
               Vector3d var53 = var49.getVelocity();
               var17 = NPCPhysicsMath.headingFromDirection(var53.x, var53.z, var15);
               if (!var3.hasYawOrDirection()) {
                  var3.setYaw(var15);
               }

               if (this.maxHover > 0.0 && this.floatsDown) {
                  this.fallSpeed = this.climbSpeedConst;
                  if (this.fallSpeed != 0.0 && this.climbSpeedMult != 0.0) {
                     double var59 = this.fallSpeed;
                     double var23 = this.climbSpeedMult * Math.pow(var59, this.climbSpeedPow);
                     this.fallSpeed += var23;
                  }
               } else {
                  double var58 = this.fallSpeed;
                  this.fallSpeed = -NPCPhysicsMath.gravityDrag(-var58, 5.0 * this.gravity, var4, var10);
               }
            }

            if (this.moveSpeed > var12) {
               this.moveSpeed = var12;
            }

            if (this.fallSpeed > var10) {
               this.fallSpeed = var10;
            } else if (this.fallSpeed < -var10) {
               this.fallSpeed = -var10;
            }

            double var50 = this.moveSpeed;
            if (var18) {
               double var60 = this.blendRestRelativeSpeed * this.getMaximumSpeed();
               if (var50 > var60) {
                  var50 = var60;
               }
            }

            var6.x = var50 * var4 * PhysicsMath.headingX(var17);
            var6.z = var50 * var4 * PhysicsMath.headingZ(var17);
            var6.y = -this.fallSpeed * var4;
            double var61 = var3.getMaxDistance();
            if (this.canSteer(var1, var7) && var61 < Double.MAX_VALUE && var61 > 0.0) {
               double var63 = NPCPhysicsMath.dotProduct(var6.x, var6.y, var6.z, this.getComponentSelector());
               double var25 = Math.sqrt(var63);
               if (var25 > var61) {
                  var6.mul(var61 / var25);
               }
            }

            this.validateSpeeds(var1, var16 ? "Moving" : "Falling", var7);
            this.validateTranslation(var6, var16 ? "Moving" : "Falling");
            class="kw">return var4;
         }
      }
   }

   class="kw">private double computeNewFallSpeed(double var1, double var3) {
      Box var5 = this.collisionBoundingBox;
      int var6 = this.movementSettings.invertedGravity ? 1 : -1;
      double var7 = var6
         * PhysicsMath.getTerminalVelocity(
            this.movementSettings.mass, 0.001225, Math.abs((var5.max.x - var5.min.x) * (var5.max.z - var5.min.z)), this.movementSettings.dragCoefficient
         );
      double var9 = PhysicsMath.getAcceleration(var3, var7) * var1;
      if (var3 < var7 && var9 > 0.0) {
         var3 = Math.min(var3 + var9, var7);
      } else if (var3 > var7 && var9 < 0.0) {
         var3 = Math.max(var3 + var9, var7);
      }

      class="kw">return var3;
   }

   class="kw">private boolean findMoveCollisions(int var1, boolean var2, @Nonnull Vector3d var3, @Nonnull ComponentAccessor<EntityStore> var4) {
      this.collisionResult.setCollisionByMaterial(4, var1);
      this.resetObstructedFlags();
      if (this.debugModeBlockCollisions) {
         this.collisionResult.setLogger(LOGGER, this.debugEntityId);
      }

      boolean var5 = this.collisionResult.setDamageBlocking(var2);
      boolean var6 = !CollisionModule.findCollisions(this.collisionBoundingBox, this.position, var3, false, this.collisionResult, var4);
      this.collisionResult.setDamageBlocking(var5);
      if (this.debugModeBlockCollisions) {
         this.collisionResult.setLogger(null);
      }

      if (this.debugModeCollisions) {
         this.dumpCollisionResults();
      }

      class="kw">return var6;
   }

   class="kw">private double finishPhysicsCollision(@Nonnull Ref<EntityStore> var1, double var2, double var4, @Nonnull ComponentAccessor<EntityStore> var6) {
      this.processTriggers(var1, this.collisionResult, var4, var6);
      var2 *= var4;
      if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
         LOGGER.at(Level.WARNING)
            .log("eid=%d Move: Physics moved to invalid position pos=%s/%s/%s", this.debugEntityId, this.position.x, this.position.y, this.position.z);
      }

      class="kw">return var2;
   }

   class="kw">private double executePhysicsMove(@Nonnull Ref<EntityStore> var1, double var2, @Nonnull Vector3d var4, @Nonnull ComponentAccessor<EntityStore> var5) {
      this.findMoveCollisions(13, false, var4, var5);
      BlockCollisionData var6 = this.collisionResult.getFirstBlockCollision();
      this.lastValidPosition.set(this.position);
      boolean var7 = this.onGround;
      if (var6 == null) {
         double var16;
         double var19;
         if (this.collisionResult.isSliding) {
            var16 = this.collisionResult.slideStart;
            var19 = this.collisionResult.slideEnd;
         } else {
            var16 = Double.MAX_VALUE;
            var19 = Double.MAX_VALUE;
         }

         this.position.add(var4);
         this.onGround = var16 <= 1.0 && var19 >= 1.0;
         double var20 = 1.0;
         if (this.onGround) {
            this.setMotionKind(MotionKind.STANDING);
         } else {
            this.setMotionKind(MotionKind.DROPPING);
            if (var7) {
               this.fallStartHeight = this.position.y;
               this.fallSpeed = 0.0;
            }
         }

         if (!this.isValidPosition(this.position, this.collisionResult, var5)) {
            double var14 = this.bisect(this.lastValidPosition, this.position, this.position, var5);
            var20 *= var14;
            if (this.debugModeMove) {
               LOGGER.at(Level.INFO)
                  .log(
                     "eid=%d Move: Physics no-collision bisect scale=%s newpos=%s state=%s",
                     this.debugEntityId,
                     var14,
                     Vector3dUtil.formatShortString(this.position),
                     this.getMotionKind()
                  );
            }

            if (var14 == 0.0) {
               this.isObstructed = true;
            }
         } else if (this.shouldDebugMove(var4)) {
            LOGGER.at(Level.INFO)
               .log(
                  "eid=%d Move: Physics no-collision onGround=%s newpos=%s state=%s",
                  this.debugEntityId,
                  this.onGround,
                  Vector3dUtil.formatShortString(this.position),
                  this.getMotionKind()
               );
         }

         this.processTriggers(var1, this.collisionResult, var20, var5);
         if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var5)) {
            LOGGER.at(Level.WARNING)
               .log("eid=%d Move: Physics moved to invalid position pos=%s/%s/%s", this.debugEntityId, this.position.x, this.position.y, this.position.z);
         }

         class="kw">return var2;
      } else {
         double var8 = var6.collisionStart;
         this.position.set(var6.collisionPoint);
         this.tmpMovePosition.set(this.lastValidPosition).add(var4).sub(var6.collisionPoint);
         if (!this.tmpMovePosition.equals(Vector3dUtil.ZERO)) {
            double var10 = this.tmpMovePosition.dot(var6.collisionNormal);
            this.tmpMovePosition.fma(-var10, var6.collisionNormal);
            this.position.add(this.tmpMovePosition);
         }

         if (!this.isValidPosition(this.position, this.collisionResult, var5)) {
            double var17 = this.bisect(this.lastValidPosition, this.position, this.position, var5);
            var8 *= var17;
            if (this.debugModeMove) {
               LOGGER.at(Level.INFO).log("eid=%d Move: Physics collision bisect=%s triggerScale=%s", this.debugEntityId, var17, var8);
            }
         }

         if (!this.isForcePushed()) {
            if (var6.collisionNormal.equals(this.getWorldNormal())) {
               this.setMotionKind(MotionKind.STANDING);
               if (!this.onGround) {
                  this.onGround = true;
                  this.postReadPosition(var1, var5);
               }

               this.fallSpeed = 0.0;
               if (this.debugModeMove) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d Move: Physics ground collision onGround=%s newpos=%s state=%s",
                        this.debugEntityId,
                        this.onGround,
                        Vector3dUtil.formatShortString(this.position),
                        this.getMotionKind()
                     );
               }

               class="kw">return this.finishPhysicsCollision(var1, var2, var8, var5);
            } else if (var6.collisionNormal.equals(this.getWorldAntiNormal())) {
               this.fallSpeed = 0.0;
               this.setMotionKind(MotionKind.DROPPING);
               if (this.debugModeMove) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d Move: Physics ceiling collision newpos=%s state=%s",
                        this.debugEntityId,
                        Vector3dUtil.formatShortString(this.position),
                        this.getMotionKind()
                     );
               }

               class="kw">return this.finishPhysicsCollision(var1, var2, var8, var5);
            } else {
               this.isObstructed = true;
               this.setMotionKind(MotionKind.STANDING);
               if (this.debugModeMove) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d Move: Physics wall collision newpos=%s state=%s",
                        this.debugEntityId,
                        Vector3dUtil.formatShortString(this.position),
                        this.getMotionKind()
                     );
               }

               class="kw">return this.finishPhysicsCollision(var1, var2, var8, var5);
            }
         } else {
            if (this.ignoreDamping) {
               this.ignoreDamping = false;
               this.clearExternalVelocity();
            }

            int var18 = this.collisionResult.getBlockCollisionCount();

            for (int var11 = 0; var11 < var18; var11++) {
               BlockCollisionData var12 = this.collisionResult.getBlockCollision(var11);
               if (var12.collisionNormal.equals(this.getWorldNormal())) {
                  this.onGround = true;
                  this.fallSpeed = 0.0;
                  break;
               }
            }

            this.setMotionKind(MotionKind.DROPPING);
            if (var6.collisionNormal.equals(this.getWorldAntiNormal())) {
               this.fallSpeed = 0.0;
            }

            if (this.debugModeMove) {
               LOGGER.at(Level.INFO)
                  .log(
                     "eid=%d Move: Physics force-push collision normal=%s onGround=%s newpos=%s state=%s",
                     this.debugEntityId,
                     var6.collisionNormal,
                     this.onGround,
                     Vector3dUtil.formatShortString(this.position),
                     this.getMotionKind()
                  );
            }

            class="kw">return this.finishPhysicsCollision(var1, var2, var8, var5);
         }
      }
   }

   @Override
   class="kw">protected double executeMove(
      @Nonnull Ref<EntityStore> var1, @Nonnull Role var2, double var3, @Nonnull Vector3d var5, @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      if (this.shouldDebugMove(var5)) {
         LOGGER.at(Level.INFO)
            .log(
               "eid=%d Move: Execute pos=%s vel=%s onGround=%s blocked=%s solidGround=%s avdDmg=%s relax=%s",
               this.debugEntityId,
               Vector3dUtil.formatShortString(this.position),
               Vector3dUtil.formatShortString(var5),
               this.onGround,
               this.isObstructed,
               this.isOnSolidGround(),
               this.isAvoidingBlockDamage(),
               !this.getRelaxedConstraints().isEmpty()
            );
      }

      if (this.isAlive(var1, var6) && !this.isForcePushed()) {
         this.effectiveMoveConstraints.clear();
         this.effectiveMoveConstraints.addAll(this.relaxedConstraints);
         if (!this.isOnSolidGround()) {
            this.effectiveMoveConstraints.add(RelaxedConstraint.DAMAGE);
            this.effectiveMoveConstraints.add(RelaxedConstraint.WADE);
         }

         if (this.inWater) {
            this.effectiveMoveConstraints.add(RelaxedConstraint.WADE);
         }

         if (!var2.couldBreatheCached(var1, var6)) {
            this.effectiveMoveConstraints.add(RelaxedConstraint.BREATHE);
         }

         boolean var7 = !this.effectiveMoveConstraints.contains(RelaxedConstraint.DAMAGE);
         boolean var8 = this.effectiveMoveConstraints.contains(RelaxedConstraint.WADE);
         double var9 = this.effectiveMaxDropHeight(this.effectiveMoveConstraints);
         boolean var11 = this.findMoveCollisions(var8 ? 13 : 5, var7, var5, var6);
         BlockCollisionData var12 = this.collisionResult.getFirstBlockCollision();
         double var13;
         double var15;
         if (this.collisionResult.isSliding) {
            var13 = this.collisionResult.slideStart;
            var15 = this.collisionResult.slideEnd;
            if (this.onGround) {
               var12 = this.discardIgnorableSlideCollisions(this.collisionResult, var12, this.effectiveMoveConstraints);
            }
         } else {
            var13 = Double.MAX_VALUE;
            var15 = Double.MAX_VALUE;
         }

         boolean var17 = this.isRequiresPreciseMovement() && !this.isFullyRotated;
         this.lastValidPosition.set(this.position);
         boolean var18 = this.onGround;
         if (var12 == null) {
            double var27;
            if (var18 && !(var15 >= 1.0)) {
               if (this.isOnSolidGround() && var17) {
                  this.isObstructed = false;
                  var15 = this.shortenSlide(var5, var15);
               } else {
                  this.onGround = false;
                  this.tmpMovePosition.set(this.position).fma(var15, var5);
                  if (this.isDropBlocked(this.tmpMovePosition, var9, false, this.effectiveMoveConstraints, var6)) {
                     ChunkStore var31 = var6.getExternalData().getWorld().getChunkStore();
                     if (this.isValidWalkPosition(
                        var31, this.lastValidPosition.x, this.lastValidPosition.y, this.lastValidPosition.z, this.effectiveMoveConstraints
                     )) {
                        var15 = this.shortenSlide(var5, var15);
                        this.isObstructed = true;
                        this.onGround = true;
                     }
                  }
               }

               this.position.fma(var15, var5);
               var27 = var15;
               var3 *= var15;
               if (this.onGround && this.validateGroundPosition(var9, this.effectiveMoveConstraints, var6)) {
                  var27 = 0.0;
               }
            } else {
               this.position.add(var5);
               this.onGround = var13 <= 1.0 && var15 >= 1.0;
               var27 = 1.0;
               if (var18 && this.onGround) {
                  ChunkStore var30 = var6.getExternalData().getWorld().getChunkStore();
                  if (!this.isValidWalkPosition(var30, this.position.x, this.position.y, this.position.z, this.effectiveMoveConstraints)
                     && this.isValidWalkPosition(
                        var30, this.lastValidPosition.x, this.lastValidPosition.y, this.lastValidPosition.z, this.effectiveMoveConstraints
                     )) {
                     double var34 = this.bisect(
                        this.lastValidPosition,
                        this.position,
                        this,
                        (var2x, var3x) -> var2x.isValidWalkPosition(var30, var3x.x, var3x.y, var3x.z, this.effectiveMoveConstraints),
                        this.position
                     );
                     var27 *= var34;
                     if (var34 == 0.0) {
                        this.isObstructed = true;
                     }
                  }
               }
            }

            if (this.getMotionKind() != MotionKind.ASCENDING) {
               if (this.onGround) {
                  this.setMotionKind(
                     !this.isObstructed && NPCPhysicsMath.projectedLengthSquared(var5, this.getComponentSelector()) > 0.0
                        ? MotionKind.MOVING
                        : MotionKind.STANDING
                  );
               } else if (this.initiateDescend(var5, var18, "No collision", var6)) {
                  this.position.set(this.lastValidPosition);
                  this.moveSpeed = 0.0;
                  var27 = 0.0;
               }
            }

            if (!this.isValidPosition(this.position, this.collisionResult, var6)) {
               if (this.getMotionKind() == MotionKind.DESCENDING) {
                  this.setMotionKind(MotionKind.DROPPING);
               }

               double var32 = this.bisect(this.lastValidPosition, this.position, this.position, var6);
               var27 *= var32;
               if (this.shouldDebugMove(var5)) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d Move: No collision, bisect onGround was/is=%s/%s slide=%s/%s scale=%s newpos=%s state=%s blocked=%s",
                        this.debugEntityId,
                        var18,
                        this.onGround,
                        var13,
                        var15,
                        var32,
                        Vector3dUtil.formatShortString(this.position),
                        this.getMotionKind(),
                        this.isObstructed
                     );
               }

               if (var32 == 0.0) {
                  this.isObstructed = true;
               }
            } else if (this.shouldDebugMove(var5)) {
               LOGGER.at(Level.INFO)
                  .log(
                     "eid=%d Move: No collision onGround was/is=%s/%s slide=%s/%s newpos=%s state=%s",
                     this.debugEntityId,
                     var18,
                     this.onGround,
                     var13,
                     var15,
                     Vector3dUtil.formatShortString(this.position),
                     this.getMotionKind()
                  );
            }

            this.processTriggers(var1, this.collisionResult, var27, var6);
            if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
               LOGGER.at(Level.WARNING)
                  .log(
                     "eid=%d Move: Walked on invalid position pos=%s/%s/%s overlaps=%s",
                     this.debugEntityId,
                     this.position.x,
                     this.position.y,
                     this.position.z,
                     this.collisionResult.getBlockCollisionCount()
                  );
            }

            class="kw">return var3;
         } else {
            if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
               throw new IllegalStateException("Invalid position");
            }

            double var19 = var12.collisionStart;
            this.position.set(var12.collisionPoint);
            if (!this.isValidPosition(this.position, this.collisionResult, var6)) {
               double var21 = this.bisect(this.lastValidPosition, this.position, this.position, var6);
               var19 *= var21;
               if (this.debugModeMove) {
                  LOGGER.at(Level.INFO).log("eid=%d Move: Collision bisect=%s triggerScale=%s", this.debugEntityId, var21, var19);
               }
            }

            if (var12.collisionNormal.equals(this.getWorldNormal())) {
               if (this.onGround && !this.isDropBlocked(this.position, var9, false, this.effectiveMoveConstraints, var6)) {
                  this.initiateDescend(var5, true, "Collision", var6);
                  this.onGround = false;
               } else {
                  if (this.onGround) {
                     this.isObstructed = true;
                     if (var7 && var12.willDamage) {
                        var19 = this.shortenMovement(var19);
                     }
                  } else if (this.getMotionKind() == MotionKind.DROPPING) {
                     double var29 = this.fallStartHeight - this.position.y;
                     if (var29 >= this.maxDropHeight) {
                        this.moveSpeed = 0.0;
                     } else if (var29 > this.maxClimbHeight) {
                        this.moveSpeed = this.moveSpeed * ((var29 - this.maxClimbHeight) / (this.maxDropHeight - this.maxClimbHeight));
                        this.validateSpeeds(var1, "Collision on Ground", var6);
                     }
                  }

                  this.setMotionKind(MotionKind.STANDING);
                  if (this.shouldDebugMove(var5)) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: Collision Up onGround is/was=%s/%s blocked=%s newpos=%s state=%s",
                           this.debugEntityId,
                           this.onGround,
                           var18,
                           this.isObstructed,
                           Vector3dUtil.formatShortString(this.position),
                           this.getMotionKind()
                        );
                  }

                  if (!this.onGround) {
                     this.onGround = true;
                     this.postReadPosition(var1, var6);
                  }
               }

               if (this.onGround && this.validateGroundPosition(var9, this.effectiveMoveConstraints, var6)) {
                  var19 = 0.0;
               }

               this.processTriggers(var1, this.collisionResult, var19, var6);
               var3 *= var19;
               if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
                  LOGGER.at(Level.WARNING)
                     .log(
                        "eid=%d Move: Walked on invalid position pos=%s/%s/%s overlaps=%s",
                        this.debugEntityId,
                        this.position.x,
                        this.position.y,
                        this.position.z,
                        this.collisionResult.getBlockCollisionCount()
                     );
               }

               class="kw">return var3;
            } else if (var12.collisionNormal.equals(this.getWorldAntiNormal())) {
               this.fallSpeed = 0.0;
               this.setMotionKind(MotionKind.DROPPING);
               if (this.debugModeMove) {
                  LOGGER.at(Level.INFO)
                     .log(
                        "eid=%d Move: No ext force, collision down, clear vert speed newpos=%s state=%s",
                        this.debugEntityId,
                        Vector3dUtil.formatShortString(this.position),
                        this.getMotionKind()
                     );
               }

               if (this.onGround && this.validateGroundPosition(var9, this.effectiveMoveConstraints, var6)) {
                  var19 = 0.0;
               }

               this.processTriggers(var1, this.collisionResult, var19, var6);
               var3 *= var19;
               if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
                  LOGGER.at(Level.WARNING)
                     .log(
                        "eid=%d Move: Walked on invalid position pos=%s/%s/%s overlaps=%s",
                        this.debugEntityId,
                        this.position.x,
                        this.position.y,
                        this.position.z,
                        this.collisionResult.getBlockCollisionCount()
                     );
               }

               class="kw">return var3;
            } else {
               boolean var28;
               if (!var11
                  && !var17
                  && this.isOnSolidGround()
                  && var12.blockType != null
                  && this.isClimbable(var12.blockType, var12.fluid, this.effectiveMoveConstraints)) {
                  var28 = this.tryClimb(var5, this.effectiveMoveConstraints, var6);
                  if (this.debugModeMove) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: No ext force, collision horz, try climb h=%s succ=%s newpos(succ|fail)=%s|%s state=%s",
                           this.debugEntityId,
                           this.climbUpDistance,
                           var28,
                           Vector3dUtil.formatShortString(this.tmpMovePosition),
                           Vector3dUtil.formatShortString(this.position),
                           this.getMotionKind()
                        );
                  }
               } else {
                  var28 = false;
                  if (var7 && var12.willDamage) {
                     var19 = this.shortenMovement(var19);
                  }

                  if (this.debugModeMove) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: No ext force, collision horz, don't try climb onGround %s, block %s newpos=%s state=%s",
                           this.debugEntityId,
                           this.onGround,
                           var12.blockType != null,
                           Vector3dUtil.formatShortString(this.position),
                           this.getMotionKind()
                        );
                  }
               }

               this.isObstructed = this.isFullyRotated && !var28 && !var11;
               if (this.onGround && this.validateGroundPosition(var9, this.effectiveMoveConstraints, var6)) {
                  var28 = false;
                  var19 = 0.0;
               }

               this.processTriggers(var1, this.collisionResult, var19, var6);
               var3 *= var19;
               if (var28 && !this.isProcessTriggersHasMoved()) {
                  this.setMotionKind(MotionKind.ASCENDING);
                  this.climbUpDirection.set(this.getWorldNormal());
                  this.climbForwardDirection.set(var5).normalize();
                  this.climbSpeed = this.computeClimbSpeed(this.moveSpeed);
                  this.onGround = false;
                  if (this.debugModeMove) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: No ext force, collision horz, start climbing h=%s forw=%s state=%s",
                           this.debugEntityId,
                           this.climbUpDistance,
                           this.maxClimbForwardDistance,
                           this.getMotionKind()
                        );
                  }

                  if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
                     throw new IllegalStateException("Invalid position");
                  }
               } else if (var2.getLastAvoidanceSteering().lengthSquared() < 1.0E-5 && var2.getLastSeparationSteering().lengthSquared() < 1.0E-5) {
                  this.tmpMovePosition.set(this.lastValidPosition).add(var5).sub(var12.collisionPoint);
                  if (!this.tmpMovePosition.equals(Vector3dUtil.ZERO)) {
                     double var22 = this.tmpMovePosition.dot(var12.collisionNormal);
                     this.tmpMovePosition.fma(-var22, var12.collisionNormal);
                     this.position.add(this.tmpMovePosition);
                  }

                  if (this.debugModeMove) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: No ext force, collision horz, sliding at wall h=%s state=%s",
                           this.debugEntityId,
                           Vector3dUtil.formatShortString(this.tmpMovePosition),
                           this.getMotionKind()
                        );
                  }

                  if (!this.isValidPosition(this.position, this.collisionResult, var6)) {
                     double var33 = this.bisect(this.lastValidPosition, this.position, this.position, var6);
                     if (this.debugModeMove) {
                        LOGGER.at(Level.INFO).log("eid=%d Move: Collision slide bisect=%s dt=%s", this.debugEntityId, var33, var3);
                     }
                  }

                  if (this.lastValidPosition.distanceSquared(this.position) > this.getEpsilonSpeed()) {
                     this.setMotionKind(MotionKind.MOVING);
                  } else {
                     this.setMotionKind(MotionKind.STANDING);
                  }
               } else {
                  if (this.debugModeMove) {
                     LOGGER.at(Level.INFO)
                        .log(
                           "eid=%d Move: No ext force, collision horz, no sliding at wall, avoidance/separation, h=%s state=%s",
                           this.debugEntityId,
                           Vector3dUtil.formatShortString(this.tmpMovePosition),
                           this.getMotionKind()
                        );
                  }

                  this.setMotionKind(MotionKind.STANDING);
               }

               if (this.debugModeValidatePositions && !this.isValidPosition(this.position, this.collisionResult, var6)) {
                  LOGGER.at(Level.WARNING)
                     .log(
                        "eid=%d Move: Walked on invalid position pos=%s/%s/%s overlaps=%s",
                        this.debugEntityId,
                        this.position.x,
                        this.position.y,
                        this.position.z,
                        this.collisionResult.getBlockCollisionCount()
                     );
               }

               class="kw">return var3;
            }
         }
      } else {
         class="kw">return this.executePhysicsMove(var1, var3, var5, var6);
      }
   }

   @Override
   class="kw">public double probeMove(@Nonnull Ref<EntityStore> var1, @Nonnull ProbeMoveData var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      World var4 = var3.getExternalData().getWorld();
      boolean var5 = var2.startProbing();
      Vector3d var6 = var2.probeDirection;
      double var7 = NPCPhysicsMath.projectedLengthSquared(var6, this.getComponentSelector());
      if (var7 == 0.0) {
         class="kw">return 0.0;
      }

      EnumSet var9 = var2.getRelaxedConstraints();
      boolean var10 = !var9.contains(RelaxedConstraint.DAMAGE);
      boolean var11 = var9.contains(RelaxedConstraint.WADE);
      double var12 = this.effectiveMaxDropHeight(var9);
      this.collisionResult.setCollisionByMaterial(4, var11 ? 13 : 5);
      Predicate var14 = this.collisionResult.setBlockCollisionFilter(var2.getBlockCollisionFilter());
      Predicate var15 = this.tmpResults.setBlockCollisionFilter(var2.getBlockCollisionFilter());
      this.activeProbeBlockCollisionFilter = var2.getBlockCollisionFilter();
      this.activeProbeBreathableBlockOverride = var2.getBreathableBlockOverride();

      try {
         Vector3d var16 = var2.probePosition;
         Vector3d var17 = var2.initialPosition;
         Vector3d var18 = var2.targetPosition;
         Vector3d var19 = var2.directionComponentSelector;
         CollisionModule var22 = CollisionModule.get();
         boolean var21;
         if (var17.equals(this.position)) {
            var21 = this.onGround;
         } else {
            this.applyActiveProbeBlockCollisionFilter(this.collisionResult);
            var21 = var22.validatePosition(var4, this.collisionBoundingBox, var16, this.collisionResult) == 1;
         }

         var19.set(this.getComponentSelector());
         var6.mul(var19);
         if (var5) {
            var2.addStartSegment(var17, true);
         }

         if (!var21) {
            if (this.isDropBlocked(var16, var12, true, var9, var3)) {
               if (var5) {
                  var2.addBlockedDropSegment(var16, this.waypointDistance(var17, var16));
                  class="kw">return var2.getLastDistance();
               }

               var2.edgeBlocked = true;
               class="kw">return this.waypointDistance(var17, var16);
            }

            if (var5) {
               var2.addDropSegment(var16, this.waypointDistance(var17, var16));
            }
         }

         while (var7 > 0.0) {
            if (this.debugModeProbeBlockCollisions || var2.debugCollision) {
               this.collisionResult.setLogger(LOGGER, this.debugEntityId);
            }

            boolean var23 = this.collisionResult.setDamageBlocking(var10);
            this.applyActiveProbeBlockCollisionFilter(this.collisionResult);
            boolean var24 = !CollisionModule.findCollisions(this.collisionBoundingBox, var16, var6, this.collisionResult, var3);
            this.collisionResult.setDamageBlocking(var23);
            if (this.debugModeProbeBlockCollisions || var2.debugCollision) {
               this.collisionResult.setLogger(null);
            }

            if (this.debugModeMove) {
               LOGGER.at(Level.INFO)
                  .log(
                     "eid=%d Probe Step: pos=%s mov=%s left=%s",
                     this.debugEntityId,
                     Vector3dUtil.formatShortString(var16),
                     Vector3dUtil.formatShortString(var6),
                     Math.sqrt(var7)
                  );
            }

            if (this.debugModeCollisions) {
               this.dumpCollisionResults();
            }

            BlockCollisionData var20 = this.collisionResult.getFirstBlockCollision();
            double var25 = this.collisionResult.isSliding ? this.collisionResult.slideEnd : Double.MAX_VALUE;
            if (this.collisionResult.isSliding) {
               var20 = this.discardIgnorableSlideCollisions(this.collisionResult, var20, var9);
            }

            if (var20 != null && var20.collisionStart <= var25) {
               if (var10 && var20.willDamage) {
                  this.shortenMovement(var16, var20.collisionPoint, var16);
                  var7 = 0.0;
               } else {
                  var16.set(var20.collisionPoint);
                  var7 = this.updateMovementVector(var16, var6, var18, var19);
               }

               if (var20.collisionNormal.equals(this.getWorldNormal())) {
                  double var40 = this.waypointDistance(var17, var16);
                  if (var5) {
                     var2.addBlockedGroundSegment(var16, var40, var20.collisionNormal, var20.blockId);
                  }

                  class="kw">return var40;
               }

               if (var5) {
                  var2.addHitWallSegment(var16, true, this.waypointDistance(var17, var16), var20.collisionNormal, var20.blockId);
               }

               int var39 = var20.blockId;
               if (var20.blockType == null || var7 < 0.010000000000000002 || !this.isClimbable(var20.blockType, var20.fluid, var9)) {
                  if (var5) {
                     var2.changeSegmentToBlockedWall();
                  }

                  class="kw">return this.waypointDistance(var17, var16);
               }

               double var28 = var24 ? 0.0 : this.computeClimbHeight(var16, var6, this.maxClimbHeight, 0.1, null, this.tmpClimbHeightResults, var9, var3);
               if (var28 <= 0.0) {
                  if (var5) {
                     var2.changeSegmentToBlockedWall();
                  }

                  class="kw">return this.waypointDistance(var17, var16);
               }

               var16.fma(var28, this.getWorldNormal());
               if (var5) {
                  var2.addClimbSegment(var16, this.waypointDistance(var17, var16), var39);
               }

               var7 = this.updateMovementVector(var16, var6, var18, var19);
            } else {
               if (var25 >= 1.0) {
                  var16.add(var6);
                  if (!var11) {
                     ChunkStore var37 = var3.getExternalData().getWorld().getChunkStore();
                     if (!this.isValidWalkPosition(var37, var16.x, var16.y, var16.z, var9) && this.isValidWalkPosition(var37, var17.x, var17.y, var17.z, var9)) {
                        var16.sub(var6);
                        if (var5) {
                           var2.addBlockedGroundSegment(var16, this.waypointDistance(var17, var16), this.getWorldNormal(), -1);
                        }

                        class="kw">return this.waypointDistance(var17, var16);
                     }
                  }

                  var6.set(Vector3dUtil.ZERO);
                  double var38 = this.waypointDistance(var17, var16);
                  if (var5) {
                     var2.addMoveSegment(var16, true, var38);
                  }

                  class="kw">return var38;
               }

               var16.fma(var25, var6);
               if (var5) {
                  var2.addHitEdgeSegment(var16, this.waypointDistance(var17, var16));
               }

               if (this.isDropBlocked(var16, var12, true, var9, var3)) {
                  ChunkStore var27 = var3.getExternalData().getWorld().getChunkStore();
                  if (var11 || this.isValidWalkPosition(var27, var17.x, var17.y, var17.z, var9)) {
                     var6.set(var18).sub(var16).mul(var19);
                     if (var5) {
                        var2.changeSegmentToBlockedEdge();
                        class="kw">return var2.getLastDistance();
                     }

                     var2.edgeBlocked = true;
                     class="kw">return this.waypointDistance(var17, var16);
                  }
               }

               if (var5) {
                  var2.addDropSegment(var16, this.waypointDistance(var17, var16));
               }

               var7 = this.updateMovementVector(var16, var6, var18, var19);
            }
         }

         double var36 = this.waypointDistance(var17, var16);
         if (var5) {
            var2.addEndSegment(var16, true, var36);
         }

         class="kw">return var36;
      } class="kw">finally {
         this.collisionResult.setBlockCollisionFilter(var14);
         this.tmpResults.setBlockCollisionFilter(var15);
         this.activeProbeBlockCollisionFilter = null;
         this.activeProbeBreathableBlockOverride = null;
      }
   }

   @Override
   class="kw">protected void postExecuteMove() {
      if (this.isObstructed && !this.onGround) {
         this.moveSpeed = 0.0;
      }
   }

   @Override
   class="kw">public double getCurrentMaxBodyRotationSpeed() {
      class="kw">return this.maxRotationSpeed * this.effectHorizontalSpeedMultiplier;
   }

   class="kw">protected float computeHeading(float var1, double var2, float var4, double var5, boolean var7, boolean var8) {
      double var9 = NPCPhysicsMath.turnAngle(var4, var1);
      double var11 = this.getEpsilonAngle();
      if (var9 >= -var11 && var9 <= var11) {
         var4 = var1;
         if (var7) {
            this.isFullyRotated = true;
         }
      } else {
         double var13 = var5 * this.getCurrentMaxBodyRotationSpeed() * var2;
         var9 = MathUtil.clamp(var9, -var13, var13);
         var4 = PhysicsMath.normalizeTurnAngle((float)(var4 + var9));
         if (var7) {
            this.isFullyRotated = false;
         }
      }

      if (var8 && Math.abs(var9) > this.maxMoveTurnAngle) {
         this.moveSpeed = 0.0;
      }

      class="kw">return var4;
   }

   class="kw">protected boolean initiateDescend(@Nonnull Vector3d var1, boolean var2, String var3, @Nonnull ComponentAccessor<EntityStore> var4) {
      if (var2 && this.getMotionKind() != MotionKind.DESCENDING && this.getMotionKind() != MotionKind.DROPPING) {
         this.fallStartHeight = this.position.y;
         this.fallSpeed = 0.0;
         this.predictedFallHeight = this.dropDistance(this.position, this.maxDropHeight, var4);
         this.totalDropDistance = 0.0;
         this.computeDescendDirection(var1);
         if (this.debugModeMove) {
            LOGGER.at(Level.INFO).log("eid=%d Move: %s, descend init %s %s", this.debugEntityId, var3, this.moveSpeed, this.climbForwardDirection.toString());
         }
      }

      if (this.getMotionKind() != MotionKind.DROPPING) {
         if (this.fallStartHeight - this.position.y > this.maxClimbHeight || this.predictedFallHeight > this.maxClimbHeight + 1.0E-5) {
            if (this.debugModeMove) {
               LOGGER.at(Level.INFO)
                  .log(
                     "eid=%d Move: %s, dropping %s %s %s %s",
                     this.debugEntityId,
                     var3,
                     this.moveSpeed,
                     this.fallStartHeight - this.position.y,
                     this.predictedFallHeight,
                     this.climbForwardDirection.toString()
                  );
            }

            boolean var5 = this.getMotionKind() == MotionKind.DESCENDING;
            this.setMotionKind(MotionKind.DROPPING);
            class="kw">return var5;
         }

         if (this.getMotionKind() != MotionKind.DESCENDING) {
            if (this.debugModeMove) {
               LOGGER.at(Level.INFO).log("eid=%d Move: %s, descending %s %s", this.debugEntityId, var3, this.moveSpeed, this.climbForwardDirection.toString());
            }

            this.setMotionKind(MotionKind.DESCENDING);
         }
      }

      class="kw">return false;
   }

   class="kw">protected double updateMovementVector(@Nonnull Vector3d var1, @Nonnull Vector3d var2, @Nonnull Vector3d var3, @Nonnull Vector3d var4) {
      var2.set(var3).sub(var1).mul(var4);
      class="kw">return this.waypointDistanceSquared(var1, var3);
   }

   @Nullable
   class="kw">private BlockCollisionData discardIgnorableSlideCollisions(
      @Nonnull CollisionResult var1, @Nullable BlockCollisionData var2, @Nonnull EnumSet<RelaxedConstraint> var3
   ) {
      boolean var4 = !var3.contains(RelaxedConstraint.DAMAGE);
      double var5 = var1.slideEnd;

      while (var2 != null) {
         if (var4 && var2.willDamage) {
            class="kw">return var2;
         }

         BlockType var7 = var2.blockType;
         if (var7 == null || !var2.collisionNormal.equals(this.getWorldNormal()) || var2.collisionStart > var5) {
            class="kw">return var2;
         }

         var2 = var1.forgetFirstBlockCollision();
      }

      class="kw">return null;
   }

   class="kw">private double bisect(@Nonnull Vector3d var1, @Nonnull Vector3d var2, @Nonnull Vector3d var3, @Nonnull ComponentAccessor<EntityStore> var4) {
      this.applyActiveProbeBlockCollisionFilter(this.collisionResult);
      if (!this.isValidPosition(var1, this.collisionResult, var4)) {
         var3.set(var2);
         class="kw">return 1.0;
      } else {
         class="kw">return this.bisect(var1, var2, this, (var1x, var2x) -> {
            var1x.applyActiveProbeBlockCollisionFilter(var1x.collisionResult);
            class="kw">return var1x.isValidPosition(var2x, var1x.collisionResult, var4);
         }, var3);
      }
   }

   class="kw">private boolean validateGroundPosition(double var1, @Nonnull EnumSet<RelaxedConstraint> var3, @Nonnull ComponentAccessor<EntityStore> var4) {
      if (this.isDropBlocked(this.position, var1, false, var3, var4)) {
         this.position.set(this.lastValidPosition);
         this.isObstructed = true;
         class="kw">return true;
      } else {
         ChunkStore var5 = var4.getExternalData().getWorld().getChunkStore();
         if (!this.isValidWalkPosition(var5, this.position.x, this.position.y, this.position.z, var3)
            && this.isValidWalkPosition(var5, this.lastValidPosition.x, this.lastValidPosition.y, this.lastValidPosition.z, var3)) {
            this.position.set(this.lastValidPosition);
            this.isObstructed = true;
            class="kw">return true;
         } else {
            class="kw">return false;
         }
      }
   }

   class="kw">private double shortenSlide(@Nonnull Vector3d var1, double var2) {
      Vector3d var4 = this.getComponentSelector();
      double var5 = (this.collisionBoundingBox.max.x - this.collisionBoundingBox.min.x) * 0.1 * var4.x;
      double var7 = (this.collisionBoundingBox.max.y - this.collisionBoundingBox.min.y) * 0.1 * var4.y;
      double var9 = (this.collisionBoundingBox.max.z - this.collisionBoundingBox.min.z) * 0.1 * var4.z;
      double var11 = Math.max(Math.max(var5, Math.max(var7, var9)), 0.05);
      double var13 = var1.length() * var2;
      if (var13 > var11) {
         var2 = var2 * (var13 - var11) / var13;
      } else {
         var2 = 0.0;
      }

      class="kw">return var2;
   }

   class="kw">private double shortenMovement(@Nonnull Vector3d var1, @Nonnull Vector3d var2, @Nonnull Vector3d var3) {
      double var4 = var2.distance(var1);
      if (var4 <= 0.05) {
         class="kw">return 0.0;
      }

      var4 = (var4 - 0.05) / var4;
      NPCPhysicsMath.lerp(var1, var2, var4, var3);
      class="kw">return var4;
   }

   class="kw">private double shortenMovement(double var1) {
      double var3 = this.shortenMovement(this.lastValidPosition, this.position, this.position);
      var1 *= var3;
      if (this.debugModeMove) {
         LOGGER.at(Level.INFO).log("eid=%d Move: Collision reduction=%s triggerScale=%s", this.debugEntityId, var3, var1);
      }

      class="kw">return var1;
   }

   class="kw">private void validateTranslation(@Nonnull Vector3d var1, String var2) {
      if (this.debugModeValidateMath) {
         boolean var3 = NPCPhysicsMath.isValid(var1) && var1.lengthSquared() < 1000000.0;
         if (!var3) {
            throw new IllegalStateException(
               String.format(
                  "Walk - Translation invalid path=%s %s, moveSpeed=%s, fallSpeed=%s, pos=%s",
                  var2,
                  var1,
                  this.moveSpeed,
                  this.fallSpeed,
                  Vector3dUtil.formatShortString(this.position)
               )
            );
         }
      } else if (!NPCPhysicsMath.isValid(var1) || var1.lengthSquared() > 1000000.0) {
         var1.zero();
      }
   }

   class="kw">private void validateSpeeds(@Nonnull Ref<EntityStore> var1, @Nonnull String var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      if (this.debugModeValidateMath) {
         if (!Double.isFinite(this.moveSpeed) || !(Math.abs(this.moveSpeed) < 200.0) || !Double.isFinite(this.fallSpeed) || !(Math.abs(this.fallSpeed) < 200.0)
            )
          {
            throw new IllegalStateException(
               String.format(
                  "Walk - Invalid speed path=%s, moveSpeed=%s, fallSpeed=%s, onGround=%s canSteer=%s, pos=%s, motionKind=%s",
                  var2,
                  this.moveSpeed,
                  this.fallSpeed,
                  this.onGround,
                  this.canSteer(var1, var3),
                  Vector3dUtil.formatShortString(this.position),
                  this.getMotionKind()
               )
            );
         }
      } else {
         this.moveSpeed = MathUtil.clamp(this.moveSpeed, -200.0, 200.0);
         this.fallSpeed = MathUtil.clamp(this.fallSpeed, -200.0, 200.0);
      }
   }

   class="kw">private void lockOrientation(@Nonnull Steering var1, @Nonnull Vector3d var2, float var3) {
      var1.setYaw(var3);
      var1.setPitch(this.getPitch());
      var1.setRoll(this.getRoll());
      if (this.debugModeValidateMath && !NPCPhysicsMath.isValid(var2)) {
         throw new IllegalArgumentException("Translation invalid");
      }
   }

   class="kw">private float computeBlendHeading(float var1, float var2, double var3, double var5, double var7) {
      float var9 = this.computeBlendTurnAngle(var1, var2);
      class="kw">return this.computeBlendHeading(var1, var2, var3, var5, var9, var7);
   }

   class="kw">private float computeBlendHeading(float var1, float var2, double var3, double var5, float var7, double var8) {
      double var10 = this.getCurrentMaxBodyRotationSpeed();
      float var12 = (float)MathUtil.clamp(var3 * var10 * var8, 0.0, (float) (Math.PI / 2));
      if (this.haveBlendHeadingPosition && var5 > 0.0) {
         var7 *= (float)this.blendLevelAtTargetPosition;
         double var13 = this.waypointDistance(this.position, this.blendHeadingPosition) / var5;
         if (var13 * var10 * var8 > var7) {
            var7 = NPCPhysicsMath.turnAngle(var1, var2);
         }
      }

      var7 = MathUtil.clamp(var7, -var12, var12);
      class="kw">return PhysicsMath.normalizeTurnAngle(var1 + var7);
   }

   class="kw">private float computeBlendTurnAngle(float var1, float var2) {
      float var3 = Double.isNaN(this.blendHeading) ? var2 : (float)this.blendHeading;
      class="kw">return NPCPhysicsMath.turnAngle(var1, var3);
   }

   class="kw">private double computeClimbMove(@Nonnull Vector3d var1, double var2, double var4, @Nonnull Vector3d var6) {
      if (var4 >= var2) {
         var4 = var2;
         var2 = 0.0;
      } else {
         double var7 = var2 - var4;
         if (var7 <= 1.0E-5) {
            var4 = var2;
            var2 = 0.0;
         } else {
            var2 = var7;
         }
      }

      var6.set(var1).mul(var4);
      class="kw">return var2;
   }

   class="kw">private void computeDescendDirection(@Nonnull Vector3d var1) {
      this.climbForwardDirection.set(this.getWorldAntiNormal());
      if (!(this.descendFlatness <= 0.0)) {
         double var2 = NPCPhysicsMath.dotProduct(var1.x, 0.0, var1.z);
         if (!(var2 <= 1.0E-12)) {
            var2 = Math.sqrt(var2);
            double var4 = this.descendFlatness / var2;
            this.climbForwardDirection.x = var4 * var1.x;
            this.climbForwardDirection.z = var4 * var1.z;
            this.climbForwardDirection.normalize();
            double var6 = Math.sqrt(NPCPhysicsMath.dotProduct(this.climbForwardDirection.x, 0.0, this.climbForwardDirection.z));
            if (var6 > 1.0E-6) {
               double var8 = 1.0 + (1.0 / var6 - 1.0) * this.descendSpeedCompensation;
               this.climbForwardDirection.mul(var8);
            }
         }
      }
   }

   class="kw">private double computeClimbSpeed(double var1) {
      double var3 = this.climbSpeedConst;
      if (var1 != 0.0 && this.climbSpeedMult != 0.0) {
         var3 += this.climbSpeedMult * Math.pow(var1, this.climbSpeedPow);
      }

      class="kw">return var3;
   }

   class="kw">private boolean tryClimb(@Nonnull Vector3d var1, @Nonnull EnumSet<RelaxedConstraint> var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      boolean var4 = this.jumpHeight > 0.0;
      this.currentClimbForwardDistance = 0.0;
      this.maxClimbForwardDistance = 0.1;
      this.climbUpDistance = this.computeClimbHeight(
         this.position, var1, this.maxClimbHeight + this.jumpHeight, this.maxClimbForwardDistance, null, this.tmpClimbHeightResults, var2, var3
      );
      double var5 = this.climbUpDistance + this.jumpHeight;
      double var7 = this.tmpClimbHeightResults.y;
      if (this.climbUpDistance > this.maxClimbHeight + 1.0E-5) {
         this.climbUpDistance = 0.0;
      } else if (var4 && this.climbUpDistance >= this.minJumpHeight && var7 >= var5) {
         this.currentJumpHeight = var5;
         this.jumpDropHeight = this.currentJumpHeight - this.climbUpDistance;
         this.jumpBlockHeight = this.climbUpDistance;
         this.jumpDropDirection.set(this.getWorldAntiNormal());
         double var9 = this.climbUpDistance;
         this.climbUpDistance = this.currentJumpHeight;
         this.tmpClimbMovement.set(var1).normalize(0.4);
         this.tmpMovePosition.set(this.position).add(0.0, var9, 0.0);
         double var11 = this.maxMoveFactor(this.tmpMovePosition, this.tmpClimbMovement, var2, var3);
         this.maxClimbForwardDistance += var11 * 0.4;
         this.tmpMovePosition.fma(var11, this.tmpClimbMovement);
         this.jumping = this.maxClimbForwardDistance >= this.minJumpDistance;
      } else {
         this.jumping = false;
      }

      class="kw">return this.climbUpDistance > 0.0;
   }

   class="kw">private double computeClimbHeight(
      @Nonnull Vector3d var1,
      @Nonnull Vector3d var2,
      double var3,
      double var5,
      @Nullable Vector3d var7,
      @Nonnull Vector2d var8,
      @Nonnull EnumSet<RelaxedConstraint> var9,
      @Nonnull ComponentAccessor<EntityStore> var10
   ) {
      World var11 = var10.getExternalData().getWorld();
      ChunkStore var12 = var11.getChunkStore();
      boolean var13 = var9.contains(RelaxedConstraint.WADE);
      this.tmpResults.setCollisionByMaterial(4, var13 ? 13 : 5);
      var8.zero();
      Vector3dc var14 = this.getWorldNormal();
      this.tmpClimbMovement.set(var14).mul(var3);
      double var15 = this.maxMoveFactor(var1, this.tmpClimbMovement, var9, var10);
      var3 *= var15;
      if (var3 == 0.0) {
         class="kw">return 0.0;
      }

      this.tmpClimbMovement.set(var2).normalize(var5);
      this.tmpClimbPosition.set(var1).add(this.tmpClimbMovement);
      this.tmpClimbMovement.set(var14).mul(var3);
      boolean var17 = this.tmpResults.isComputeOverlaps();
      this.tmpResults.setComputeOverlaps(true);
      this.applyActiveProbeBlockCollisionFilter(this.tmpResults);
      CollisionModule.findCollisions(this.collisionBoundingBox, this.tmpClimbPosition, this.tmpClimbMovement, false, this.tmpResults, var10);
      this.tmpResults.setComputeOverlaps(var17);
      BlockCollisionData var18 = this.tmpResults.getFirstBlockCollision();
      Vector3dc var19 = this.getWorldAntiNormal();
      double var20 = 0.0;
      double var22 = 1.0;

      while (var18 != null) {
         BlockType var24 = var18.blockType;
         if (var24 == null || !this.isClimbable(var24, var18.fluid, var9)) {
            break;
         }

         if (var18.collisionNormal.equals(var19)) {
            if (var18.collisionStart > var20) {
               var22 = var18.collisionStart;
               break;
            }

            if (var18.collisionEnd > var20) {
               var20 = var18.collisionEnd;
               if (var20 > 1.00001) {
                  class="kw">return 0.0;
               }
            }
         }

         var18 = this.tmpResults.forgetFirstBlockCollision();
      }

      if (var20 == 0.0) {
         class="kw">return 0.0;
      }

      this.tmpClimbPosition.fma(var20, this.tmpClimbMovement);
      if (!this.isValidWalkPosition(var12, this.tmpClimbPosition.x, this.tmpClimbPosition.y, this.tmpClimbPosition.z, var9)) {
         class="kw">return 0.0;
      }

      double var27 = var3 * var20;
      var8.set(var27, var3 * var22);
      if (var7 != null) {
         var7.set(this.tmpClimbPosition);
      }

      class="kw">return var27;
   }

   class="kw">private double effectiveMaxDropHeight(@Nonnull EnumSet<RelaxedConstraint> var1) {
      class="kw">return var1.contains(RelaxedConstraint.DROP) ? this.maxDropHeightRelaxed : this.maxDropHeight;
   }

   class="kw">private boolean isDropBlocked(
      @Nonnull Vector3d var1, double var2, boolean var4, @Nonnull EnumSet<RelaxedConstraint> var5, @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      World var7 = var6.getExternalData().getWorld();
      ChunkStore var8 = var7.getChunkStore();
      boolean var9 = !var5.contains(RelaxedConstraint.DAMAGE);
      this.applyActiveProbeBlockCollisionFilter(this.tmpResults);
      if (this.debugModeValidatePositions && !this.isValidPosition(var1, this.tmpResults, var6)) {
         throw new IllegalStateException("Invalid position");
      }

      BlockCollisionData var10 = this.findDropBlockCollision(var1, var2, var6);
      if (var10 == null) {
         class="kw">return true;
      }

      this.tmpClimbPosition.set(var10.collisionPoint);
      if (var9) {
         double var11 = var10.collisionStart;

         do {
            if (var10.willDamage) {
               if (this.debugModeMove) {
                  LOGGER.at(Level.FINE)
                     .log("eid=%d Drop DMG  %.2f/%.2f/%.2f", this.debugEntityId, this.tmpClimbPosition.x, this.tmpClimbPosition.y, this.tmpClimbPosition.z);
               }

               class="kw">return true;
            }

            var10 = this.tmpResults.forgetFirstBlockCollision();
         } while (var10 != null && var10.collisionStart <= var11);
      }

      if (!this.isValidWalkPosition(var8, this.tmpClimbPosition.x, this.tmpClimbPosition.y, this.tmpClimbPosition.z, var5)) {
         if (this.debugModeMove) {
            LOGGER.at(Level.FINE)
               .log("eid=%d Drop INV  %.2f/%.2f/%.2f", this.debugEntityId, this.tmpClimbPosition.x, this.tmpClimbPosition.y, this.tmpClimbPosition.z);
         }

         class="kw">return true;
      } else {
         if (this.debugModeMove) {
            LOGGER.at(Level.FINE)
               .log("eid=%d Drop END  %.2f/%.2f/%.2f", this.debugEntityId, this.tmpClimbPosition.x, this.tmpClimbPosition.y, this.tmpClimbPosition.z);
         }

         if (var4) {
            var1.set(this.tmpClimbPosition);
         }

         class="kw">return false;
      }
   }

   class="kw">private double dropDistance(@Nonnull Vector3d var1, double var2, @Nonnull ComponentAccessor<EntityStore> var4) {
      BlockCollisionData var5 = this.findDropBlockCollision(var1, var2, var4);
      class="kw">return var5 != null ? var5.collisionStart * var2 : var2;
   }

   @Nullable
   class="kw">private BlockCollisionData findDropBlockCollision(@Nonnull Vector3d var1, double var2, @Nonnull ComponentAccessor<EntityStore> var4) {
      this.tmpResults.setCollisionByMaterial(4);
      this.tmpClimbMovement.set(this.getWorldAntiNormal()).mul(var2);
      this.applyActiveProbeBlockCollisionFilter(this.tmpResults);
      CollisionModule.findCollisions(this.collisionBoundingBox, var1, this.tmpClimbMovement, this.tmpResults, var4);
      BlockCollisionData var5 = this.tmpResults.getFirstBlockCollision();
      if (this.debugModeMove) {
         LOGGER.at(Level.FINE)
            .log(
               "eid=%d Test Drop BOX  %.2f/%.2f/%.2f %.2f/%.2f/%.2f",
               this.debugEntityId,
               this.collisionBoundingBox.min.x,
               this.collisionBoundingBox.min.y,
               this.collisionBoundingBox.min.z,
               this.collisionBoundingBox.max.x,
               this.collisionBoundingBox.max.y,
               this.collisionBoundingBox.max.z
            );
         if (var5 == null) {
            LOGGER.at(Level.FINE)
               .log(
                  "eid=%d Test Drop NONE %.2f/%.2f/%.2f %.2f/%.2f/%.2f",
                  this.debugEntityId,
                  var1.x,
                  var1.y,
                  var1.z,
                  this.tmpClimbMovement.x,
                  this.tmpClimbMovement.y,
                  this.tmpClimbMovement.z
               );
         } else {
            LOGGER.at(Level.FINE)
               .log(
                  "eid=%d Test Drop COLL %.2f/%.2f/%.2f %.2f/%.2f/%.2f dist=%s",
                  this.debugEntityId,
                  var1.x,
                  var1.y,
                  var1.z,
                  this.tmpClimbMovement.x,
                  this.tmpClimbMovement.y,
                  this.tmpClimbMovement.z,
                  var5.collisionStart * var2
               );
         }
      }

      class="kw">return var5;
   }

   class="kw">private boolean isClimbable(@Nonnull BlockType var1, @Nonnull Fluid var2, @Nonnull EnumSet<RelaxedConstraint> var3) {
      boolean var4 = var3.contains(RelaxedConstraint.DAMAGE);
      boolean var5 = var3.contains(RelaxedConstraint.FENCE);
      class="kw">return (var4 || var1.getDamageToEntities() <= 0 && var2.getDamageToEntities() <= 0)
         && (var5 || this.fenceBlockSet == Integer.MIN_VALUE || !BlockSetModule.getInstance().blockInSet(this.fenceBlockSet, var1));
   }

   class="kw">private boolean isValidWalkPosition(
      @Nonnull Ref<ChunkStore> var1,
      @Nonnull ComponentAccessor<ChunkStore> var2,
      double var3,
      double var5,
      double var7,
      @Nonnull EnumSet<RelaxedConstraint> var9
   ) {
      boolean var10 = !var9.contains(RelaxedConstraint.BREATHE);
      boolean var11 = var9.contains(RelaxedConstraint.WADE);
      if (var10) {
         if (!this.couldBreatheAtWalkPosition(var1, var2, var3, var5 + this.breathingDepth, var7)) {
            class="kw">return false;
         }

         if (this.breathingDepth == this.constraintDepth) {
            class="kw">return true;
         }
      }

      class="kw">return !var11 ? this.couldBreatheAtWalkPosition(var1, var2, var3, var5 + this.constraintDepth, var7) : true;
   }

   class="kw">private boolean couldBreatheAtWalkPosition(@Nonnull Ref<ChunkStore> var1, @Nonnull ComponentAccessor<ChunkStore> var2, double var3, double var5, double var7) {
      long var9 = WorldUtil.getPackedMaterialAndFluidAtPosition(var1, var2, var3, var5, var7);
      BlockMaterial var11 = this.isProbeBreathableBlockOverride(var1, var2, var3, var5, var7)
         ? BlockMaterial.Empty
         : BlockMaterial.VALUES[MathUtil.unpackLeft(var9)];
      int var12 = MathUtil.unpackRight(var9);
      class="kw">return this.role.couldBreathe(var11, var12);
   }

   class="kw">private boolean isProbeBreathableBlockOverride(
      @Nonnull Ref<ChunkStore> var1, @Nonnull ComponentAccessor<ChunkStore> var2, double var3, double var5, double var7
   ) {
      if (this.activeProbeBreathableBlockOverride == null) {
         class="kw">return false;
      }

      BlockChunk var9 = var2.getComponent(var1, BlockChunk.getComponentType());
      if (var9 == null) {
         class="kw">return false;
      }

      int var10 = var9.getBlock(MathUtil.floor(var3), MathUtil.floor(var5), MathUtil.floor(var7));
      class="kw">return this.activeProbeBreathableBlockOverride.test(var10);
   }

   class="kw">private boolean isValidWalkPosition(@Nonnull ChunkStore var1, double var2, double var4, double var6, @Nonnull EnumSet<RelaxedConstraint> var8) {
      long var9 = ChunkUtil.indexChunkFromBlock(var2, var6);
      Ref var11 = var1.getChunkReference(var9);
      class="kw">return var11 != null && var11.isValid() ? this.isValidWalkPosition(var11, var1.getStore(), var2, var4, var6, var8) : false;
   }

   class="kw">private double maxMoveFactor(
      @Nonnull Vector3d var1, @Nonnull Vector3d var2, @Nonnull EnumSet<RelaxedConstraint> var3, @Nonnull ComponentAccessor<EntityStore> var4
   ) {
      this.applyActiveProbeBlockCollisionFilter(this.tmpResults);
      CollisionModule.findCollisions(this.collisionBoundingBox, var1, var2, this.tmpResults, var4);
      BlockCollisionData var5;
      if (var2.y != 0.0) {
         var5 = this.tmpResults.getFirstBlockCollision();
      } else {
         var5 = this.discardIgnorableSlideCollisions(this.tmpResults, this.tmpResults.getFirstBlockCollision(), var3);
      }

      class="kw">return var5 == null ? 1.0 : MathUtil.clamp(var5.collisionStart, 0.0, 1.0);
   }

   class="kw">private void applyActiveProbeBlockCollisionFilter(@Nonnull CollisionResult var1) {
      if (this.activeProbeBlockCollisionFilter != null) {
         var1.setBlockCollisionFilter(this.activeProbeBlockCollisionFilter);
      }
   }

   class="kw">public enum AscentAnimationType class="kw">implements Supplier<String> {
      Walk("Play walk animation"),
      Jump("Play jump animation"),
      Climb("Play climb animation"),
      Fly("Play fly animation"),
      Idle("Play idle animation");

      class="kw">private class="kw">final String description;

      AscentAnimationType(String nullxx) {
         this.description = nullxx;
      }

      class="kw">public String get() {
         class="kw">return this.description;
      }
   }

   class="kw">public enum DescentAnimationType class="kw">implements Supplier<String> {
      Walk("Play walk animation"),
      Fall("Play fall animation"),
      Idle("Play idle animation");

      class="kw">private class="kw">final String description;

      DescentAnimationType(String nullxx) {
         this.description = nullxx;
      }

      class="kw">public String get() {
         class="kw">return this.description;
      }
   }
}