github.com/df-mc/dragonfly@v0.9.13/server/block/coral.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 "time" 11 ) 12 13 // Coral is a non-solid block that comes in 5 variants. 14 type Coral struct { 15 empty 16 transparent 17 bassDrum 18 sourceWaterDisplacer 19 20 // Type is the type of coral of the block. 21 Type CoralType 22 // Dead is whether the coral is dead. 23 Dead bool 24 } 25 26 // UseOnBlock ... 27 func (c Coral) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool { 28 pos, _, used := firstReplaceable(w, pos, face, c) 29 if !used { 30 return false 31 } 32 if !w.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, w) { 33 return false 34 } 35 if liquid, ok := w.Liquid(pos); ok { 36 if water, ok := liquid.(Water); ok { 37 if water.Depth != 8 { 38 return false 39 } 40 } 41 } 42 43 place(w, pos, c, user, ctx) 44 return placed(ctx) 45 } 46 47 // HasLiquidDrops ... 48 func (c Coral) HasLiquidDrops() bool { 49 return false 50 } 51 52 // SideClosed ... 53 func (c Coral) SideClosed(cube.Pos, cube.Pos, *world.World) bool { 54 return false 55 } 56 57 // NeighbourUpdateTick ... 58 func (c Coral) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) { 59 if !w.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, w) { 60 w.SetBlock(pos, nil, nil) 61 w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: c}) 62 return 63 } 64 if c.Dead { 65 return 66 } 67 w.ScheduleBlockUpdate(pos, time.Second*5/2) 68 } 69 70 // ScheduledTick ... 71 func (c Coral) ScheduledTick(pos cube.Pos, w *world.World, _ *rand.Rand) { 72 if c.Dead { 73 return 74 } 75 76 adjacentWater := false 77 pos.Neighbours(func(neighbour cube.Pos) { 78 if liquid, ok := w.Liquid(neighbour); ok { 79 if _, ok := liquid.(Water); ok { 80 adjacentWater = true 81 } 82 } 83 }, w.Range()) 84 if !adjacentWater { 85 c.Dead = true 86 w.SetBlock(pos, c, nil) 87 } 88 } 89 90 // BreakInfo ... 91 func (c Coral) BreakInfo() BreakInfo { 92 return newBreakInfo(0, alwaysHarvestable, nothingEffective, silkTouchOnlyDrop(c)) 93 } 94 95 // EncodeBlock ... 96 func (c Coral) EncodeBlock() (name string, properties map[string]any) { 97 if c.Dead { 98 return "minecraft:dead_" + c.Type.String() + "_coral", nil 99 } 100 return "minecraft:" + c.Type.String() + "_coral", nil 101 } 102 103 // EncodeItem ... 104 func (c Coral) EncodeItem() (name string, meta int16) { 105 if c.Dead { 106 return "minecraft:dead_" + c.Type.String() + "_coral", 0 107 } 108 return "minecraft:" + c.Type.String() + "_coral", 0 109 } 110 111 // allCoral returns a list of all coral block variants 112 func allCoral() (c []world.Block) { 113 f := func(dead bool) { 114 for _, t := range CoralTypes() { 115 c = append(c, Coral{Type: t, Dead: dead}) 116 } 117 } 118 f(true) 119 f(false) 120 return 121 }