github.com/df-mc/dragonfly@v0.9.13/server/block/leaves.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/go-gl/mathgl/mgl64" 8 "math/rand" 9 ) 10 11 // Leaves are blocks that grow as part of trees which mainly drop saplings and sticks. 12 type Leaves struct { 13 leaves 14 sourceWaterDisplacer 15 16 // Wood is the type of wood of the leaves. This field must have one of the values found in the material 17 // package. 18 Wood WoodType 19 // Persistent specifies if the leaves are persistent, meaning they will not decay as a result of no wood 20 // being nearby. 21 Persistent bool 22 23 ShouldUpdate bool 24 } 25 26 // UseOnBlock makes leaves persistent when they are placed so that they don't decay. 27 func (l Leaves) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) (used bool) { 28 pos, _, used = firstReplaceable(w, pos, face, l) 29 if !used { 30 return 31 } 32 l.Persistent = true 33 34 place(w, pos, l, user, ctx) 35 return placed(ctx) 36 } 37 38 // findLog ... 39 func findLog(pos cube.Pos, w *world.World, visited *[]cube.Pos, distance int) bool { 40 for _, v := range *visited { 41 if v == pos { 42 return false 43 } 44 } 45 *visited = append(*visited, pos) 46 47 if log, ok := w.Block(pos).(Log); ok && !log.Stripped { 48 return true 49 } 50 if _, ok := w.Block(pos).(Leaves); !ok || distance > 6 { 51 return false 52 } 53 logFound := false 54 pos.Neighbours(func(neighbour cube.Pos) { 55 if !logFound && findLog(neighbour, w, visited, distance+1) { 56 logFound = true 57 } 58 }, w.Range()) 59 return logFound 60 } 61 62 // RandomTick ... 63 func (l Leaves) RandomTick(pos cube.Pos, w *world.World, _ *rand.Rand) { 64 if !l.Persistent && l.ShouldUpdate { 65 if findLog(pos, w, &[]cube.Pos{}, 0) { 66 l.ShouldUpdate = false 67 w.SetBlock(pos, l, nil) 68 } else { 69 w.SetBlock(pos, nil, nil) 70 } 71 } 72 } 73 74 // NeighbourUpdateTick ... 75 func (l Leaves) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) { 76 if !l.Persistent && !l.ShouldUpdate { 77 l.ShouldUpdate = true 78 w.SetBlock(pos, l, nil) 79 } 80 } 81 82 // FlammabilityInfo ... 83 func (l Leaves) FlammabilityInfo() FlammabilityInfo { 84 return newFlammabilityInfo(30, 60, true) 85 } 86 87 // BreakInfo ... 88 func (l Leaves) BreakInfo() BreakInfo { 89 return newBreakInfo(0.2, alwaysHarvestable, func(t item.Tool) bool { 90 return t.ToolType() == item.TypeShears || t.ToolType() == item.TypeHoe 91 }, func(t item.Tool, enchantments []item.Enchantment) []item.Stack { 92 if t.ToolType() == item.TypeShears || hasSilkTouch(enchantments) { 93 return []item.Stack{item.NewStack(l, 1)} 94 } 95 var drops []item.Stack 96 if (l.Wood == OakWood() || l.Wood == DarkOakWood()) && rand.Float64() < 0.005 { 97 drops = append(drops, item.NewStack(item.Apple{}, 1)) 98 } 99 // TODO: Saplings and sticks can drop along with apples 100 return drops 101 }) 102 } 103 104 // CompostChance ... 105 func (Leaves) CompostChance() float64 { 106 return 0.3 107 } 108 109 // EncodeItem ... 110 func (l Leaves) EncodeItem() (name string, meta int16) { 111 switch l.Wood { 112 case OakWood(), SpruceWood(), BirchWood(), JungleWood(): 113 return "minecraft:leaves", int16(l.Wood.Uint8()) 114 case AcaciaWood(), DarkOakWood(): 115 return "minecraft:leaves2", int16(l.Wood.Uint8() - 4) 116 default: 117 return "minecraft:" + l.Wood.String() + "_leaves", 0 118 } 119 } 120 121 // LightDiffusionLevel ... 122 func (Leaves) LightDiffusionLevel() uint8 { 123 return 1 124 } 125 126 // SideClosed ... 127 func (Leaves) SideClosed(cube.Pos, cube.Pos, *world.World) bool { 128 return false 129 } 130 131 // EncodeBlock ... 132 func (l Leaves) EncodeBlock() (name string, properties map[string]any) { 133 switch l.Wood { 134 case OakWood(), SpruceWood(), BirchWood(), JungleWood(): 135 return "minecraft:leaves", map[string]any{"old_leaf_type": l.Wood.String(), "persistent_bit": l.Persistent, "update_bit": l.ShouldUpdate} 136 case AcaciaWood(), DarkOakWood(): 137 return "minecraft:leaves2", map[string]any{"new_leaf_type": l.Wood.String(), "persistent_bit": l.Persistent, "update_bit": l.ShouldUpdate} 138 default: 139 return "minecraft:" + l.Wood.String() + "_leaves", map[string]any{"persistent_bit": l.Persistent, "update_bit": l.ShouldUpdate} 140 } 141 } 142 143 // allLogs returns a list of all possible leaves states. 144 func allLeaves() (leaves []world.Block) { 145 f := func(persistent, update bool) { 146 for _, w := range WoodTypes() { 147 if w != CrimsonWood() && w != WarpedWood() { 148 leaves = append(leaves, Leaves{Wood: w, Persistent: persistent, ShouldUpdate: update}) 149 } 150 } 151 } 152 f(true, true) 153 f(true, false) 154 f(false, true) 155 f(false, false) 156 return 157 }