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

     1  package block
     2  
     3  import (
     4  	"github.com/df-mc/dragonfly/server/block/cube"
     5  	"github.com/df-mc/dragonfly/server/world"
     6  	"math/rand"
     7  )
     8  
     9  // Farmland is a block that crops are grown on. Farmland is created by interacting with a grass or dirt block using a
    10  // hoe. Farmland can be hydrated by nearby water, with no hydration resulting in it turning into a dirt block.
    11  type Farmland struct {
    12  	tilledGrass
    13  
    14  	// Hydration is how much moisture the farmland block has. Hydration starts at 0 & caps at 7. During a random tick
    15  	// update, if there is water within 4 blocks from the farmland block, hydration is set to 7. Otherwise, it
    16  	// decrements until it turns into dirt.
    17  	Hydration int
    18  }
    19  
    20  // SoilFor ...
    21  func (f Farmland) SoilFor(block world.Block) bool {
    22  	switch block.(type) {
    23  	case TallGrass, DoubleTallGrass, Flower, DoubleFlower, NetherSprouts:
    24  		return true
    25  	}
    26  	return false
    27  }
    28  
    29  // NeighbourUpdateTick ...
    30  func (f Farmland) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) {
    31  	if solid := w.Block(pos.Side(cube.FaceUp)).Model().FaceSolid(pos.Side(cube.FaceUp), cube.FaceDown, w); solid {
    32  		w.SetBlock(pos, Dirt{}, nil)
    33  	}
    34  }
    35  
    36  // RandomTick ...
    37  func (f Farmland) RandomTick(pos cube.Pos, w *world.World, _ *rand.Rand) {
    38  	if !f.hydrated(pos, w) {
    39  		if f.Hydration > 0 {
    40  			f.Hydration--
    41  			w.SetBlock(pos, f, nil)
    42  		} else {
    43  			blockAbove := w.Block(pos.Side(cube.FaceUp))
    44  			if _, cropAbove := blockAbove.(Crop); !cropAbove {
    45  				w.SetBlock(pos, Dirt{}, nil)
    46  			}
    47  		}
    48  	} else {
    49  		f.Hydration = 7
    50  		w.SetBlock(pos, f, nil)
    51  	}
    52  }
    53  
    54  // hydrated checks for water within 4 blocks in each direction from the farmland.
    55  func (f Farmland) hydrated(pos cube.Pos, w *world.World) bool {
    56  	posX, posY, posZ := pos.X(), pos.Y(), pos.Z()
    57  	for y := 0; y <= 1; y++ {
    58  		for x := -4; x <= 4; x++ {
    59  			for z := -4; z <= 4; z++ {
    60  				if liquid, ok := w.Liquid(cube.Pos{posX + x, posY + y, posZ + z}); ok {
    61  					if _, ok := liquid.(Water); ok {
    62  						return true
    63  					}
    64  				}
    65  			}
    66  		}
    67  	}
    68  	return false
    69  }
    70  
    71  // EntityLand ...
    72  func (f Farmland) EntityLand(pos cube.Pos, w *world.World, e world.Entity, distance *float64) {
    73  	if living, ok := e.(livingEntity); ok {
    74  		if fall, ok := living.(fallDistanceEntity); ok && rand.Float64() < fall.FallDistance()-0.5 {
    75  			w.SetBlock(pos, Dirt{}, nil)
    76  		}
    77  	}
    78  }
    79  
    80  // fallDistanceEntity is an entity that has a fall distance.
    81  type fallDistanceEntity interface {
    82  	// ResetFallDistance resets the entities fall distance.
    83  	ResetFallDistance()
    84  	// FallDistance returns the entities fall distance.
    85  	FallDistance() float64
    86  }
    87  
    88  // BreakInfo ...
    89  func (f Farmland) BreakInfo() BreakInfo {
    90  	return newBreakInfo(0.6, alwaysHarvestable, shovelEffective, oneOf(Dirt{}))
    91  }
    92  
    93  // EncodeBlock ...
    94  func (f Farmland) EncodeBlock() (name string, properties map[string]any) {
    95  	return "minecraft:farmland", map[string]any{"moisturized_amount": int32(f.Hydration)}
    96  }
    97  
    98  // EncodeItem ...
    99  func (f Farmland) EncodeItem() (name string, meta int16) {
   100  	return "minecraft:farmland", 0
   101  }
   102  
   103  // allFarmland returns all possible states that a block of farmland can be in.
   104  func allFarmland() (b []world.Block) {
   105  	for i := 0; i <= 7; i++ {
   106  		b = append(b, Farmland{Hydration: i})
   107  	}
   108  	return
   109  }