Example #1
0
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (controls.IsFlying)
            {
                pos.Motion.Add(controls.FlyVector.X, (controls.Up || controls.Down) ? 0 : controls.FlyVector.Y, controls.FlyVector.Z);

                float moveSpeed = dt * GlobalConstants.BaseMoveSpeed * controls.MovespeedMultiplier / 2;

                pos.Motion.Add(0, (controls.Up ? moveSpeed : 0) + (controls.Down ? -moveSpeed : 0), 0);
            }
            else
            {
                if (controls.IsClimbing)
                {
                    pos.Motion.Add(controls.WalkVector);
                    pos.Motion.X *= System.Math.Pow(1 - wallDragFactor, dt * 60);
                    pos.Motion.Y *= System.Math.Pow(1 - wallDragFactor, dt * 60);
                    pos.Motion.Z *= System.Math.Pow(1 - wallDragFactor, dt * 60);
                }
                else
                {
                    float strength = airMovingStrength * (float)System.Math.Min(1, entity.Stats?.GetBlended("walkspeed") ?? 1.0) * dt * 60f;

                    if (!controls.Jump && entity is EntityPlayer)
                    {
                        strength      = airMovingStrengthFalling;
                        pos.Motion.X *= (float)System.Math.Pow(0.98f, dt * 33);
                        pos.Motion.Z *= (float)System.Math.Pow(0.98f, dt * 33);
                    }

                    pos.Motion.Add(controls.WalkVector.X * strength, controls.WalkVector.Y * strength, controls.WalkVector.Z * strength);
                }
            }
        }
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            Block belowBlock = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y - 0.05f), (int)pos.Z);

            if (!entity.Swimming && entity.Alive)
            {
                double multiplier = (entity as EntityAgent).GetWalkSpeedMultiplier(groundDragFactor);

                motionDelta.Set(
                    motionDelta.X + (controls.WalkVector.X * multiplier - motionDelta.X) * belowBlock.DragMultiplier,
                    0,
                    motionDelta.Z + (controls.WalkVector.Z * multiplier - motionDelta.Z) * belowBlock.DragMultiplier
                    );

                pos.Motion.Add(motionDelta.X, 0, motionDelta.Z);
            }

            if (controls.Jump && entity.World.ElapsedMilliseconds - lastJump > 500 && entity.Alive && !entity.Swimming)
            {
                lastJump = entity.World.ElapsedMilliseconds;

                pos.Motion.Y = GlobalConstants.BaseJumpForce * dt;
                EntityPlayer entityPlayer = entity as EntityPlayer;
                IPlayer      player       = entityPlayer != null?entityPlayer.World.PlayerByUid(entityPlayer.PlayerUID) : null;

                entity.PlayEntitySound("jump", player, false);
            }

            if (!entity.Swimming)
            {
                pos.Motion.X *= (1 - groundDragFactor);
                pos.Motion.Z *= (1 - groundDragFactor);
            }
        }
Example #3
0
        static void Prefix(EntityBehaviorPlayerPhysics __instance, Entity entity, float dt)
        {
            // FileLog.Log("Logs onto desktop Logger");

            // Continue if entity is a player
            if (entity is EntityPlayer entityPlayer)
            {
                // Assign useful variables
                EntityControls controls  = entityPlayer.Controls;
                string         playerUID = entity.WatchedAttributes.GetString("playerUID");
                IPlayer        player    = entity.World.PlayerByUid(playerUID);

                if (PlayerManager.Instance == null)
                {
                    return;
                }

                if (player == null)
                {
                    return;
                }

                PlayerData playerData = PlayerManager.Instance.GetOrAddPlayerData(player);

                // Sitting Logic
                if (playerData != null && playerData.IsPlayerSitting())
                {
                    // Disable Movement
                    controls.StopAllMovement();
                }
            }
        }
Example #4
0
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (controls.IsFlying)
            {
                pos.Motion.Add(controls.FlyVector.X, (controls.Up || controls.Down) ? 0 : controls.FlyVector.Y, controls.FlyVector.Z);

                float moveSpeed = dt * GlobalConstants.BaseMoveSpeed * controls.MovespeedMultiplier / 2;

                pos.Motion.Add(0, (controls.Up ? moveSpeed : 0) + (controls.Down ? -moveSpeed : 0), 0);
            }
            else
            {
                if (controls.IsClimbing)
                {
                    pos.Motion.Add(controls.WalkVector);
                    pos.Motion.X *= (1 - wallDragFactor);
                    pos.Motion.Y *= (1 - wallDragFactor);
                    pos.Motion.Z *= (1 - wallDragFactor);
                }
                else
                {
                    pos.Motion.Add(controls.WalkVector.X * airMovingStrength, controls.WalkVector.Y * airMovingStrength, controls.WalkVector.Z * airMovingStrength);
                }
            }
        }
Example #5
0
        private bool HandleSteppingOnBlocks(EntityPos pos, EntityControls controls)
        {
            if (!controls.TriesToMove || (!entity.OnGround && !entity.Swimming))
            {
                return(false);
            }

            Cuboidd entityCollisionBox = entity.CollisionBox.ToDouble();

            entityCollisionBox.Translate(pos.X, pos.Y, pos.Z);

            Vec3d walkVec    = controls.WalkVector;
            Vec3d testVec    = new Vec3d();
            Vec3d testMotion = new Vec3d();

            Cuboidd stepableBox = findSteppableCollisionbox(entityCollisionBox, pos.Motion.Y, walkVec);

            // Must have walked into a slab
            if (stepableBox != null)
            {
                return
                    (tryStep(pos, testMotion.Set(pos.Motion.X, pos.Motion.Y, pos.Motion.Z), stepableBox, entityCollisionBox) ||
                     tryStep(pos, testMotion.Set(pos.Motion.X, pos.Motion.Y, 0), findSteppableCollisionbox(entityCollisionBox, pos.Motion.Y, testVec.Set(walkVec.X, walkVec.Y, 0)), entityCollisionBox) ||
                     tryStep(pos, testMotion.Set(0, pos.Motion.Y, pos.Motion.Z), findSteppableCollisionbox(entityCollisionBox, pos.Motion.Y, testVec.Set(0, walkVec.Y, walkVec.Z)), entityCollisionBox)
                    );
            }

            return(false);
        }
