github.com/df-mc/dragonfly@v0.9.13/server/block/crop.go (about) 1 package block 2 3 import ( 4 "github.com/df-mc/dragonfly/server/block/cube" 5 "github.com/df-mc/dragonfly/server/item" 6 "github.com/df-mc/dragonfly/server/world" 7 ) 8 9 // Crop is an interface for all crops that are grown on farmland. A crop has a random chance to grow during random ticks. 10 type Crop interface { 11 // GrowthStage returns the crop's current stage of growth. The max value is 7. 12 GrowthStage() int 13 // SameCrop checks if two crops are of the same type. 14 SameCrop(c Crop) bool 15 } 16 17 // crop is a base for crop plants. 18 type crop struct { 19 transparent 20 empty 21 22 // Growth is the current stage of growth. The max value is 7. 23 Growth int 24 } 25 26 // NeighbourUpdateTick ... 27 func (c crop) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) { 28 if _, ok := w.Block(pos.Side(cube.FaceDown)).(Farmland); !ok { 29 b := w.Block(pos) 30 w.SetBlock(pos, nil, nil) 31 if breakable, ok := b.(Breakable); ok { 32 for _, drop := range breakable.BreakInfo().Drops(item.ToolNone{}, []item.Enchantment{}) { 33 dropItem(w, drop, pos.Vec3Centre()) 34 } 35 } 36 } 37 } 38 39 // HasLiquidDrops ... 40 func (c crop) HasLiquidDrops() bool { 41 return true 42 } 43 44 // GrowthStage returns the current stage of growth. 45 func (c crop) GrowthStage() int { 46 return c.Growth 47 } 48 49 // CalculateGrowthChance calculates the chance the crop will grow during a random tick. 50 func (c crop) CalculateGrowthChance(pos cube.Pos, w *world.World) float64 { 51 points := 0.0 52 53 block := w.Block(pos) 54 under := pos.Side(cube.FaceDown) 55 56 for x := -1; x <= 1; x++ { 57 for z := -1; z <= 1; z++ { 58 block := w.Block(under.Add(cube.Pos{x, 0, z})) 59 if farmland, ok := block.(Farmland); ok { 60 farmlandPoints := 0.0 61 if farmland.Hydration > 0 { 62 farmlandPoints = 4 63 } else { 64 farmlandPoints = 2 65 } 66 if x != 0 || z != 0 { 67 farmlandPoints = (farmlandPoints - 1) / 4 68 } 69 points += farmlandPoints 70 } 71 } 72 } 73 74 north := pos.Side(cube.FaceNorth) 75 south := pos.Side(cube.FaceSouth) 76 77 northSouth := sameCrop(block, w.Block(north)) || sameCrop(block, w.Block(south)) 78 westEast := sameCrop(block, w.Block(pos.Side(cube.FaceWest))) || sameCrop(block, w.Block(pos.Side(cube.FaceEast))) 79 if northSouth && westEast { 80 points /= 2 81 } else { 82 diagonal := sameCrop(block, w.Block(north.Side(cube.FaceWest))) || 83 sameCrop(block, w.Block(north.Side(cube.FaceEast))) || 84 sameCrop(block, w.Block(south.Side(cube.FaceWest))) || 85 sameCrop(block, w.Block(south.Side(cube.FaceEast))) 86 if diagonal { 87 points /= 2 88 } 89 } 90 91 chance := 1 / (25/points + 1) 92 return chance 93 } 94 95 // sameCrop checks if both blocks are crops and that they are the same type. 96 func sameCrop(blockA, blockB world.Block) bool { 97 if a, ok := blockA.(Crop); ok { 98 if b, ok := blockB.(Crop); ok { 99 return a.SameCrop(b) 100 } 101 } 102 return false 103 } 104 105 // min returns the smaller of the two integers passed. 106 func min(a, b int) int { 107 if a < b { 108 return a 109 } 110 return b 111 }