aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt
blob: 19ae6067c45b0e922857a1fae40f6c8cd0abddb2 (plain)
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
package moe.nea.notenoughupdates.repo

import com.mojang.serialization.Dynamic
import io.github.cottonmc.cotton.gui.client.CottonHud
import io.github.moulberry.repo.IReloadable
import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.data.NEUItem
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import moe.nea.notenoughupdates.NotEnoughUpdates
import moe.nea.notenoughupdates.util.LegacyTagParser
import moe.nea.notenoughupdates.util.appendLore
import net.minecraft.datafixer.Schemas
import net.minecraft.datafixer.TypeReferences
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtOps
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import java.io.PrintWriter
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap
import kotlin.io.path.absolutePathString
import kotlin.io.path.writer

object ItemCache : IReloadable {
    val dfuLog = Path.of("logs/dfulog.txt")
    private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
    private val df = Schemas.getFixer()
    private val dfuHandle = PrintWriter(dfuLog.writer())
    var isFlawless = true
        private set

    private fun NEUItem.get10809CompoundTag(): NbtCompound = NbtCompound().apply {
        put("tag", LegacyTagParser.parse(nbttag))
        putString("id", minecraftItemId)
        putByte("Count", 1)
        putShort("Damage", damage.toShort())
    }

    private fun NbtCompound.transformFrom10809ToModern(): NbtCompound? =
        try {
            df.update(
                TypeReferences.ITEM_STACK,
                Dynamic(NbtOps.INSTANCE, this),
                -1,
                2975
            ).value as NbtCompound
        } catch (e: Exception) {
            if (isFlawless)
                NotEnoughUpdates.logger.error("Failed to run data fixer an item. Check ${dfuLog.absolutePathString()} for more information")
            isFlawless = false
            e.printStackTrace(dfuHandle)
            null
        }

    private fun NEUItem.asItemStackNow(): ItemStack {
        val oldItemTag = get10809CompoundTag()
        val modernItemTag = oldItemTag.transformFrom10809ToModern()
            ?: return ItemStack(Items.PAINTING).apply {
                setCustomName(Text.literal(this@asItemStackNow.displayName))
                appendLore(listOf(Text.literal("Exception rendering item: $skyblockItemId")))
            }
        val itemInstance = ItemStack.fromNbt(modernItemTag)
        if (itemInstance.nbt?.contains("Enchantments") == true) {
            itemInstance.enchantments.add(NbtCompound())
        }
        return itemInstance
    }

    fun NEUItem.asItemStack(): ItemStack {
        var s = cache[this.skyblockItemId]
        if (s == null) {
            s = asItemStackNow()
            cache[this.skyblockItemId] = s
        }
        return s
    }

    fun NEUItem.getIdentifier() =
        Identifier("skyblockitem", skyblockItemId.lowercase().replace(";", "__"))


    var job: Job? = null

    override fun reload(repository: NEURepository) {
        val j = job
        if (j != null && j.isActive) {
            j.cancel()
        }
        cache.clear()
        isFlawless = true

        job = NotEnoughUpdates.coroutineScope.launch {
            val items = repository.items?.items
            if (items == null) {
                CottonHud.remove(RepoManager.progressBar)
                return@launch
            }
            RepoManager.progressBar.reportProgress("Recache Items", 0, items.size)
            CottonHud.add(RepoManager.progressBar)
            var i = 0
            items.values.forEach {
                it.asItemStack() // Rebuild cache
                RepoManager.progressBar.reportProgress("Recache Items", i++, items.size)
            }
            CottonHud.remove(RepoManager.progressBar)
        }
    }
}