Example #6
0
 public override bool Applicable(Entity entity, EntityPos pos, EntityControls controls)
 {
     return
         ((!controls.IsFlying && entity.Properties.Habitat != EnumHabitat.Air) &&
          (entity.Properties.Habitat != EnumHabitat.Sea || !entity.Swimming) &&
          !controls.IsClimbing
         );
 }
Example #7
0
        public void TickEntityPhysics(EntityPos pos, EntityControls controls, float dt)
        {
            IBlockAccessor blockAccessor = entity.World.BlockAccessor;

            foreach (EntityLocomotion locomotor in Locomotors)
            {
                if (locomotor.Applicable(entity, pos, controls))
                {
                    locomotor.Apply(dt, entity, pos, controls);
                }
            }

            EntityAgent agent = entity as EntityAgent;

            if (agent?.MountedOn != null)
            {
                pos.SetFrom(agent.MountedOn.MountPosition);
                pos.Motion.X = 0;
                pos.Motion.Y = 0;
                pos.Motion.Z = 0;
                return;
            }


            pos.Motion.X = GameMath.Clamp(pos.Motion.X, -10, 10);
            pos.Motion.Y = GameMath.Clamp(pos.Motion.Y, -10, 10);
            pos.Motion.Z = GameMath.Clamp(pos.Motion.Z, -10, 10);

            if (!controls.NoClip)
            {
                DisplaceWithBlockCollision(pos, controls, dt);
            }
            else
            {
                pos.X += pos.Motion.X;
                pos.Y += pos.Motion.Y;
                pos.Z += pos.Motion.Z;

                entity.Swimming     = false;
                entity.FeetInLiquid = false;
                entity.OnGround     = false;
            }



            // Shake the player violently when falling at high speeds

            /*if (movedy < -50)
             * {
             *  pos.X += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             *  pos.Z += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             * }
             */

            //return result;
        }
Example #8
0
        public virtual void GameTick(Entity entity, float dt)
        {
            EntityControls controls = ((EntityAgent)entity).Controls;

            TickEntityPhysics(entity.ServerPos, controls, dt);
            if (entity.World is IServerWorldAccessor)
            {
                entity.Pos.SetFrom(entity.ServerPos);
            }
        }
Example #9
0
        public virtual void GameTick(Entity entity, float dt)
        {
            EntityControls controls = ((EntityAgent)entity).Controls;

            TickEntityPhysics(entity.ServerPos, controls, dt);  // this was entity.ServerPos - wtf? - apparently needed so they don't glitch through terrain o.O
            if (entity.World is IServerWorldAccessor)
            {
                entity.Pos.SetFrom(entity.ServerPos);
            }
        }
Example #10
0
        public virtual void TickEntityPhysicsPre(Entity entity, float dt)
        {
            prevPos.Set(entity.Pos.X, entity.Pos.Y, entity.Pos.Z);
            EntityControls controls = ((EntityAgent)entity).Controls;

            TickEntityPhysics(entity.ServerPos, controls, dt);  // this was entity.ServerPos - wtf? - apparently needed so they don't glitch through terrain o.O

            if (entity.World.Side == EnumAppSide.Server)
            {
                entity.Pos.SetFrom(entity.ServerPos);
            }
        }
Example #11
0
        private void HandleSneaking(EntityPos pos, EntityControls controls, float dt)
        {
            if (!controls.Sneak || !entity.OnGround || pos.Motion.Y > 0)
            {
                return;
            }

            // Sneak to prevent falling off blocks
            Vec3d testPosition = new Vec3d();

            testPosition.Set(pos.X, pos.Y - GlobalConstants.GravityPerSecond * dt, pos.Z);

            // Only apply this if he was on the ground in the first place
            if (!collisionTester.IsColliding(entity.World.BlockAccessor, sneakTestCollisionbox, testPosition))
            {
                return;
            }

            Block belowBlock = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)pos.Y - 1, (int)pos.Z);


            // Test for X
            testPosition.Set(outposition.X, outposition.Y - GlobalConstants.GravityPerSecond * dt, pos.Z);
            if (!collisionTester.IsColliding(entity.World.BlockAccessor, sneakTestCollisionbox, testPosition))
            {
                // Weird hack so you can climb down ladders more easily
                if (belowBlock.Climbable)
                {
                    outposition.X += (pos.X - outposition.X) / 10;
                }
                else
                {
                    outposition.X = pos.X;
                }
            }


            // Test for Z
            testPosition.Set(pos.X, outposition.Y - GlobalConstants.GravityPerSecond * dt, outposition.Z);
            if (!collisionTester.IsColliding(entity.World.BlockAccessor, sneakTestCollisionbox, testPosition))
            {
                // Weird hack so you can climb down ladders more easily
                if (belowBlock.Climbable)
                {
                    outposition.Z += (pos.Z - outposition.Z) / 10;
                }
                else
                {
                    outposition.Z = pos.Z;
                }
            }
        }
Example #12
0
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (entity.FeetInLiquid || entity.Swimming)
            {
                pos.Motion *= (float)Math.Pow(waterDragValue, dt * 33);
            }
            else
            {
                pos.Motion *= (float)Math.Pow(airDragValue, dt * 33);
            }

            if (controls.IsFlying)
            {
                pos.Motion *= (float)Math.Pow(GlobalConstants.AirDragFlying, dt * 33);
            }
        }
Example #13
0
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (entity.Swimming)
            {
                if ((controls.TriesToMove || controls.Jump) && entity.World.ElapsedMilliseconds - lastPush > 2000)
                {
                    push     = 8f;
                    lastPush = entity.World.ElapsedMilliseconds;
                    string playerUID = entity is EntityPlayer ? ((EntityPlayer)entity).PlayerUID : null;
                    entity.PlayEntitySound("swim", playerUID == null ? null : entity.World.PlayerByUid(playerUID));
                    EntityAgent.SplashParticleProps.BasePos.Set(pos.X, pos.Y + 0.25f, pos.Z);
                    entity.World.SpawnParticles(EntityAgent.AirBubbleParticleProps);
                }
                else
                {
                    push = Math.Max(1, push - 0.1f);
                }

                double yMot = 0;
                if (controls.Jump)
                {
                    yMot = push * 0.001f;
                }
                else
                {
                    yMot = controls.FlyVector.Y * (1 + push) * 0.03f;
                }


                pos.Motion.Add(
                    controls.FlyVector.X * (1 + push) * 0.03f,
                    yMot,
                    controls.FlyVector.Z * (1 + push) * 0.03f
                    );
            }


            // http://fooplot.com/plot/kg6l1ikyx2

            /*float x = entity.Pos.Motion.Length();
             * if (x > 0)
             * {
             *  pos.Motion.Normalize();
             *  pos.Motion *= (float)Math.Log(x + 1) / 1.5f;
             *
             * }*/
        }
