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,142 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/internal/nbtconv"
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/df-mc/dragonfly/server/world/sound"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Smoker is a type of furnace that cooks food items, similar to a furnace, but twice as fast. It also serves as a
|
||||
// butcher's job site block.
|
||||
// The empty value of Smoker is not valid. It must be created using block.NewSmoker(cube.Face).
|
||||
type Smoker struct {
|
||||
solid
|
||||
bassDrum
|
||||
*smelter
|
||||
|
||||
// Facing is the direction the smoker is facing.
|
||||
Facing cube.Direction
|
||||
// Lit is true if the smoker is lit.
|
||||
Lit bool
|
||||
}
|
||||
|
||||
// NewSmoker creates a new initialised smoker. The smelter is properly initialised.
|
||||
func NewSmoker(face cube.Direction) Smoker {
|
||||
return Smoker{
|
||||
Facing: face,
|
||||
smelter: newSmelter(),
|
||||
}
|
||||
}
|
||||
|
||||
// Tick is called to check if the smoker should update and start or stop smelting.
|
||||
func (s Smoker) Tick(_ int64, pos cube.Pos, tx *world.Tx) {
|
||||
if s.Lit && rand.Float64() <= 0.016 { // Every three or so seconds.
|
||||
tx.PlaySound(pos.Vec3Centre(), sound.SmokerCrackle{})
|
||||
}
|
||||
if lit := s.tickSmelting(time.Second*5, time.Millisecond*200, s.Lit, func(i item.SmeltInfo) bool {
|
||||
return i.Food
|
||||
}); s.Lit != lit {
|
||||
s.Lit = lit
|
||||
tx.SetBlock(pos, s, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// LightEmissionLevel ...
|
||||
func (s Smoker) LightEmissionLevel() uint8 {
|
||||
if s.Lit {
|
||||
return 13
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// EncodeItem ...
|
||||
func (s Smoker) EncodeItem() (name string, meta int16) {
|
||||
return "minecraft:smoker", 0
|
||||
}
|
||||
|
||||
// EncodeBlock ...
|
||||
func (s Smoker) EncodeBlock() (name string, properties map[string]interface{}) {
|
||||
if s.Lit {
|
||||
return "minecraft:lit_smoker", map[string]interface{}{"minecraft:cardinal_direction": s.Facing.String()}
|
||||
}
|
||||
return "minecraft:smoker", map[string]interface{}{"minecraft:cardinal_direction": s.Facing.String()}
|
||||
}
|
||||
|
||||
// UseOnBlock ...
|
||||
func (s Smoker) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) bool {
|
||||
pos, _, used := firstReplaceable(tx, pos, face, s)
|
||||
if !used {
|
||||
return false
|
||||
}
|
||||
|
||||
place(tx, pos, NewSmoker(user.Rotation().Direction().Opposite()), user, ctx)
|
||||
return placed(ctx)
|
||||
}
|
||||
|
||||
// BreakInfo ...
|
||||
func (s Smoker) BreakInfo() BreakInfo {
|
||||
xp := s.Experience()
|
||||
return newBreakInfo(3.5, alwaysHarvestable, pickaxeEffective, oneOf(Smoker{})).withXPDropRange(xp, xp).withBreakHandler(func(pos cube.Pos, tx *world.Tx, u item.User) {
|
||||
for _, i := range s.Inventory(tx, pos).Clear() {
|
||||
dropItem(tx, i, pos.Vec3())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Activate ...
|
||||
func (s Smoker) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, u item.User, _ *item.UseContext) bool {
|
||||
if opener, ok := u.(ContainerOpener); ok {
|
||||
opener.OpenBlockContainer(pos, tx)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// EncodeNBT ...
|
||||
func (s Smoker) EncodeNBT() map[string]interface{} {
|
||||
if s.smelter == nil {
|
||||
//noinspection GoAssignmentToReceiver
|
||||
s = NewSmoker(s.Facing)
|
||||
}
|
||||
remaining, maximum, cook := s.Durations()
|
||||
return map[string]interface{}{
|
||||
"BurnTime": int16(remaining.Milliseconds() / 50),
|
||||
"CookTime": int16(cook.Milliseconds() / 50),
|
||||
"BurnDuration": int16(maximum.Milliseconds() / 50),
|
||||
"StoredXPInt": int16(s.Experience()),
|
||||
"Items": nbtconv.InvToNBT(s.inventory),
|
||||
"id": "Smoker",
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeNBT ...
|
||||
func (s Smoker) DecodeNBT(data map[string]interface{}) interface{} {
|
||||
remaining := nbtconv.TickDuration[int16](data, "BurnTime")
|
||||
maximum := nbtconv.TickDuration[int16](data, "BurnDuration")
|
||||
cook := nbtconv.TickDuration[int16](data, "CookTime")
|
||||
|
||||
xp := int(nbtconv.Int16(data, "StoredXPInt"))
|
||||
lit := s.Lit
|
||||
|
||||
//noinspection GoAssignmentToReceiver
|
||||
s = NewSmoker(s.Facing)
|
||||
s.Lit = lit
|
||||
s.setExperience(xp)
|
||||
s.setDurations(remaining, maximum, cook)
|
||||
nbtconv.InvFromNBT(s.inventory, nbtconv.Slice(data, "Items"))
|
||||
return s
|
||||
}
|
||||
|
||||
// allSmokers ...
|
||||
func allSmokers() (smokers []world.Block) {
|
||||
for _, face := range cube.Directions() {
|
||||
smokers = append(smokers, Smoker{Facing: face})
|
||||
smokers = append(smokers, Smoker{Facing: face, Lit: true})
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user