github.com/df-mc/dragonfly@v0.9.13/server/block/smoker.go (about) 1 package block 2 3 import ( 4 "github.com/df-mc/dragonfly/server/block/cube" 5 "github.com/df-mc/dragonfly/server/internal/nbtconv" 6 "github.com/df-mc/dragonfly/server/item" 7 "github.com/df-mc/dragonfly/server/world" 8 "github.com/df-mc/dragonfly/server/world/sound" 9 "github.com/go-gl/mathgl/mgl64" 10 "math/rand" 11 "time" 12 ) 13 14 // Smoker is a type of furnace that cooks food items, similar to a furnace, but twice as fast. It also serves as a 15 // butcher's job site block. 16 // The empty value of Smoker is not valid. It must be created using block.NewSmoker(cube.Face). 17 type Smoker struct { 18 solid 19 bassDrum 20 *smelter 21 22 // Facing is the direction the smoker is facing. 23 Facing cube.Face 24 // Lit is true if the smoker is lit. 25 Lit bool 26 } 27 28 // NewSmoker creates a new initialised smoker. The smelter is properly initialised. 29 func NewSmoker(face cube.Face) Smoker { 30 return Smoker{ 31 Facing: face, 32 smelter: newSmelter(), 33 } 34 } 35 36 // Tick is called to check if the smoker should update and start or stop smelting. 37 func (s Smoker) Tick(_ int64, pos cube.Pos, w *world.World) { 38 if s.Lit && rand.Float64() <= 0.016 { // Every three or so seconds. 39 w.PlaySound(pos.Vec3Centre(), sound.SmokerCrackle{}) 40 } 41 if lit := s.smelter.tickSmelting(time.Second*5, time.Millisecond*200, s.Lit, func(i item.SmeltInfo) bool { 42 return i.Food 43 }); s.Lit != lit { 44 s.Lit = lit 45 w.SetBlock(pos, s, nil) 46 } 47 } 48 49 // EncodeItem ... 50 func (s Smoker) EncodeItem() (name string, meta int16) { 51 return "minecraft:smoker", 0 52 } 53 54 // EncodeBlock ... 55 func (s Smoker) EncodeBlock() (name string, properties map[string]interface{}) { 56 if s.Lit { 57 return "minecraft:lit_smoker", map[string]interface{}{"minecraft:cardinal_direction": s.Facing.String()} 58 } 59 return "minecraft:smoker", map[string]interface{}{"minecraft:cardinal_direction": s.Facing.String()} 60 } 61 62 // UseOnBlock ... 63 func (s Smoker) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool { 64 pos, _, used := firstReplaceable(w, pos, face, s) 65 if !used { 66 return false 67 } 68 69 place(w, pos, NewSmoker(user.Rotation().Direction().Face().Opposite()), user, ctx) 70 return placed(ctx) 71 } 72 73 // BreakInfo ... 74 func (s Smoker) BreakInfo() BreakInfo { 75 xp := s.Experience() 76 return newBreakInfo(3.5, alwaysHarvestable, pickaxeEffective, oneOf(s)).withXPDropRange(xp, xp) 77 } 78 79 // Activate ... 80 func (s Smoker) Activate(pos cube.Pos, _ cube.Face, _ *world.World, u item.User, _ *item.UseContext) bool { 81 if opener, ok := u.(ContainerOpener); ok { 82 opener.OpenBlockContainer(pos) 83 return true 84 } 85 return false 86 } 87 88 // EncodeNBT ... 89 func (s Smoker) EncodeNBT() map[string]interface{} { 90 if s.smelter == nil { 91 //noinspection GoAssignmentToReceiver 92 s = NewSmoker(s.Facing) 93 } 94 remaining, maximum, cook := s.Durations() 95 return map[string]interface{}{ 96 "BurnTime": int16(remaining.Milliseconds() / 50), 97 "CookTime": int16(cook.Milliseconds() / 50), 98 "BurnDuration": int16(maximum.Milliseconds() / 50), 99 "StoredXPInt": int16(s.Experience()), 100 "Items": nbtconv.InvToNBT(s.Inventory()), 101 "id": "Smoker", 102 } 103 } 104 105 // DecodeNBT ... 106 func (s Smoker) DecodeNBT(data map[string]interface{}) interface{} { 107 remaining := nbtconv.TickDuration[int16](data, "BurnTime") 108 maximum := nbtconv.TickDuration[int16](data, "BurnDuration") 109 cook := nbtconv.TickDuration[int16](data, "CookTime") 110 111 xp := int(nbtconv.Int16(data, "StoredXPInt")) 112 lit := s.Lit 113 114 //noinspection GoAssignmentToReceiver 115 s = NewSmoker(s.Facing) 116 s.Lit = lit 117 s.setExperience(xp) 118 s.setDurations(remaining, maximum, cook) 119 nbtconv.InvFromNBT(s.Inventory(), nbtconv.Slice(data, "Items")) 120 return s 121 } 122 123 // allSmokers ... 124 func allSmokers() (smokers []world.Block) { 125 for _, face := range cube.HorizontalFaces() { 126 smokers = append(smokers, Smoker{Facing: face}) 127 smokers = append(smokers, Smoker{Facing: face, Lit: true}) 128 } 129 return 130 }