Example #14
0
        private bool TryStepSmooth(EntityControls controls, EntityPos pos, Vec2d walkVec, float dtFac, List <Cuboidd> stepableBoxes, Cuboidd entityCollisionBox)
        {
            if (stepableBoxes == null || stepableBoxes.Count == 0)
            {
                return(false);
            }
            double gravityOffset = 0.03; // This added constant value is a fugly hack because outposition has gravity added, but has not adjusted its position to the ground floor yet

            var walkVecOrtho = new Vec2d(walkVec.Y, -walkVec.X).Normalize();

            var maxX = Math.Abs(walkVecOrtho.X * 0.3) + 0.001;
            var minX = -maxX;
            var maxZ = Math.Abs(walkVecOrtho.Y * 0.3) + 0.001;
            var minZ = -maxZ;
            var col  = new Cuboidf((float)minX, entity.CollisionBox.Y1, (float)minZ, (float)maxX, entity.CollisionBox.Y2, (float)maxZ);

            double newYPos   = pos.Y;
            bool   foundStep = false;

            foreach (var stepableBox in stepableBoxes)
            {
                double heightDiff = stepableBox.Y2 - entityCollisionBox.Y1 + gravityOffset;
                Vec3d  steppos    = new Vec3d(GameMath.Clamp(outposition.X, stepableBox.MinX, stepableBox.MaxX), outposition.Y + heightDiff, GameMath.Clamp(outposition.Z, stepableBox.MinZ, stepableBox.MaxZ));

                bool canStep = !collisionTester.IsColliding(entity.World.BlockAccessor, col, steppos, false);

                if (canStep)
                {
                    double elevateFactor = controls.Sprint ? 0.10 : controls.Sneak ? 0.025 : 0.05;
                    if (!stepableBox.IntersectsOrTouches(entityCollisionBox))
                    {
                        newYPos = Math.Max(newYPos, Math.Min(pos.Y + elevateFactor * dtFac, stepableBox.Y2 - entity.CollisionBox.Y1 + gravityOffset));
                    }
                    else
                    {
                        newYPos = Math.Max(newYPos, pos.Y + elevateFactor * dtFac);
                    }
                    foundStep = true;
                }
            }
            if (foundStep)
            {
                pos.Y = newYPos;
                collisionTester.ApplyTerrainCollision(entity, pos, dtFac, ref outposition);
            }
            return(foundStep);
        }
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            Block belowBlock = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y - 0.05f), (int)pos.Z);

            accum = Math.Min(1, accum + dt);
            float frametime = 1 / 60f;

            while (accum > frametime)
            {
                accum -= frametime;

                if (!entity.Swimming && entity.Alive)
                {
                    // Apply walk motion
                    double multiplier = (entity as EntityAgent).GetWalkSpeedMultiplier(groundDragFactor);

                    motionDelta.Set(
                        motionDelta.X + (controls.WalkVector.X * multiplier - motionDelta.X) * belowBlock.DragMultiplier,
                        0,
                        motionDelta.Z + (controls.WalkVector.Z * multiplier - motionDelta.Z) * belowBlock.DragMultiplier
                        );

                    pos.Motion.Add(motionDelta.X, 0, motionDelta.Z);
                }

                if (!entity.Swimming)
                {
                    // Apply ground drag
                    double dragstrength = 1 - groundDragFactor;

                    pos.Motion.X *= dragstrength;
                    pos.Motion.Z *= dragstrength;
                }
            }

            if (controls.Jump && entity.World.ElapsedMilliseconds - lastJump > 500 && entity.Alive && !entity.Swimming)
            {
                // Apply jump motion
                lastJump     = entity.World.ElapsedMilliseconds;
                pos.Motion.Y = GlobalConstants.BaseJumpForce * 1 / 60f;

                EntityPlayer entityPlayer = entity as EntityPlayer;
                IPlayer      player       = entityPlayer != null?entityPlayer.World.PlayerByUid(entityPlayer.PlayerUID) : null;

                entity.PlayEntitySound("jump", player, false);
            }
        }
Example #16
0
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (entity.Swimming && controls.TriesToMove)
            {
                return;
            }
            if (!entity.ApplyGravity)
            {
                return;
            }


            if (pos.Y > -100)
            {
                pos.Motion.Y -= (gravityPerSecond * dt + Math.Max(0, -0.015f * pos.Motion.Y)) * (entity.FeetInLiquid ? 0.33f : 1f);
            }
        }
Example #17
0
//-------------------------------------------------------------------------------------------
    private void AddControl(Random rnd)
    {
        int x = rnd.Next(10000);

        //EntityDataSource eds = new EntityDataSource();
        //eds.ID = "DetailsDataSource" + x.ToString();
        //eds.EnableUpdate = true;
        //eds.EntityTypeFilter = table.EntityType.Name;

        ////eds.EntitySetName = "Accounting_Accounts";
        ////eds.ContextTypeName = "WeavverEntityContext";
        ////eds.Where = "it.id = @id";
        ////eds.WhereParameters.Add("id", DbType.Guid, "3d322c57-2b4a-4b27-8187-2094931eb2ca");
        //AddedControls.Controls.Add(eds);


        //DynamicDataManager ddm = new DynamicDataManager();
        //ddm.ID = "DynamicDataManager3";
        //ddm.AutoLoadForeignKeys = true;
        //DataControlReference ddr = new DataControlReference();
        //ddr.ControlID = "FormView3";
        //ddm.DataControls.Add(ddr);


        //AddedControls.Controls.Add(ddm);

        FormView fv = new FormView();

        fv.ID           = "FormView" + x.ToString();
        fv.DataSourceID = "GridDataSource";
        YourTemplate yt = new YourTemplate();

        fv.ItemTemplate = yt;


        //fv.ItemTemplate.Controls.Add(de);

        AddedControls.Controls.Add(fv);

        DynamicDataManager1.RegisterControl(fv);

        EntityControls.Update();
    }
