forked from df-mc/dragonfly
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kelp.go
154 lines (133 loc) · 3.92 KB
/
kelp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package block
import (
"github.com/Adrian8115/dragonfly-Amethyst-Protocol/server/block/cube"
"github.com/Adrian8115/dragonfly-Amethyst-Protocol/server/item"
"github.com/Adrian8115/dragonfly-Amethyst-Protocol/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand"
)
// Kelp is an underwater block which can grow on top of solids underwater.
type Kelp struct {
empty
transparent
sourceWaterDisplacer
// Age is the age of the kelp block which can be 0-25. If age is 25, kelp won't grow any further.
Age int
}
// SmeltInfo ...
func (k Kelp) SmeltInfo() item.SmeltInfo {
return newFoodSmeltInfo(item.NewStack(item.DriedKelp{}, 1), 0.1)
}
// BoneMeal ...
func (k Kelp) BoneMeal(pos cube.Pos, w *world.World) bool {
for y := pos.Y(); y <= w.Range()[1]; y++ {
currentPos := cube.Pos{pos.X(), y, pos.Z()}
block := w.Block(currentPos)
if kelp, ok := block.(Kelp); ok {
if kelp.Age == 25 {
break
}
continue
}
if water, ok := block.(Water); ok && water.Depth == 8 {
w.SetBlock(currentPos, Kelp{Age: k.Age + 1}, nil)
return true
}
break
}
return false
}
// BreakInfo ...
func (k Kelp) BreakInfo() BreakInfo {
return newBreakInfo(0, alwaysHarvestable, nothingEffective, oneOf(k))
}
// CompostChance ...
func (Kelp) CompostChance() float64 {
return 0.3
}
// EncodeItem ...
func (Kelp) EncodeItem() (name string, meta int16) {
return "minecraft:kelp", 0
}
// EncodeBlock ...
func (k Kelp) EncodeBlock() (name string, properties map[string]any) {
return "minecraft:kelp", map[string]any{"kelp_age": int32(k.Age)}
}
// SideClosed will always return false since kelp doesn't close any side.
func (Kelp) SideClosed(cube.Pos, cube.Pos, *world.World) bool {
return false
}
// withRandomAge returns a new Kelp block with its age value randomized between 0 and 24.
func (k Kelp) withRandomAge() Kelp {
k.Age = rand.Intn(25)
return k
}
// UseOnBlock ...
func (k Kelp) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) (used bool) {
pos, _, used = firstReplaceable(w, pos, face, k)
if !used {
return
}
below := pos.Side(cube.FaceDown)
belowBlock := w.Block(below)
if _, kelp := belowBlock.(Kelp); !kelp {
if !belowBlock.Model().FaceSolid(below, cube.FaceUp, w) {
return false
}
}
liquid, ok := w.Liquid(pos)
if !ok {
return false
} else if _, ok := liquid.(Water); !ok || liquid.LiquidDepth() < 8 {
return false
}
// When first placed, kelp gets a random age between 0 and 24.
place(w, pos, k.withRandomAge(), user, ctx)
return placed(ctx)
}
// NeighbourUpdateTick ...
func (k Kelp) NeighbourUpdateTick(pos, changed cube.Pos, w *world.World) {
if _, ok := w.Liquid(pos); !ok {
w.SetBlock(pos, nil, nil)
return
}
if changed.Y()-1 == pos.Y() {
// When a kelp block is broken above, the kelp block underneath it gets a new random age.
w.SetBlock(pos, k.withRandomAge(), nil)
}
below := pos.Side(cube.FaceDown)
belowBlock := w.Block(below)
if _, kelp := belowBlock.(Kelp); !kelp {
if !belowBlock.Model().FaceSolid(below, cube.FaceUp, w) {
w.SetBlock(pos, nil, nil)
}
}
}
// RandomTick ...
func (k Kelp) RandomTick(pos cube.Pos, w *world.World, r *rand.Rand) {
// Every random tick, there's a 14% chance for Kelp to grow if its age is below 25.
if r.Intn(100) < 15 && k.Age < 25 {
abovePos := pos.Side(cube.FaceUp)
liquid, ok := w.Liquid(abovePos)
// For kelp to grow, there must be only water above.
if !ok {
return
} else if _, ok := liquid.(Water); ok {
switch w.Block(abovePos).(type) {
case Air, Water:
w.SetBlock(abovePos, Kelp{Age: k.Age + 1}, nil)
if liquid.LiquidDepth() < 8 {
// When kelp grows into a water block, the water block becomes a source block.
w.SetLiquid(abovePos, Water{Still: true, Depth: 8, Falling: false})
}
}
}
}
}
// allKelp returns all possible states of a kelp block.
func allKelp() (b []world.Block) {
for i := 0; i < 26; i++ {
b = append(b, Kelp{Age: i})
}
return
}