-
Notifications
You must be signed in to change notification settings - Fork 140
/
break_info.go
156 lines (135 loc) · 5.1 KB
/
break_info.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
155
156
package block
import (
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/item/tool"
"github.com/df-mc/dragonfly/server/world"
"math"
"time"
)
// Breakable represents a block that may be broken by a player in survival mode. Blocks not include are blocks
// such as bedrock.
type Breakable interface {
// BreakInfo returns information of the block related to the breaking of it.
BreakInfo() BreakInfo
}
// BreakDuration returns the base duration that breaking the block passed takes when being broken using the
// item passed.
func BreakDuration(b world.Block, i item.Stack) time.Duration {
breakable, ok := b.(Breakable)
if !ok {
return math.MaxInt64
}
t, ok := i.Item().(tool.Tool)
if !ok {
t = tool.None{}
}
info := breakable.BreakInfo()
breakTime := info.Hardness * 5
if info.Harvestable(t) {
breakTime = info.Hardness * 1.5
}
if info.Effective(t) {
breakTime /= t.BaseMiningEfficiency(b)
}
// TODO: Account for haste, efficiency etc here.
timeInTicksAccurate := math.Round(breakTime/0.05) * 0.05
return (time.Duration(math.Round(timeInTicksAccurate*20)) * time.Second) / 20
}
// BreaksInstantly checks if the block passed can be broken instantly using the item stack passed to break
// it.
func BreaksInstantly(b world.Block, i item.Stack) bool {
breakable, ok := b.(Breakable)
if !ok {
return false
}
hardness := breakable.BreakInfo().Hardness
if hardness == 0 {
return true
}
t, ok := i.Item().(tool.Tool)
if !ok || !breakable.BreakInfo().Effective(t) {
return false
}
// TODO: Account for haste, efficiency etc here.
efficiencyVal := 0.0
hasteVal := 0.0
return (t.BaseMiningEfficiency(b)+efficiencyVal)*hasteVal >= hardness*30
}
// BreakInfo is a struct returned by every block. It holds information on block breaking related data, such as
// the tool type and tier required to break it.
type BreakInfo struct {
// Hardness is the hardness of the block, which influences the speed with which the block may be mined.
Hardness float64
// Harvestable is a function called to check if the block is harvestable using the tool passed. If the
// item used to break the block is not a tool, a tool.None is passed.
Harvestable func(t tool.Tool) bool
// Effective is a function called to check if the block can be mined more effectively with the tool passed
// than with an empty hand.
Effective func(t tool.Tool) bool
// Drops is a function called to get the drops of the block if it is broken using the tool passed. If the
// item used to break the block is not a tool, a tool.None is passed.
Drops func(t tool.Tool) []item.Stack
// XPDrops is the range of XP a block can drop when broken.
XPDrops XPDropRange
}
// newBreakInfo creates a BreakInfo struct with the properties passed. The XPDrops field is 0 by default.
func newBreakInfo(hardness float64, harvestable func(tool.Tool) bool, effective func(tool.Tool) bool, drops func(tool2 tool.Tool) []item.Stack) BreakInfo {
return BreakInfo{
Hardness: hardness,
Harvestable: harvestable,
Effective: effective,
Drops: drops,
}
}
// XPDropRange holds the min & max XP drop amounts of blocks.
type XPDropRange [2]int
// pickaxeEffective is a convenience function for blocks that are effectively mined with a pickaxe.
var pickaxeEffective = func(t tool.Tool) bool {
return t.ToolType() == tool.TypePickaxe
}
// axeEffective is a convenience function for blocks that are effectively mined with an axe.
var axeEffective = func(t tool.Tool) bool {
return t.ToolType() == tool.TypeAxe
}
// shearsEffective is a convenience function for blocks that are effectively mined with shears.
var shearsEffective = func(t tool.Tool) bool {
return t.ToolType() == tool.TypeShears
}
// shovelEffective is a convenience function for blocks that are effectively mined with a shovel.
var shovelEffective = func(t tool.Tool) bool {
return t.ToolType() == tool.TypeShovel
}
// hoeEffective is a convenience function for blocks that are effectively mined with a hoe.
var hoeEffective = func(t tool.Tool) bool {
return t.ToolType() == tool.TypeHoe
}
// nothingEffective is a convenience function for blocks that cannot be mined efficiently with any tool.
var nothingEffective = func(tool.Tool) bool {
return false
}
// alwaysHarvestable is a convenience function for blocks that are harvestable using any item.
var alwaysHarvestable = func(t tool.Tool) bool {
return true
}
// neverHarvestable is a convenience function for blocks that are not harvestable by any item.
var neverHarvestable = func(t tool.Tool) bool {
return false
}
// pickaxeHarvestable is a convenience function for blocks that are harvestable using any kind of pickaxe.
var pickaxeHarvestable = pickaxeEffective
// simpleDrops returns a drops function that returns the items passed.
func simpleDrops(s ...item.Stack) func(t tool.Tool) []item.Stack {
return func(t tool.Tool) []item.Stack {
return s
}
}
// oneOf returns a drops function that returns one of each of the item types passed.
func oneOf(i ...world.Item) func(t tool.Tool) []item.Stack {
return func(t tool.Tool) []item.Stack {
var s []item.Stack
for _, it := range i {
s = append(s, item.NewStack(it, 1))
}
return s
}
}