github.com/df-mc/dragonfly@v0.9.13/server/block/model/stair.go (about) 1 package model 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 ) 8 9 // Stair is a model for stair-like blocks. These have different solid sides depending on the direction the 10 // stairs are facing, the surrounding blocks and whether it is upside down or not. 11 type Stair struct { 12 // Facing specifies the direction that the full side of the Stair faces. 13 Facing cube.Direction 14 // UpsideDown turns the Stair upside-down, meaning the full side of the Stair is turned to the top side of the 15 // block. 16 UpsideDown bool 17 } 18 19 // BBox returns a slice of physics.BBox depending on if the Stair is upside down and which direction it is facing. 20 // Additionally, these BBoxs depend on the Stair blocks surrounding this one, which can influence the model. 21 func (s Stair) BBox(pos cube.Pos, w *world.World) []cube.BBox { 22 b := []cube.BBox{cube.Box(0, 0, 0, 1, 0.5, 1)} 23 if s.UpsideDown { 24 b[0] = cube.Box(0, 0.5, 0, 1, 1, 1) 25 } 26 t := s.cornerType(pos, w) 27 28 face, oppositeFace := s.Facing.Face(), s.Facing.Opposite().Face() 29 if t == noCorner || t == cornerRightInner || t == cornerLeftInner { 30 b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5). 31 ExtendTowards(face, 0.5). 32 Stretch(s.Facing.RotateRight().Face().Axis(), 0.5)) 33 } 34 if t == cornerRightOuter { 35 b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5). 36 ExtendTowards(face, 0.5). 37 ExtendTowards(s.Facing.RotateLeft().Face(), 0.5)) 38 } else if t == cornerLeftOuter { 39 b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5). 40 ExtendTowards(face, 0.5). 41 ExtendTowards(s.Facing.RotateRight().Face(), 0.5)) 42 } else if t == cornerRightInner { 43 b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5). 44 ExtendTowards(oppositeFace, 0.5). 45 ExtendTowards(s.Facing.RotateRight().Face(), 0.5)) 46 } else if t == cornerLeftInner { 47 b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5). 48 ExtendTowards(oppositeFace, 0.5). 49 ExtendTowards(s.Facing.RotateLeft().Face(), 0.5)) 50 } 51 if s.UpsideDown { 52 for i := range b[1:] { 53 b[i+1] = b[i+1].Translate(mgl64.Vec3{0, -0.5}) 54 } 55 } 56 return b 57 } 58 59 // FaceSolid returns true for all faces of the Stair that are completely filled. 60 func (s Stair) FaceSolid(pos cube.Pos, face cube.Face, w *world.World) bool { 61 if !s.UpsideDown && face == cube.FaceDown { 62 // Non-upside-down stairs have a closed side at the bottom. 63 return true 64 } else if s.UpsideDown && face == cube.FaceUp { 65 // Upside-down stairs always have a closed side at the top. 66 return true 67 } 68 t := s.cornerType(pos, w) 69 if t == cornerRightOuter || t == cornerLeftOuter { 70 // Small corner blocks, they do not block water flowing out horizontally. 71 return false 72 } else if t == noCorner { 73 // Not a corner, so only block directly behind the stairs. 74 return s.Facing.Face() == face 75 } 76 if t == cornerRightInner { 77 return face == s.Facing.RotateRight().Face() || face == s.Facing.Face() 78 } 79 return face == s.Facing.RotateLeft().Face() || face == s.Facing.Face() 80 } 81 82 const ( 83 noCorner = iota 84 cornerRightInner 85 cornerLeftInner 86 cornerRightOuter 87 cornerLeftOuter 88 ) 89 90 // cornerType returns the type of the corner that the stairs form, or 0 if it does not form a corner with any 91 // other stairs. 92 func (s Stair) cornerType(pos cube.Pos, w *world.World) uint8 { 93 rotatedFacing := s.Facing.RotateRight() 94 if closedSide, ok := w.Block(pos.Side(s.Facing.Face())).Model().(Stair); ok && closedSide.UpsideDown == s.UpsideDown { 95 if closedSide.Facing == rotatedFacing { 96 return cornerLeftOuter 97 } else if closedSide.Facing == rotatedFacing.Opposite() { 98 // This will only form a corner if there is not a stair on the right of this one with the same 99 // direction. 100 if side, ok := w.Block(pos.Side(s.Facing.RotateRight().Face())).Model().(Stair); !ok || side.Facing != s.Facing || side.UpsideDown != s.UpsideDown { 101 return cornerRightOuter 102 } 103 return noCorner 104 } 105 } 106 if openSide, ok := w.Block(pos.Side(s.Facing.Opposite().Face())).Model().(Stair); ok && openSide.UpsideDown == s.UpsideDown { 107 if openSide.Facing == rotatedFacing { 108 // This will only form a corner if there is not a stair on the right of this one with the same 109 // direction. 110 if side, ok := w.Block(pos.Side(s.Facing.RotateRight().Face())).Model().(Stair); !ok || side.Facing != s.Facing || side.UpsideDown != s.UpsideDown { 111 return cornerRightInner 112 } 113 } else if openSide.Facing == rotatedFacing.Opposite() { 114 return cornerLeftInner 115 } 116 } 117 return noCorner 118 }