Example #18
0
        public override bool PreAI(NPC npc)
        {
            EntityControls.ApplyFakeTarget(npc, this.FakeTarget, this.FakeTargetPosition);

            if (this.LockedAI0.HasValue)
            {
                npc.ai[0] = this.LockedAI0.Value;
            }
            if (this.LockedAI1.HasValue)
            {
                npc.ai[1] = this.LockedAI1.Value;
            }
            if (this.LockedAI2.HasValue)
            {
                npc.ai[2] = this.LockedAI2.Value;
            }
            if (this.LockedAI3.HasValue)
            {
                npc.ai[3] = this.LockedAI3.Value;
            }

            return(base.PreAI(npc));
        }
Example #19
0
        public float[] GetControls()
        {
            IPlayer        player = capi.World.Player;
            EntityControls c      = player.Entity.Controls;

            return(new float[]
            {
                c.Backward ? 1 : 0,       //0
                c.Down ? 1 : 0,           //1
                c.FloorSitting ? 1 : 0,   //2
                c.Forward ? 1 : 0,        //3
                c.Jump ? 1 : 0,           //4
                c.Left ? 1 : 0,           //5
                c.LeftMouseDown ? 1 : 0,  //6
                c.Right ? 1 : 0,          //7
                c.RightMouseDown ? 1 : 0, //8
                c.Sitting ? 1 : 0,        //9
                c.Sneak ? 1 : 0,          //10
                c.Sprint ? 1 : 0,         //11
                c.TriesToMove ? 1 : 0,    // 12
                c.Up ? 1 : 0,             //13
            });
        }
        public void Apply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            DoApply(dt, entity, pos, controls);

            appliedMilliseconds += (int)(dt * 1000);
        }
 public abstract void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls);
 public abstract bool Applicable(Entity entity, EntityPos pos, EntityControls controls);
Example #23
0
 public override bool Applicable(Entity entity, EntityPos pos, EntityControls controls)
 {
     return(controls.IsFlying || (!entity.Collided && !entity.FeetInLiquid));
 }
        public override void GameTick(Entity entity, float dt)
        {
            EntityPlayer   entityplayer = entity as EntityPlayer;
            EntityControls controls     = entityplayer.Controls;

            string  playerUID = entity.WatchedAttributes.GetString("playerUID");
            IPlayer player    = entity.World.PlayerByUid(playerUID);

            if (entity.World is IServerWorldAccessor && ((IServerPlayer)player).ConnectionState != EnumClientState.Playing)
            {
                return;
            }

            if (player != null)
            {
                IClientWorldAccessor clientWorld = entity.World as IClientWorldAccessor;

                // Tyron Nov. 10 2020: This line of code was from August 2020 where it fixed jitter of other players related to climbing ladders?
                // Cannot repro. But what I can repro is this line breaks player animations. They are stuck in a permanent land pose, so disabled for now.
                //if (clientWorld != null && clientWorld.Player.ClientId != player.ClientId) return;

                // We pretend the entity is flying to disable gravity so that EntityBehaviorInterpolatePosition system
                // can work better
                controls.IsFlying            = player.WorldData.FreeMove || (clientWorld != null && clientWorld.Player.ClientId != player.ClientId);
                controls.NoClip              = player.WorldData.NoClip;
                controls.MovespeedMultiplier = player.WorldData.MoveSpeedMultiplier;
            }

            EntityPos pos = entity.World is IServerWorldAccessor ? entity.ServerPos : entity.Pos;



            if (controls.TriesToMove && player is IClientPlayer)
            {
                IClientPlayer cplr = player as IClientPlayer;

                float prevYaw = pos.Yaw;

                if (entity.Swimming)
                {
                    float prevPitch = pos.Pitch;
                    pos.Yaw   = cplr.CameraYaw;
                    pos.Pitch = cplr.CameraPitch;
                    controls.CalcMovementVectors(pos, dt);
                    pos.Yaw   = prevYaw;
                    pos.Pitch = prevPitch;
                }
                else
                {
                    pos.Yaw = cplr.CameraYaw;
                    controls.CalcMovementVectors(pos, dt);
                    pos.Yaw = prevYaw;
                }

                float desiredYaw = (float)Math.Atan2(controls.WalkVector.X, controls.WalkVector.Z) - GameMath.PIHALF;

                float yawDist = GameMath.AngleRadDistance(entityplayer.WalkYaw, desiredYaw);
                entityplayer.WalkYaw += GameMath.Clamp(yawDist, -8 * dt * GlobalConstants.OverallSpeedMultiplier, 8 * dt * GlobalConstants.OverallSpeedMultiplier);
                entityplayer.WalkYaw  = GameMath.Mod(entityplayer.WalkYaw, GameMath.TWOPI);

                if (entity.Swimming)
                {
                    float desiredPitch = -(float)Math.Sin(pos.Pitch); // (float)controls.FlyVector.Y * GameMath.PI;
                    float pitchDist    = GameMath.AngleRadDistance(entityplayer.WalkPitch, desiredPitch);
                    entityplayer.WalkPitch += GameMath.Clamp(pitchDist, -2 * dt * GlobalConstants.OverallSpeedMultiplier, 2 * dt * GlobalConstants.OverallSpeedMultiplier);
                    entityplayer.WalkPitch  = GameMath.Mod(entityplayer.WalkPitch, GameMath.TWOPI);
                }
                else
                {
                    entityplayer.WalkPitch = 0;
                }
            }
            else
            {
                controls.CalcMovementVectors(pos, dt);
            }

            TickEntityPhysics(pos, controls, dt);
        }
