public override void OnTick() { base.OnTick(); if (HealthManager.IsDead) { return; } if (Level.EnableChunkTicking && DespawnIfNotSeenPlayer && DateTime.UtcNow - LastSeenPlayerTimer > TimeSpan.FromSeconds(30)) { if (Level.GetSpawnedPlayers().Count(e => Vector3.Distance(KnownPosition, e.KnownPosition) < 32) == 0) { if (Level.Random.Next(800) == 0) { if (Log.IsDebugEnabled) { Log.Warn($"Despawn because didn't see any players within 32 blocks for 30s or longer. Last seen {LastSeenPlayerTimer}"); } DespawnEntity(); return; } } else { LastSeenPlayerTimer = DateTime.UtcNow; } } _currentBehavior = GetBehavior(); _currentBehavior?.OnTick(); // Execute move bool onGroundBefore = IsMobOnGround(KnownPosition); KnownPosition.X += (float)Velocity.X; KnownPosition.Y += (float)Velocity.Y; KnownPosition.Z += (float)Velocity.Z; // Fix potential fall through ground because of speed bool onGround = IsMobOnGround(KnownPosition); if (!onGroundBefore && onGround) { while (Level.GetBlock(KnownPosition).IsSolid) { KnownPosition.Y = (float)Math.Floor(KnownPosition.Y + 1); } KnownPosition.Y = (float)Math.Floor(KnownPosition.Y); } //if (Math.Abs(_lastSentDir - Direction) < 1.1) Direction = _lastSentDir; //if (Math.Abs(_lastSentHeadYaw - KnownPosition.HeadYaw) < 1.1) KnownPosition.HeadYaw = (float) _lastSentHeadYaw; if ((_lastSentPos - KnownPosition).Length() > 0.01 || Math.Abs(_lastSentHeadYaw - KnownPosition.HeadYaw) > 0.01 || Math.Abs(_lastSentDir - Direction) > 0.01) { _lastSentDir = Direction; _lastSentPos = KnownPosition; _lastSentHeadYaw = KnownPosition.HeadYaw; BroadcastMove(); BroadcastMotion(); } // Calculate velocity for next move _currentBehavior?.CalculateNextMove(); bool inWater = IsMobInFluid(KnownPosition); if (inWater && Level.Random.NextDouble() < 0.8) { Velocity += new Vector3(0, 0.039f, 0); } else if (onGround) { if (Velocity.Y < 0) { Velocity *= new Vector3(1, 0, 1); } } else { Velocity -= new Vector3(0, (float)Gravity, 0); } float drag = (float)(1 - Drag); if (inWater) { drag = 0.8F; } Velocity *= drag; }