github.com/df-mc/dragonfly@v0.9.13/server/block/tall_grass.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 "github.com/df-mc/dragonfly/server/world/particle" 8 "github.com/go-gl/mathgl/mgl64" 9 "math/rand" 10 ) 11 12 // TallGrass is a transparent plant block which can be used to obtain seeds and as decoration. 13 type TallGrass struct { 14 replaceable 15 transparent 16 empty 17 18 // Type is the type of tall grass that the plant represents. 19 Type TallGrassType 20 } 21 22 // FlammabilityInfo ... 23 func (g TallGrass) FlammabilityInfo() FlammabilityInfo { 24 return newFlammabilityInfo(60, 100, false) 25 } 26 27 // BreakInfo ... 28 func (g TallGrass) BreakInfo() BreakInfo { 29 return newBreakInfo(0, alwaysHarvestable, nothingEffective, func(t item.Tool, enchantments []item.Enchantment) []item.Stack { 30 if t.ToolType() == item.TypeShears || hasSilkTouch(enchantments) { 31 return []item.Stack{item.NewStack(g, 1)} 32 } 33 if rand.Float32() > 0.57 { 34 return []item.Stack{item.NewStack(WheatSeeds{}, 1)} 35 } 36 return nil 37 }) 38 } 39 40 // BoneMeal attempts to affect the block using a bone meal item. 41 func (g TallGrass) BoneMeal(pos cube.Pos, w *world.World) bool { 42 upper := DoubleTallGrass{Type: g.Type.Double(), UpperPart: true} 43 if replaceableWith(w, pos.Side(cube.FaceUp), upper) { 44 w.SetBlock(pos, DoubleTallGrass{Type: g.Type.Double()}, nil) 45 w.SetBlock(pos.Side(cube.FaceUp), upper, nil) 46 return true 47 } 48 return false 49 } 50 51 // CompostChance ... 52 func (g TallGrass) CompostChance() float64 { 53 if g.Type == FernTallGrass() { 54 return 0.65 55 } 56 return 0.3 57 } 58 59 // NeighbourUpdateTick ... 60 func (g TallGrass) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) { 61 if !supportsVegetation(g, w.Block(pos.Side(cube.FaceDown))) { 62 w.SetBlock(pos, nil, nil) 63 w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: g}) 64 } 65 } 66 67 // HasLiquidDrops ... 68 func (g TallGrass) HasLiquidDrops() bool { 69 return true 70 } 71 72 // UseOnBlock ... 73 func (g TallGrass) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool { 74 pos, _, used := firstReplaceable(w, pos, face, g) 75 if !used { 76 return false 77 } 78 if !supportsVegetation(g, w.Block(pos.Side(cube.FaceDown))) { 79 return false 80 } 81 82 place(w, pos, g, user, ctx) 83 return placed(ctx) 84 } 85 86 // EncodeItem ... 87 func (g TallGrass) EncodeItem() (name string, meta int16) { 88 return "minecraft:tallgrass", int16(g.Type.Uint8()) 89 } 90 91 // EncodeBlock ... 92 func (g TallGrass) EncodeBlock() (name string, properties map[string]any) { 93 return "minecraft:tallgrass", map[string]any{"tall_grass_type": g.Type.String()} 94 } 95 96 // allTallGrass ... 97 func allTallGrass() (grasses []world.Block) { 98 for _, g := range TallGrassTypes() { 99 grasses = append(grasses, TallGrass{Type: g}) 100 } 101 return 102 } 103 104 // supportsVegetation checks if the vegetation can exist on the block. 105 func supportsVegetation(vegetation, block world.Block) bool { 106 soil, ok := block.(Soil) 107 return ok && soil.SoilFor(vegetation) 108 } 109 110 // Soil represents a block that can support vegetation. 111 type Soil interface { 112 // SoilFor returns whether the vegetation can exist on the block. 113 SoilFor(world.Block) bool 114 }