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  }