up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"math/rand/v2"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
)
|
||||
|
||||
// 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, tx *world.Tx) item.BoneMealResult {
|
||||
for y := pos.Y(); y <= tx.Range()[1]; y++ {
|
||||
currentPos := cube.Pos{pos.X(), y, pos.Z()}
|
||||
block := tx.Block(currentPos)
|
||||
if kelp, ok := block.(Kelp); ok {
|
||||
if kelp.Age == 25 {
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
if water, ok := block.(Water); ok && water.Depth == 8 {
|
||||
tx.SetBlock(currentPos, Kelp{Age: k.Age + 1}, nil)
|
||||
return item.BoneMealResultSmall
|
||||
}
|
||||
break
|
||||
}
|
||||
return item.BoneMealResultNone
|
||||
}
|
||||
|
||||
// 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.Tx) 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, tx *world.Tx, user item.User, ctx *item.UseContext) (used bool) {
|
||||
pos, _, used = firstReplaceable(tx, pos, face, k)
|
||||
if !used {
|
||||
return
|
||||
}
|
||||
|
||||
below := pos.Side(cube.FaceDown)
|
||||
belowBlock := tx.Block(below)
|
||||
if _, kelp := belowBlock.(Kelp); !kelp {
|
||||
if !belowBlock.Model().FaceSolid(below, cube.FaceUp, tx) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
liquid, ok := tx.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(tx, pos, k.withRandomAge(), user, ctx)
|
||||
return placed(ctx)
|
||||
}
|
||||
|
||||
// NeighbourUpdateTick ...
|
||||
func (k Kelp) NeighbourUpdateTick(pos, changedNeighbour cube.Pos, tx *world.Tx) {
|
||||
if _, ok := tx.Liquid(pos); !ok {
|
||||
breakBlock(k, pos, tx)
|
||||
return
|
||||
}
|
||||
if changedNeighbour[1]-1 == pos.Y() {
|
||||
// When a kelp block is broken above, the kelp block underneath it gets a new random age.
|
||||
tx.SetBlock(pos, k.withRandomAge(), nil)
|
||||
}
|
||||
|
||||
below := pos.Side(cube.FaceDown)
|
||||
belowBlock := tx.Block(below)
|
||||
if _, kelp := belowBlock.(Kelp); !kelp {
|
||||
if !belowBlock.Model().FaceSolid(below, cube.FaceUp, tx) {
|
||||
breakBlock(k, pos, tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RandomTick ...
|
||||
func (k Kelp) RandomTick(pos cube.Pos, tx *world.Tx, 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 := tx.Liquid(abovePos)
|
||||
|
||||
// For kelp to grow, there must be only water above.
|
||||
if !ok {
|
||||
return
|
||||
} else if _, ok := liquid.(Water); ok {
|
||||
switch tx.Block(abovePos).(type) {
|
||||
case Air, Water:
|
||||
tx.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.
|
||||
tx.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
|
||||
}
|
||||
Reference in New Issue
Block a user