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