Example #25
0
        public void TickEntityPhysics(EntityPos pos, EntityControls controls, float dt)
        {
            float dtFac = 60 * dt;

            // This seems to make creatures clip into the terrain. Le sigh.
            // Since we currently only really need it for when the creature is dead, let's just use it only there

            // Also running animations for all nearby living entities is pretty CPU intensive so
            // the AnimationManager also just ticks if the entity is in view or dead
            if (!entity.Alive)
            {
                AdjustCollisionBoxToAnimation(dtFac);
            }


            foreach (EntityLocomotion locomotor in Locomotors)
            {
                if (locomotor.Applicable(entity, pos, controls))
                {
                    locomotor.Apply(dt, entity, pos, controls);
                }
            }

            EntityAgent agent = entity as EntityAgent;

            if (agent?.MountedOn != null)
            {
                pos.SetFrom(agent.MountedOn.MountPosition);
                pos.Motion.X = 0;
                pos.Motion.Y = 0;
                pos.Motion.Z = 0;
                return;
            }

            pos.Motion.X = GameMath.Clamp(pos.Motion.X, -10, 10);
            pos.Motion.Y = GameMath.Clamp(pos.Motion.Y, -10, 10);
            pos.Motion.Z = GameMath.Clamp(pos.Motion.Z, -10, 10);

            if (!controls.NoClip)
            {
                DisplaceWithBlockCollision(pos, controls, dt);
            }
            else
            {
                pos.X += pos.Motion.X * dt * 60f;
                pos.Y += pos.Motion.Y * dt * 60f;
                pos.Z += pos.Motion.Z * dt * 60f;

                entity.Swimming     = false;
                entity.FeetInLiquid = false;
                entity.OnGround     = false;
            }



            // Shake the player violently when falling at high speeds

            /*if (movedy < -50)
             * {
             *  pos.X += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             *  pos.Z += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             * }
             */

            //return result;
        }
 public override bool Applicable(Entity entity, EntityPos pos, EntityControls controls)
 {
     return(entity.FeetInLiquid);
 }
        public override void DoApply(float dt, Entity entity, EntityPos pos, EntityControls controls)
        {
            if (entity.Swimming && entity.Alive)
            {
                string playerUID = entity is EntityPlayer ? ((EntityPlayer)entity).PlayerUID : null;


                if ((controls.TriesToMove || controls.Jump) && entity.World.ElapsedMilliseconds - lastPush > 2000 && playerUID != null)
                {
                    push     = 8f;
                    lastPush = entity.World.ElapsedMilliseconds;
                    entity.PlayEntitySound("swim", playerUID == null ? null : entity.World.PlayerByUid(playerUID));
                }
                else
                {
                    push = Math.Max(1f, push - 0.1f);
                }

                Block inblock             = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y), (int)pos.Z);
                Block aboveblock          = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y + 1), (int)pos.Z);
                Block twoaboveblock       = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y + 2), (int)pos.Z);
                float waterY              = (int)pos.Y + inblock.LiquidLevel / 8f + (aboveblock.IsLiquid() ? 9 / 8f : 0) + (twoaboveblock.IsLiquid() ? 9 / 8f : 0);
                float bottomSubmergedness = waterY - (float)pos.Y;

                // 0 = at swim line
                // 1 = completely submerged
                float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness - ((float)entity.SwimmingOffsetY), 0, 1);
                swimlineSubmergedness = Math.Min(1, swimlineSubmergedness + 0.075f);


                double yMot = 0;
                if (controls.Jump)
                {
                    yMot = 0.005f * swimlineSubmergedness;
                }
                else
                {
                    yMot = controls.FlyVector.Y * (1 + push) * 0.03f * swimlineSubmergedness;
                }

                pos.Motion.Add(
                    controls.FlyVector.X * (1 + push) * 0.03f,
                    yMot,
                    controls.FlyVector.Z * (1 + push) * 0.03f
                    );
            }


            Block block = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)pos.Y, (int)pos.Z);

            if (block.PushVector != null)
            {
                pos.Motion.Add(block.PushVector);
            }

            // http://fooplot.com/plot/kg6l1ikyx2

            /*float x = entity.Pos.Motion.Length();
             * if (x > 0)
             * {
             *  pos.Motion.Normalize();
             *  pos.Motion *= (float)Math.Log(x + 1) / 1.5f;
             *
             * }*/
        }
