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
|
package moe.nea.firmament.repo.item
import kotlin.collections.runningFold
import net.minecraft.item.ItemStack
import moe.nea.firmament.repo.RepoManager
class SBItemData {
private var itemCache: ItemStack? = null
private val data: MutableMap<SBItemProperty<*>, Any> = mutableMapOf()
fun <T> getData(prop: SBItemProperty<T>): T? {
return data[prop] as T?
}
fun <Prop : SBItemProperty<T>, T> set(property: Prop, data: T) {
if (data != null) {
(this.data as MutableMap<Any, Any>)[property] = data
} else {
this.data.remove(property)
}
itemCache = null
}
private fun <T> enhanceStack(stack: ItemStack, property: SBItemProperty.State<T>): ItemStack {
val data = getData(property)
return property.applyToStack(stack, this, data)
}
private fun createStack(): ItemStack {
return SBItemProperty.allStates.fold(ItemStack.EMPTY) { stack, prop ->
enhanceStack(stack, prop)
}
}
fun debugStackCreation(): List<PartialStack<*>> {
fun <T> combinedEnhanceStack(previous: PartialStack<*>, mod: SBItemProperty.State<T>): PartialStack<T> {
val nextStack = enhanceStack(previous.stack.copy(), mod)
return PartialStack(mod, getData(mod), nextStack)
}
return SBItemProperty.allStates
.runningFold(
PartialStack<Nothing>(null, null, ItemStack.EMPTY)) { stack: PartialStack<*>, prop ->
combinedEnhanceStack(stack, prop)
}
}
/**
* Creates an [ItemStack] based on the current properties. The returned item stack must not be modified by the
* caller.
*/
fun toImmutableStack(): ItemStack {
var cached = itemCache
if (cached == null) {
cached = createStack()
itemCache = cached
}
return cached
}
data class PartialStack<T>(
val lastAppliedModifier: SBItemProperty<T>?,
val data: T?,
val stack: ItemStack,
)
companion object {
/**
* Create an [SBItemData] from only the given characteristica. Any unspecified characteristica will be non-existent.
* If you want to compute all other properties based on the given properties, use [roundtrip].
*/
fun fromCharacteristica(
vararg char: SBItemProperty.BoundState<*>
): SBItemData {
val store = SBItemData()
char.forEach {
it.applyTo(store)
}
return store
}
fun fromStack(itemStack: ItemStack): SBItemData {
val store = SBItemData()
store.loadFrom(itemStack)
return store
}
}
/**
* Creates a new [SBItemData] from the item stack this [SBItemData] produces. This will initialize all properties.
*/
fun roundtrip(): SBItemData {
return fromStack(toImmutableStack())
}
/**
* Creates a new [SBItemData] with cheap inferences completed only by using data available in [io.github.moulberry.repo.data.NEUItem]. This is a cheaper version of [roundtrip], that does not create any [ItemStack]s, and preserves all properties already provided. Check if the property you need overrides [SBItemProperty.fromNeuItem].
*/
fun cheapInfer(): SBItemData {
val neuItem = getData(SBItemId)?.let { RepoManager.getNEUItem(it) } ?: return this
val store = SBItemData()
SBItemProperty.allProperties.forEach {
it.fromNeuItem(neuItem, this)
}
store.data.putAll(this.data)
return store
}
private fun loadFrom(stack: ItemStack) {
SBItemProperty.allProperties.forEach {
loadModifier(stack, it)
}
}
private fun <T> loadModifier(
stack: ItemStack,
modifier: SBItemProperty<T>
) {
val data = modifier.fromStack(stack, this) ?: return
set(modifier, data)
}
}
|