void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
    if (m_IsInGround)
    {
        // Already-grounded projectiles don't move at all
        return;
    }

    auto DtSec = std::chrono::duration_cast<std::chrono::duration<double>>(a_Dt);

    const Vector3d DeltaSpeed = GetSpeed() * DtSec.count();
    const Vector3d Pos = GetPosition();
    const Vector3d NextPos = Pos + DeltaSpeed;

    // Test for entity collisions:
    cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
    a_Chunk.ForEachEntity(EntityCollisionCallback);
    if (EntityCollisionCallback.HasHit())
    {
        // An entity was hit:
        Vector3d HitPos = Pos + (NextPos - Pos) * EntityCollisionCallback.GetMinCoeff();

        // DEBUG:
        LOGD("Projectile %d has hit an entity %d (%s) at {%.02f, %.02f, %.02f} (coeff %.03f)",
             m_UniqueID,
             EntityCollisionCallback.GetHitEntity()->GetUniqueID(),
             EntityCollisionCallback.GetHitEntity()->GetClass(),
             HitPos.x, HitPos.y, HitPos.z,
             EntityCollisionCallback.GetMinCoeff()
            );

        OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
        if (!IsTicking())
        {
            return;  // We were destroyed by an override of OnHitEntity
        }
    }
    // TODO: Test the entities in the neighboring chunks, too

    // Trace the tick's worth of movement as a line:
    cProjectileTracerCallback TracerCallback(this);
    if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
    {
        // Something has been hit, abort all other processing
        return;
    }
    // The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff

    // Update the position:
    SetPosition(NextPos);

    // Add slowdown and gravity effect to the speed:
    Vector3d NewSpeed(GetSpeed());
    NewSpeed.y += m_Gravity * DtSec.count();
    NewSpeed -= NewSpeed * (m_AirDrag * 20.0f) * DtSec.count();
    SetSpeed(NewSpeed);
    SetYawFromSpeed();
    SetPitchFromSpeed();

    /*
    LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}, rot {%.02f, %.02f}",
    	m_UniqueID,
    	GetPosX(), GetPosY(), GetPosZ(),
    	GetSpeedX(), GetSpeedY(), GetSpeedZ(),
    	GetYaw(), GetPitch()
    );
    */
}
void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
	if (m_IsInGround)
	{
		// Already-grounded projectiles don't move at all
		return;
	}
	
	Vector3d PerTickSpeed = GetSpeed() / 20;
	Vector3d Pos = GetPosition();
	
	// Trace the tick's worth of movement as a line:
	Vector3d NextPos = Pos + PerTickSpeed;
	cProjectileTracerCallback TracerCallback(this);
	if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
	{
		// Something has been hit, abort all other processing
		return;
	}
	// The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
	
	// Test for entity collisions:
	cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
	a_Chunk.ForEachEntity(EntityCollisionCallback);
	if (EntityCollisionCallback.HasHit())
	{
		// An entity was hit:
		Vector3d HitPos = Pos + (NextPos - Pos) * EntityCollisionCallback.GetMinCoeff();

		// DEBUG:
		LOGD("Projectile %d has hit an entity %d (%s) at {%.02f, %.02f, %.02f} (coeff %.03f)",
			m_UniqueID,
			EntityCollisionCallback.GetHitEntity()->GetUniqueID(),
			EntityCollisionCallback.GetHitEntity()->GetClass(),
			HitPos.x, HitPos.y, HitPos.z,
			EntityCollisionCallback.GetMinCoeff()
		);
		
		OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
	}
	// TODO: Test the entities in the neighboring chunks, too

	// Update the position:
	SetPosition(NextPos);
	
	// Add slowdown and gravity effect to the speed:
	Vector3d NewSpeed(GetSpeed());
	NewSpeed.y += m_Gravity / 20;
	NewSpeed *= TracerCallback.GetSlowdownCoeff();
	SetSpeed(NewSpeed);
	SetRotationFromSpeed();
	SetPitchFromSpeed();

	// DEBUG:
	LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}, rot {%.02f, %.02f}",
		m_UniqueID,
		GetPosX(), GetPosY(), GetPosZ(),
		GetSpeedX(), GetSpeedY(), GetSpeedZ(),
		GetRotation(), GetPitch()
	);
}