Example #28
0
        public void DisplaceWithBlockCollision(EntityPos pos, EntityControls controls, float dt)
        {
            IBlockAccessor blockAccess = entity.World.BlockAccessor;

            nextPosition.Set(pos.X + pos.Motion.X, pos.Y + pos.Motion.Y, pos.Z + pos.Motion.Z);
            bool falling            = pos.Motion.Y < 0;
            bool feetInLiquidBefore = entity.FeetInLiquid;
            bool onGroundBefore     = entity.OnGround;
            bool swimmingBefore     = entity.Swimming;

            double prevYMotion = pos.Motion.Y;

            controls.IsClimbing = false;

            if (!onGroundBefore && entity.Properties.CanClimb == true)
            {
                int height = (int)Math.Ceiling(entity.CollisionBox.Y2);

                entityBox.Set(entity.CollisionBox).Translate(pos.X, pos.Y, pos.Z);

                for (int dy = 0; dy < height; dy++)
                {
                    tmpPos.Set((int)pos.X, (int)pos.Y + dy, (int)pos.Z);
                    Block nblock = blockAccess.GetBlock(tmpPos);
                    if (!nblock.Climbable && !entity.Properties.CanClimbAnywhere)
                    {
                        continue;
                    }

                    Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                    if (collBoxes == null)
                    {
                        continue;
                    }

                    for (int i = 0; i < collBoxes.Length; i++)
                    {
                        double dist = entityBox.ShortestDistanceFrom(collBoxes[i], tmpPos);
                        controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                        if (controls.IsClimbing)
                        {
                            entity.ClimbingOnFace = null;
                            break;
                        }
                    }
                }

                for (int i = 0; !controls.IsClimbing && i < BlockFacing.HORIZONTALS.Length; i++)
                {
                    BlockFacing facing = BlockFacing.HORIZONTALS[i];
                    for (int dy = 0; dy < height; dy++)
                    {
                        tmpPos.Set((int)pos.X + facing.Normali.X, (int)pos.Y + dy, (int)pos.Z + facing.Normali.Z);
                        Block nblock = blockAccess.GetBlock(tmpPos);
                        if (!nblock.Climbable && !entity.Properties.CanClimbAnywhere)
                        {
                            continue;
                        }

                        Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                        if (collBoxes == null)
                        {
                            continue;
                        }

                        for (int j = 0; j < collBoxes.Length; j++)
                        {
                            double dist = entityBox.ShortestDistanceFrom(collBoxes[j], tmpPos);
                            controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                            if (controls.IsClimbing)
                            {
                                entity.ClimbingOnFace = facing;
                                break;
                            }
                        }
                    }
                }
            }


            if (controls.IsClimbing)
            {
                if (controls.WalkVector.Y == 0)
                {
                    pos.Motion.Y = controls.Sneak ? Math.Max(-0.07, pos.Motion.Y - 0.07) : pos.Motion.Y;
                    if (controls.Jump)
                    {
                        pos.Motion.Y = 0.04;
                    }
                }

                nextPosition.Set(pos.X + pos.Motion.X, pos.Y + pos.Motion.Y, pos.Z + pos.Motion.Z);
            }

            collisionTester.ApplyTerrainCollision(entity, pos, ref outposition, !(entity is EntityPlayer));

            bool isStepping = HandleSteppingOnBlocks(pos, controls);

            HandleSneaking(pos, controls, dt);



            if (blockAccess.IsNotTraversable((int)(pos.X + pos.Motion.X), (int)pos.Y, (int)pos.Z))
            {
                outposition.X = pos.X;
            }
            if (blockAccess.IsNotTraversable((int)pos.X, (int)(pos.Y + pos.Motion.Y), (int)pos.Z))
            {
                outposition.Y = pos.Y;
            }
            if (blockAccess.IsNotTraversable((int)pos.X, (int)pos.Y, (int)(pos.Z + pos.Motion.Z)))
            {
                outposition.Z = pos.Z;
            }

            pos.SetPos(outposition);


            // Set the players motion to zero if he collided.

            if ((nextPosition.X < outposition.X && pos.Motion.X < 0) || (nextPosition.X > outposition.X && pos.Motion.X > 0))
            {
                pos.Motion.X = 0;
            }

            if ((nextPosition.Y < outposition.Y && pos.Motion.Y < 0) || (nextPosition.Y > outposition.Y && pos.Motion.Y > 0))
            {
                pos.Motion.Y = 0;
            }

            if ((nextPosition.Z < outposition.Z && pos.Motion.Z < 0) || (nextPosition.Z > outposition.Z && pos.Motion.Z > 0))
            {
                pos.Motion.Z = 0;
            }



            Block block       = blockAccess.GetBlock((int)pos.X, (int)(pos.Y), (int)pos.Z);
            Block aboveblock  = blockAccess.GetBlock((int)pos.X, (int)(pos.Y + 1), (int)pos.Z);
            Block middleBlock = blockAccess.GetBlock((int)pos.X, (int)(pos.Y + entity.CollisionBox.Y1 + entity.CollisionBox.Y2 * 0.66f), (int)pos.Z);


            entity.OnGround     = (entity.CollidedVertically && falling && !controls.IsClimbing) || isStepping;
            entity.FeetInLiquid = block.IsLiquid() && ((block.LiquidLevel + (aboveblock.LiquidLevel > 0 ? 1 : 0)) / 8f >= pos.Y - (int)pos.Y);
            entity.Swimming     = middleBlock.IsLiquid();
            //    Console.WriteLine(entity.World.Side + ": "+ entity.OnGround + " / " + pos.Y);

            if (!onGroundBefore && entity.OnGround)
            {
                entity.OnFallToGround(prevYMotion);
            }

            if ((!entity.Swimming && !feetInLiquidBefore && entity.FeetInLiquid) || (!entity.FeetInLiquid && !swimmingBefore && entity.Swimming))
            {
                entity.OnCollideWithLiquid();
            }

            if ((swimmingBefore && !entity.Swimming && !entity.FeetInLiquid) || (feetInLiquidBefore && !entity.FeetInLiquid && !entity.Swimming))
            {
                entity.OnExitedLiquid();
            }

            if (!falling || entity.OnGround || controls.IsClimbing)
            {
                entity.PositionBeforeFalling.Set(outposition);
            }

            Cuboidd testedEntityBox = collisionTester.entityBox;

            for (int y = (int)testedEntityBox.Y1; y <= (int)testedEntityBox.Y2; y++)
            {
                for (int x = (int)testedEntityBox.X1; x <= (int)testedEntityBox.X2; x++)
                {
                    for (int z = (int)testedEntityBox.Z1; z <= (int)testedEntityBox.Z2; z++)
                    {
                        collisionTester.tmpPos.Set(x, y, z);
                        collisionTester.tempCuboid.Set(x, y, z, x + 1, y + 1, z + 1);

                        if (collisionTester.tempCuboid.IntersectsOrTouches(testedEntityBox))
                        {
                            // Saves us a few cpu cycles
                            if (x == (int)pos.X && y == (int)pos.Y && z == (int)pos.Z)
                            {
                                block.OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                                continue;
                            }

                            blockAccess.GetBlock(x, y, z).OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                        }
                    }
                }
            }
        }
