github.com/df-mc/dragonfly@v0.9.13/server/block/cube/trace/result.go (about)

     1  package trace
     2  
     3  import (
     4  	"github.com/df-mc/dragonfly/server/block/cube"
     5  	"github.com/df-mc/dragonfly/server/world"
     6  	"github.com/go-gl/mathgl/mgl64"
     7  	"math"
     8  )
     9  
    10  // Result represents the result of a ray trace collision with a bounding box.
    11  type Result interface {
    12  	// BBox returns the bounding box collided with.
    13  	BBox() cube.BBox
    14  	// Position returns where the ray first collided with the bounding box.
    15  	Position() mgl64.Vec3
    16  	// Face returns the face of the bounding box that was collided on.
    17  	Face() cube.Face
    18  }
    19  
    20  // Perform performs a ray trace between start and end, checking if any blocks or entities collided with the
    21  // ray. The physics.BBox that's passed is used for checking if any entity within the bounding box collided
    22  // with the ray.
    23  func Perform(start, end mgl64.Vec3, w *world.World, box cube.BBox, ignored func(world.Entity) bool) (hit Result, ok bool) {
    24  	// Check if there's any blocks that we may collide with.
    25  	TraverseBlocks(start, end, func(pos cube.Pos) (cont bool) {
    26  		b := w.Block(pos)
    27  
    28  		// Check if we collide with the block's model.
    29  		if result, ok := BlockIntercept(pos, w, b, start, end); ok {
    30  			hit = result
    31  			end = hit.Position()
    32  			return false
    33  		}
    34  		return true
    35  	})
    36  
    37  	// Now check for any entities that we may collide with.
    38  	dist := math.MaxFloat64
    39  	bb := box.Translate(start).Extend(end.Sub(start))
    40  	for _, entity := range w.EntitiesWithin(bb.Grow(8.0), ignored) {
    41  		if ignored != nil && ignored(entity) || !entity.Type().BBox(entity).Translate(entity.Position()).IntersectsWith(bb) {
    42  			continue
    43  		}
    44  		// Check if we collide with the entities bounding box.
    45  		result, ok := EntityIntercept(entity, start, end)
    46  		if !ok {
    47  			continue
    48  		}
    49  
    50  		if distance := start.Sub(result.Position()).LenSqr(); distance < dist {
    51  			dist = distance
    52  			hit = result
    53  		}
    54  	}
    55  
    56  	return hit, hit != nil
    57  }