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 }