Example #29
0
        public void DisplaceWithBlockCollision(EntityPos pos, EntityControls controls, float dt)
        {
            IBlockAccessor blockAccess = entity.World.BlockAccessor;
            float          dtFac       = 60 * dt;

            moveDelta.Set(pos.Motion.X * dtFac, pos.Motion.Y * dtFac, pos.Motion.Z * dtFac);

            nextPosition.Set(pos.X + moveDelta.X, pos.Y + moveDelta.Y, pos.Z + moveDelta.Z);
            bool falling            = pos.Motion.Y < 0;
            bool feetInLiquidBefore = entity.FeetInLiquid;
            bool onGroundBefore     = entity.OnGround;
            bool swimmingBefore     = entity.Swimming;

            double prevYMotion = pos.Motion.Y;

            controls.IsClimbing = false;

            if (!onGroundBefore && entity.Properties.CanClimb == true)
            {
                int height = (int)Math.Ceiling(entity.CollisionBox.Y2);

                entityBox.Set(entity.CollisionBox).Translate(pos.X, pos.Y, pos.Z);

                for (int dy = 0; dy < height; dy++)
                {
                    tmpPos.Set((int)pos.X, (int)pos.Y + dy, (int)pos.Z);
                    Block nblock = blockAccess.GetBlock(tmpPos);
                    if (!nblock.Climbable && !entity.Properties.CanClimbAnywhere)
                    {
                        continue;
                    }

                    Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                    if (collBoxes == null)
                    {
                        continue;
                    }

                    for (int i = 0; i < collBoxes.Length; i++)
                    {
                        double dist = entityBox.ShortestDistanceFrom(collBoxes[i], tmpPos);
                        controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                        if (controls.IsClimbing)
                        {
                            entity.ClimbingOnFace = null;
                            break;
                        }
                    }
                }

                for (int i = 0; !controls.IsClimbing && i < BlockFacing.HORIZONTALS.Length; i++)
                {
                    BlockFacing facing = BlockFacing.HORIZONTALS[i];
                    for (int dy = 0; dy < height; dy++)
                    {
                        tmpPos.Set((int)pos.X + facing.Normali.X, (int)pos.Y + dy, (int)pos.Z + facing.Normali.Z);
                        Block nblock = blockAccess.GetBlock(tmpPos);
                        if (!nblock.Climbable && !(entity.Properties.CanClimbAnywhere && entity.Alive))
                        {
                            continue;
                        }

                        Cuboidf[] collBoxes = nblock.GetCollisionBoxes(blockAccess, tmpPos);
                        if (collBoxes == null)
                        {
                            continue;
                        }

                        for (int j = 0; j < collBoxes.Length; j++)
                        {
                            double dist = entityBox.ShortestDistanceFrom(collBoxes[j], tmpPos);
                            controls.IsClimbing |= dist < entity.Properties.ClimbTouchDistance;

                            if (controls.IsClimbing)
                            {
                                entity.ClimbingOnFace    = facing;
                                entity.ClimbingOnCollBox = collBoxes[j];
                                break;
                            }
                        }
                    }
                }
            }


            if (controls.IsClimbing)
            {
                if (controls.WalkVector.Y == 0)
                {
                    pos.Motion.Y = controls.Sneak ? Math.Max(-0.07, pos.Motion.Y - 0.07) : pos.Motion.Y;
                    if (controls.Jump)
                    {
                        pos.Motion.Y = 0.035 * dt * 60f;
                    }
                }

                // what was this for? it causes jitter
                //moveDelta.Y = pos.Motion.Y * dt * 60f;
                //nextPosition.Set(pos.X + moveDelta.X, pos.Y + moveDelta.Y, pos.Z + moveDelta.Z);
            }

            collisionTester.ApplyTerrainCollision(entity, pos, dtFac, ref outposition, stepHeight);

            if (!entity.Properties.CanClimbAnywhere)
            {
                controls.IsStepping = HandleSteppingOnBlocks(pos, moveDelta, dtFac, controls);
            }

            HandleSneaking(pos, controls, dt);

            if (entity.CollidedHorizontally && !controls.IsClimbing && !controls.IsStepping)
            {
                if (blockAccess.GetBlock((int)pos.X, (int)(pos.Y), (int)pos.Z).LiquidLevel >= 7 || (blockAccess.GetBlock((int)pos.X, (int)(pos.Y - 0.05), (int)pos.Z).LiquidLevel >= 7))
                {
                    pos.Motion.Y       += 0.2 * dt;
                    controls.IsStepping = true;
                }
            }


            if (blockAccess.IsNotTraversable((pos.X + pos.Motion.X * dt * 60f), pos.Y, pos.Z))
            {
                outposition.X = pos.X;
            }
            if (blockAccess.IsNotTraversable(pos.X, (pos.Y + pos.Motion.Y * dt * 60f), pos.Z))
            {
                outposition.Y = pos.Y;
            }
            if (blockAccess.IsNotTraversable(pos.X, pos.Y, (pos.Z + pos.Motion.Z * dt * 60f)))
            {
                outposition.Z = pos.Z;
            }

            pos.SetPos(outposition);


            // Set the motion to zero if he collided.

            if ((nextPosition.X < outposition.X && pos.Motion.X < 0) || (nextPosition.X > outposition.X && pos.Motion.X > 0))
            {
                pos.Motion.X = 0;
            }

            if ((nextPosition.Y < outposition.Y && pos.Motion.Y < 0) || (nextPosition.Y > outposition.Y && pos.Motion.Y > 0))
            {
                pos.Motion.Y = 0;
            }

            if ((nextPosition.Z < outposition.Z && pos.Motion.Z < 0) || (nextPosition.Z > outposition.Z && pos.Motion.Z > 0))
            {
                pos.Motion.Z = 0;
            }

            float offX = entity.CollisionBox.X2 - entity.OriginCollisionBox.X2;
            float offZ = entity.CollisionBox.Z2 - entity.OriginCollisionBox.Z2;

            int posX = (int)(pos.X + offX);
            int posZ = (int)(pos.Z + offZ);

            Block block       = blockAccess.GetBlock(posX, (int)(pos.Y), posZ);
            Block aboveblock  = blockAccess.GetBlock(posX, (int)(pos.Y + 1), posZ);
            Block middleBlock = blockAccess.GetBlock(posX, (int)(pos.Y + entity.SwimmingOffsetY), posZ);


            entity.OnGround     = (entity.CollidedVertically && falling && !controls.IsClimbing) || controls.IsStepping;
            entity.FeetInLiquid = block.IsLiquid() && ((block.LiquidLevel + (aboveblock.LiquidLevel > 0 ? 1 : 0)) / 8f >= pos.Y - (int)pos.Y);
            entity.InLava       = block.LiquidCode == "lava";
            entity.Swimming     = middleBlock.IsLiquid();

            if (!onGroundBefore && entity.OnGround)
            {
                entity.OnFallToGround(prevYMotion);
            }

            if ((!entity.Swimming && !feetInLiquidBefore && entity.FeetInLiquid) || (!entity.FeetInLiquid && !swimmingBefore && entity.Swimming))
            {
                entity.OnCollideWithLiquid();
            }

            if ((swimmingBefore && !entity.Swimming && !entity.FeetInLiquid) || (feetInLiquidBefore && !entity.FeetInLiquid && !entity.Swimming))
            {
                entity.OnExitedLiquid();
            }

            if (!falling || entity.OnGround || controls.IsClimbing)
            {
                entity.PositionBeforeFalling.Set(outposition);
            }

            Cuboidd testedEntityBox = collisionTester.entityBox;

            for (int y = (int)testedEntityBox.Y1; y <= (int)testedEntityBox.Y2; y++)
            {
                for (int x = (int)testedEntityBox.X1; x <= (int)testedEntityBox.X2; x++)
                {
                    for (int z = (int)testedEntityBox.Z1; z <= (int)testedEntityBox.Z2; z++)
                    {
                        collisionTester.tmpPos.Set(x, y, z);
                        collisionTester.tempCuboid.Set(x, y, z, x + 1, y + 1, z + 1);

                        if (collisionTester.tempCuboid.IntersectsOrTouches(testedEntityBox))
                        {
                            // Saves us a few cpu cycles
                            if (x == (int)pos.X && y == (int)pos.Y && z == (int)pos.Z)
                            {
                                block.OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                                continue;
                            }

                            blockAccess.GetBlock(x, y, z).OnEntityInside(entity.World, entity, collisionTester.tmpPos);
                        }
                    }
                }
            }
        }
Example #30
0
        public override void OnGameTick(float dt)
        {
            if (!Active)
            {
                return;
            }


            // For land dwellers only check horizontal distance
            double sqDistToTarget =
                entity.Properties.Habitat == API.Common.EnumHabitat.Land ?
                target.SquareDistanceTo(entity.ServerPos.X, target.Y, entity.ServerPos.Z) :
                target.SquareDistanceTo(entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z)
            ;


            if (sqDistToTarget < targetDistance * targetDistance)
            {
                Stop();
                OnGoalReached?.Invoke();
                return;
            }

            bool stuck =
                (entity.CollidedVertically && entity.Controls.IsClimbing) ||
                (entity.ServerPos.SquareDistanceTo(prevPos) < 0.005 * 0.005) ||  // This used to test motion, but that makes no sense, we want to test if the entity moved, not if it had motion
                (entity.CollidedHorizontally && entity.ServerPos.Motion.Y <= 0)
            ;

            prevPos.Set(entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z);

            stuckCounter = stuck ? (stuckCounter + 1) : 0;

            if (GlobalConstants.OverallSpeedMultiplier > 0 && stuckCounter > 20 / GlobalConstants.OverallSpeedMultiplier)
            {
                //entity.World.SpawnParticles(10, ColorUtil.WhiteArgb, prevPos, prevPos, new Vec3f(0, 0, 0), new Vec3f(0, -1, 0), 1, 1);
                Stop();
                OnStuck?.Invoke();
                return;
            }


            EntityControls controls = entity.MountedOn == null ? entity.Controls : entity.MountedOn.Controls;

            if (controls == null)
            {
                return;
            }

            targetVec.Set(
                (float)(target.X - entity.ServerPos.X),
                (float)(target.Y - entity.ServerPos.Y),
                (float)(target.Z - entity.ServerPos.Z)
                );

            float desiredYaw = 0;

            if (sqDistToTarget >= 0.01)
            {
                desiredYaw = (float)Math.Atan2(targetVec.X, targetVec.Z);
            }



            float yawDist = GameMath.AngleRadDistance(entity.ServerPos.Yaw, desiredYaw);

            entity.ServerPos.Yaw += GameMath.Clamp(yawDist, -curTurnRadPerSec * dt * GlobalConstants.OverallSpeedMultiplier, curTurnRadPerSec * dt * GlobalConstants.OverallSpeedMultiplier);
            entity.ServerPos.Yaw  = entity.ServerPos.Yaw % GameMath.TWOPI;



            double cosYaw = Math.Cos(entity.ServerPos.Yaw);
            double sinYaw = Math.Sin(entity.ServerPos.Yaw);

            controls.WalkVector.Set(sinYaw, GameMath.Clamp(targetVec.Y, -1, 1), cosYaw);
            controls.WalkVector.Mul(movingSpeed * GlobalConstants.OverallSpeedMultiplier);

            // Make it walk along the wall, but not walk into the wall, which causes it to climb
            if (entity.Properties.RotateModelOnClimb && entity.Controls.IsClimbing && entity.ClimbingOnFace != null && entity.Alive)
            {
                BlockFacing facing = entity.ClimbingOnFace;
                if (Math.Sign(facing.Normali.X) == Math.Sign(controls.WalkVector.X))
                {
                    controls.WalkVector.X = 0;
                }

                if (Math.Sign(facing.Normali.Z) == Math.Sign(controls.WalkVector.Z))
                {
                    controls.WalkVector.Z = 0;
                }
            }

            //   entity.World.SpawnParticles(0.3f, ColorUtil.WhiteAhsl, target, target, new Vec3f(), new Vec3f(), 0.1f, 0.1f, 3f, EnumParticleModel.Cube);


            if (entity.Swimming)
            {
                controls.FlyVector.Set(controls.WalkVector);
                controls.FlyVector.X *= 0.85f;
                controls.FlyVector.Z *= 0.85f;

                Vec3d pos                 = entity.Pos.XYZ;
                Block inblock             = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y), (int)pos.Z);
                Block aboveblock          = entity.World.BlockAccessor.GetBlock((int)pos.X, (int)(pos.Y + 1), (int)pos.Z);
                float waterY              = (int)pos.Y + inblock.LiquidLevel / 8f + (aboveblock.IsLiquid() ? 9 / 8f : 0);
                float bottomSubmergedness = waterY - (float)pos.Y;

                // 0 = at swim line
                // 1 = completely submerged
                float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness - ((float)entity.SwimmingOffsetY), 0, 1);
                swimlineSubmergedness = Math.Min(1, swimlineSubmergedness + 0.075f);
                controls.FlyVector.Y  = GameMath.Clamp(controls.FlyVector.Y, 0.002f, 0.004f) * swimlineSubmergedness;


                if (entity.CollidedHorizontally)
                {
                    controls.FlyVector.Y = 0.05f;
                }
            }
        }