feat: Allow breaking itemstacks even further for faster repo reloads

This commit is contained in:
Linnea Gräf
2025-06-22 16:09:43 +02:00
parent 7c45e48050
commit cbc8eff63a
19 changed files with 128 additions and 25 deletions

View File

@@ -13,18 +13,17 @@ import snownee.jade.api.ui.IElementHelper
import snownee.jade.impl.ui.ItemStackElement import snownee.jade.impl.ui.ItemStackElement
import snownee.jade.impl.ui.TextElement import snownee.jade.impl.ui.TextElement
import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrDefault
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.Vec2f import net.minecraft.util.math.Vec2f
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
class DrillToolProvider : IBlockComponentProvider { class DrillToolProvider : IBlockComponentProvider {
@OptIn(ExpensiveItemCacheApi::class)
override fun appendTooltip( override fun appendTooltip(
tooltip: ITooltip, tooltip: ITooltip,
accessor: BlockAccessor, accessor: BlockAccessor,

View File

@@ -29,6 +29,7 @@ import moe.nea.firmament.compat.rei.recipes.SBShopRecipe
import moe.nea.firmament.events.HandledScreenPushREIEvent import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.repo.recipes.SBCraftingRecipeRenderer import moe.nea.firmament.repo.recipes.SBCraftingRecipeRenderer
@@ -44,6 +45,7 @@ import moe.nea.firmament.util.unformattedString
class FirmamentReiPlugin : REIClientPlugin { class FirmamentReiPlugin : REIClientPlugin {
companion object { companion object {
@ExpensiveItemCacheApi
fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> { fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack()) return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack())
} }
@@ -51,6 +53,7 @@ class FirmamentReiPlugin : REIClientPlugin {
val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems") val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems")
} }
@OptIn(ExpensiveItemCacheApi::class)
override fun registerTransferHandlers(registry: TransferHandlerRegistry) { override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
registry.register(TransferHandler { context -> registry.register(TransferHandler { context ->
val screen = context.containerScreen val screen = context.containerScreen

View File

@@ -17,10 +17,13 @@ import me.shedaniel.rei.api.common.entry.EntryStack
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext import net.minecraft.client.gui.DrawContext
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.item.tooltip.TooltipType import net.minecraft.item.tooltip.TooltipType
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.events.ItemTooltipEvent import moe.nea.firmament.events.ItemTooltipEvent
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.ErrorUtil import moe.nea.firmament.util.ErrorUtil
@@ -32,6 +35,7 @@ import moe.nea.firmament.util.mc.loreAccordingToNbt
// TODO: make this re implement BatchedEntryRenderer, if possible (likely not, due to no-alloc rendering) // TODO: make this re implement BatchedEntryRenderer, if possible (likely not, due to no-alloc rendering)
// Also it is probably not even that much faster now, with render layers. // Also it is probably not even that much faster now, with render layers.
object NEUItemEntryRenderer : EntryRenderer<SBItemStack> { object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
@OptIn(ExpensiveItemCacheApi::class)
override fun render( override fun render(
entry: EntryStack<SBItemStack>, entry: EntryStack<SBItemStack>,
context: DrawContext, context: DrawContext,
@@ -40,13 +44,20 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
mouseY: Int, mouseY: Int,
delta: Float delta: Float
) { ) {
val neuItem = entry.value.neuItem
val itemToRender = if(RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER && !entry.value.isWarm() && neuItem != null) {
ItemCache.recacheSoon(neuItem)
ItemStack(Items.PAINTING)
} else {
entry.value.asImmutableItemStack()
}
context.matrices.push() context.matrices.push()
context.matrices.translate(bounds.centerX.toFloat(), bounds.centerY.toFloat(), 0F) context.matrices.translate(bounds.centerX.toFloat(), bounds.centerY.toFloat(), 0F)
context.matrices.scale(bounds.width.toFloat() / 16F, bounds.height.toFloat() / 16F, 1f) context.matrices.scale(bounds.width.toFloat() / 16F, bounds.height.toFloat() / 16F, 1f)
val item = entry.asItemEntry().value context.drawItemWithoutEntity(itemToRender, -8, -8)
context.drawItemWithoutEntity(item, -8, -8)
context.drawStackOverlay( context.drawStackOverlay(
minecraft.textRenderer, item, -8, -8, minecraft.textRenderer, itemToRender, -8, -8,
if (entry.value.getStackSize() > 1000) FirmFormatters.shortFormat( if (entry.value.getStackSize() > 1000) FirmFormatters.shortFormat(
entry.value.getStackSize() entry.value.getStackSize()
.toDouble() .toDouble()
@@ -59,8 +70,9 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
val minecraft = MinecraftClient.getInstance() val minecraft = MinecraftClient.getInstance()
var canUseVanillaTooltipEvents = true var canUseVanillaTooltipEvents = true
@OptIn(ExpensiveItemCacheApi::class)
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? { override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
if (!entry.value.isWarm() && !RepoManager.Config.perfectTooltips) { if (!entry.value.isWarm() && RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER_AND_TEXT) {
val neuItem = entry.value.neuItem val neuItem = entry.value.neuItem
if (neuItem != null) { if (neuItem != null) {
val lore = mutableListOf<Text>() val lore = mutableListOf<Text>()

View File

@@ -15,6 +15,7 @@ import net.minecraft.registry.tag.TagKey
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
@@ -24,6 +25,7 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize() return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize()
} }
@OptIn(ExpensiveItemCacheApi::class)
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack { override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
return value.asCopiedItemStack() return value.asCopiedItemStack()
} }
@@ -41,9 +43,10 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
return Stream.empty() return Stream.empty()
} }
@OptIn(ExpensiveItemCacheApi::class)
override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text { override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
val neuItem = entry.value.neuItem val neuItem = entry.value.neuItem
return if (RepoManager.Config.perfectTooltips || entry.value.isWarm() || neuItem == null) { return if (RepoManager.Config.perfectRenders < RepoManager.PerfectRender.RENDER_AND_TEXT || entry.value.isWarm() || neuItem == null) {
VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack()) VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack())
} else { } else {
Text.literal(neuItem.displayName) Text.literal(neuItem.displayName)

View File

@@ -1,3 +1,5 @@
@file:OptIn(ExpensiveItemCacheApi::class)
package moe.nea.firmament.compat.rei.recipes package moe.nea.firmament.compat.rei.recipes
import java.util.Optional import java.util.Optional
@@ -27,6 +29,7 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.compat.rei.EntityWidget import moe.nea.firmament.compat.rei.EntityWidget
import moe.nea.firmament.compat.rei.SBItemEntryDefinition import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.gui.entity.EntityRenderer import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.Reforge import moe.nea.firmament.repo.Reforge
import moe.nea.firmament.repo.ReforgeStore import moe.nea.firmament.repo.ReforgeStore
import moe.nea.firmament.repo.RepoItemTypeCache import moe.nea.firmament.repo.RepoItemTypeCache

View File

@@ -6,6 +6,7 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache import moe.nea.firmament.repo.ItemCache
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
@@ -57,6 +58,7 @@ object LegacyItemData {
val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) } val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) }
val itemDat = getLegacyData<List<ItemData>>("items") val itemDat = getLegacyData<List<ItemData>>("items")
@OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread.
val itemLut = itemDat.flatMap { item -> val itemLut = itemDat.flatMap { item ->
item.allVariants().map { legacyItemType -> item.allVariants().map { legacyItemType ->
val nbt = ItemCache.convert189ToModern(NbtCompound().apply { val nbt = ItemCache.convert189ToModern(NbtCompound().apply {

View File

@@ -15,6 +15,7 @@ import moe.nea.firmament.events.WorldReadyEvent
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.gui.hud.MoulConfigHud import moe.nea.firmament.gui.hud.MoulConfigHud
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemNameLookup import moe.nea.firmament.repo.ItemNameLookup
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
@@ -202,7 +203,8 @@ object AnniversaryFeatures : FirmamentFeature {
SBItemStack(SkyblockId.NULL) SBItemStack(SkyblockId.NULL)
} }
@Bind @OptIn(ExpensiveItemCacheApi::class)
@Bind
fun name(): String { fun name(): String {
return when (backedBy) { return when (backedBy) {
is Reward.Coins -> "Coins" is Reward.Coins -> "Coins"

View File

@@ -8,6 +8,7 @@ import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ScreenChangeEvent import moe.nea.firmament.events.ScreenChangeEvent
import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.events.SlotRenderEvents
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.skyblockId import moe.nea.firmament.util.skyblockId
@@ -45,6 +46,7 @@ object CraftingOverlay : FirmamentFeature {
override val identifier: String override val identifier: String
get() = "crafting-overlay" get() = "crafting-overlay"
@OptIn(ExpensiveItemCacheApi::class)
@Subscribe @Subscribe
fun onSlotRender(event: SlotRenderEvents.After) { fun onSlotRender(event: SlotRenderEvents.After) {
val slot = event.slot val slot = event.slot

View File

@@ -3,6 +3,7 @@ package moe.nea.firmament.features.inventory
import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.HandledScreenKeyPressedEvent import moe.nea.firmament.events.HandledScreenKeyPressedEvent
import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.HypixelStaticData import moe.nea.firmament.repo.HypixelStaticData
import moe.nea.firmament.repo.ItemCache import moe.nea.firmament.repo.ItemCache
import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ItemCache.asItemStack
@@ -18,6 +19,7 @@ object ItemHotkeys {
val openGlobalTradeInterface by keyBindingWithDefaultUnbound("global-trade-interface") val openGlobalTradeInterface by keyBindingWithDefaultUnbound("global-trade-interface")
} }
@OptIn(ExpensiveItemCacheApi::class)
@Subscribe @Subscribe
fun onHandledInventoryPress(event: HandledScreenKeyPressedEvent) { fun onHandledInventoryPress(event: HandledScreenKeyPressedEvent) {
if (!event.matches(TConfig.openGlobalTradeInterface)) { if (!event.matches(TConfig.openGlobalTradeInterface)) {

View File

@@ -11,6 +11,7 @@ import net.minecraft.command.argument.ItemStackArgumentType
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.resource.featuretoggle.FeatureFlags import net.minecraft.resource.featuretoggle.FeatureFlags
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ItemCache.asItemStack
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
@@ -40,6 +41,7 @@ data class InventoryButton(
} }
val dimensions = Dimension(18, 18) val dimensions = Dimension(18, 18)
val getItemForName = ::getItemForName0.memoize(1024) val getItemForName = ::getItemForName0.memoize(1024)
@OptIn(ExpensiveItemCacheApi::class)
fun getItemForName0(icon: String): ItemStack { fun getItemForName0(icon: String): ItemStack {
val repoItem = RepoManager.getNEUItem(SkyblockId(icon)) val repoItem = RepoManager.getNEUItem(SkyblockId(icon))
var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon)) var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon))

View File

@@ -8,6 +8,7 @@ import net.minecraft.entity.LivingEntity
import net.minecraft.item.Item import net.minecraft.item.Item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.Items import net.minecraft.item.Items
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.mc.setEncodedSkullOwner import moe.nea.firmament.util.mc.setEncodedSkullOwner
@@ -31,6 +32,7 @@ object ModifyEquipment : EntityModifier {
return entity return entity
} }
@OptIn(ExpensiveItemCacheApi::class)
private fun createItem(item: String): ItemStack { private fun createItem(item: String): ItemStack {
val split = item.split("#") val split = item.split("#")
if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack() if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()

View File

@@ -0,0 +1,8 @@
package moe.nea.firmament.repo
/**
* Marker for functions that could potentially invoke DFU. Please do not call on a lot of objects at once, or try to make sure the item is cached and fall back to a more gentle function call using [SBItemStack.isWarm] and similar functions.
*/
@RequiresOptIn
@Retention(AnnotationRetention.BINARY)
annotation class ExpensiveItemCacheApi

View File

@@ -8,8 +8,14 @@ import java.text.NumberFormat
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import kotlinx.coroutines.Job import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull
import net.minecraft.SharedConstants import net.minecraft.SharedConstants
import net.minecraft.component.DataComponentTypes import net.minecraft.component.DataComponentTypes
@@ -30,6 +36,7 @@ import moe.nea.firmament.repo.RepoManager.initialize
import moe.nea.firmament.util.LegacyFormattingCode import moe.nea.firmament.util.LegacyFormattingCode
import moe.nea.firmament.util.LegacyTagParser import moe.nea.firmament.util.LegacyTagParser
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.TestUtil import moe.nea.firmament.util.TestUtil
import moe.nea.firmament.util.directLiteralStringContent import moe.nea.firmament.util.directLiteralStringContent
@@ -40,6 +47,7 @@ import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.mc.modifyLore import moe.nea.firmament.util.mc.modifyLore
import moe.nea.firmament.util.mc.setCustomName import moe.nea.firmament.util.mc.setCustomName
import moe.nea.firmament.util.mc.setSkullOwner import moe.nea.firmament.util.mc.setSkullOwner
import moe.nea.firmament.util.skyblockId
import moe.nea.firmament.util.transformEachRecursively import moe.nea.firmament.util.transformEachRecursively
object ItemCache : IReloadable { object ItemCache : IReloadable {
@@ -56,7 +64,10 @@ object ItemCache : IReloadable {
putShort("Damage", damage.toShort()) putShort("Damage", damage.toShort())
} }
@ExpensiveItemCacheApi
private fun NbtCompound.transformFrom10809ToModern() = convert189ToModern(this@transformFrom10809ToModern) private fun NbtCompound.transformFrom10809ToModern() = convert189ToModern(this@transformFrom10809ToModern)
@ExpensiveItemCacheApi
fun convert189ToModern(nbtComponent: NbtCompound): NbtCompound? = fun convert189ToModern(nbtComponent: NbtCompound): NbtCompound? =
try { try {
df.update( df.update(
@@ -126,6 +137,7 @@ object ItemCache : IReloadable {
return base return base
} }
@ExpensiveItemCacheApi
private fun NEUItem.asItemStackNow(): ItemStack { private fun NEUItem.asItemStackNow(): ItemStack {
try { try {
val oldItemTag = get10809CompoundTag() val oldItemTag = get10809CompoundTag()
@@ -150,6 +162,7 @@ object ItemCache : IReloadable {
return skyblockId.neuItem in cache return skyblockId.neuItem in cache
} }
@ExpensiveItemCacheApi
fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack { fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack {
if (this == null) return brokenItemStack(null, idHint) if (this == null) return brokenItemStack(null, idHint)
var s = cache[this.skyblockItemId] var s = cache[this.skyblockItemId]
@@ -183,22 +196,43 @@ object ItemCache : IReloadable {
} }
} }
var job: Job? = null var itemRecacheScope: CoroutineScope? = null
override fun reload(repository: NEURepository) { private var recacheSoonSubmitted = mutableSetOf<SkyblockId>()
val j = job
if (j != null && j.isActive) { @OptIn(ExpensiveItemCacheApi::class)
j.cancel() fun recacheSoon(neuItem: NEUItem) {
itemRecacheScope?.launch {
if (!withContext(MinecraftDispatcher) {
recacheSoonSubmitted.add(neuItem.skyblockId)
}) {
return@launch
}
neuItem.asItemStack()
} }
}
@OptIn(ExpensiveItemCacheApi::class)
override fun reload(repository: NEURepository) {
val j = itemRecacheScope
j?.cancel("New reload invoked")
cache.clear() cache.clear()
isFlawless = true isFlawless = true
if (TestUtil.isInTest) return if (TestUtil.isInTest) return
job = Firmament.coroutineScope.launch { val newScope =
val items = repository.items?.items ?: return@launch CoroutineScope(Firmament.coroutineScope.coroutineContext + SupervisorJob(Firmament.globalJob) + Dispatchers.Default)
items.values.forEach { val items = repository.items?.items
it.asItemStack() // Rebuild cache newScope.launch {
} val items = items ?: return@launch
items.values.chunked(500).map { chunk ->
async {
chunk.forEach {
it.asItemStack() // Rebuild cache
}
}
}.awaitAll()
} }
itemRecacheScope = newScope
} }
fun coinItem(coinAmount: Int): ItemStack { fun coinItem(coinAmount: Int): ItemStack {

View File

@@ -81,6 +81,7 @@ class MiningRepoData : IReloadable {
) { ) {
@Transient @Transient
val dropItem = baseDrop?.let(::SBItemStack) val dropItem = baseDrop?.let(::SBItemStack)
@OptIn(ExpensiveItemCacheApi::class)
private val labeledStack by lazy { private val labeledStack by lazy {
dropItem?.asCopiedItemStack()?.also(::markItemStack) dropItem?.asCopiedItemStack()?.also(::markItemStack)
} }
@@ -110,6 +111,7 @@ class MiningRepoData : IReloadable {
fun isActiveIn(location: SkyBlockIsland) = onlyIn == null || location in onlyIn fun isActiveIn(location: SkyBlockIsland) = onlyIn == null || location in onlyIn
@OptIn(ExpensiveItemCacheApi::class)
private fun convertToModernBlock(): Block? { private fun convertToModernBlock(): Block? {
// TODO: this should be in a shared util, really // TODO: this should be in a shared util, really
val newCompound = ItemCache.convert189ToModern(NbtCompound().apply { val newCompound = ItemCache.convert189ToModern(NbtCompound().apply {

View File

@@ -11,6 +11,7 @@ import kotlinx.coroutines.launch
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
import net.minecraft.recipe.display.CuttingRecipeDisplay import net.minecraft.recipe.display.CuttingRecipeDisplay
import net.minecraft.util.StringIdentifiable
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.Firmament.logger import moe.nea.firmament.Firmament.logger
import moe.nea.firmament.events.ReloadRegistrationEvent import moe.nea.firmament.events.ReloadRegistrationEvent
@@ -46,7 +47,16 @@ object RepoManager {
} }
val alwaysSuperCraft by toggle("enable-super-craft") { true } val alwaysSuperCraft by toggle("enable-super-craft") { true }
var warnForMissingItemListMod by toggle("warn-for-missing-item-list-mod") { true } var warnForMissingItemListMod by toggle("warn-for-missing-item-list-mod") { true }
val perfectTooltips by toggle("perfect-tooltips") { false } val perfectRenders by choice("perfect-renders") { PerfectRender.RENDER }
}
enum class PerfectRender(val label: String) : StringIdentifiable {
NOTHING("nothing"),
RENDER("render"),
RENDER_AND_TEXT("text"),
;
override fun asString(): String? = label
} }
val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash
@@ -136,8 +146,10 @@ object RepoManager {
} catch (exc: NEURepositoryException) { } catch (exc: NEURepositoryException) {
ErrorUtil.softError("Failed to reload repository", exc) ErrorUtil.softError("Failed to reload repository", exc)
MC.sendChat( MC.sendChat(
tr("firmament.repo.reloadfail", tr(
"Failed to reload repository. This will result in some mod features not working.") "firmament.repo.reloadfail",
"Failed to reload repository. This will result in some mod features not working."
)
) )
} }
} }

View File

@@ -353,7 +353,9 @@ data class SBItemStack constructor(
} }
// TODO: avoid instantiating the item stack here // TODO: avoid instantiating the item stack here
@ExpensiveItemCacheApi
val itemType: ItemType? get() = ItemType.fromItemStack(asImmutableItemStack()) val itemType: ItemType? get() = ItemType.fromItemStack(asImmutableItemStack())
@ExpensiveItemCacheApi
val rarity: Rarity? get() = Rarity.fromItem(asImmutableItemStack()) val rarity: Rarity? get() = Rarity.fromItem(asImmutableItemStack())
private var itemStack_: ItemStack? = null private var itemStack_: ItemStack? = null
@@ -364,6 +366,7 @@ data class SBItemStack constructor(
group("power").toInt() group("power").toInt()
} ?: 0 } ?: 0
@ExpensiveItemCacheApi
private val itemStack: ItemStack private val itemStack: ItemStack
get() { get() {
val itemStack = itemStack_ ?: run { val itemStack = itemStack_ ?: run {
@@ -437,15 +440,18 @@ data class SBItemStack constructor(
return false return false
} }
@OptIn(ExpensiveItemCacheApi::class)
fun asLazyImmutableItemStack(): ItemStack? { fun asLazyImmutableItemStack(): ItemStack? {
if (isWarm()) return asImmutableItemStack() if (isWarm()) return asImmutableItemStack()
return null return null
} }
fun asImmutableItemStack(): ItemStack { @ExpensiveItemCacheApi
fun asImmutableItemStack(): ItemStack { // TODO: add a "or fallback to painting" option to asLazyImmutableItemStack to be used in more places.
return itemStack return itemStack
} }
@ExpensiveItemCacheApi
fun asCopiedItemStack(): ItemStack { fun asCopiedItemStack(): ItemStack {
return itemStack.copy() return itemStack.copy()
} }

View File

@@ -9,6 +9,7 @@ import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.repo.EssenceRecipeProvider import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
@@ -62,6 +63,7 @@ object SBEssenceUpgradeRecipeRenderer : GenericRecipeRenderer<EssenceRecipeProvi
return listOfNotNull(SBItemStack(recipe.itemId)) return listOfNotNull(SBItemStack(recipe.itemId))
} }
@OptIn(ExpensiveItemCacheApi::class)
override val icon: ItemStack get() = SBItemStack(SkyblockId("ESSENCE_WITHER")).asImmutableItemStack() override val icon: ItemStack get() = SBItemStack(SkyblockId("ESSENCE_WITHER")).asImmutableItemStack()
override val title: Text = tr("firmament.category.essence", "Essence Upgrades") override val title: Text = tr("firmament.category.essence", "Essence Upgrades")
override val identifier: Identifier = Firmament.identifier("essence_upgrade") override val identifier: Identifier = Firmament.identifier("essence_upgrade")

View File

@@ -22,6 +22,7 @@ import net.minecraft.network.codec.PacketCodec
import net.minecraft.network.codec.PacketCodecs import net.minecraft.network.codec.PacketCodecs
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.repo.ExpLadders import moe.nea.firmament.repo.ExpLadders
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ItemCache.asItemStack
import moe.nea.firmament.repo.set import moe.nea.firmament.repo.set
import moe.nea.firmament.util.collections.WeakCache import moe.nea.firmament.util.collections.WeakCache
@@ -86,6 +87,7 @@ value class SkyblockId(val neuItem: String) : Comparable<SkyblockId> {
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId) val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
val NEUIngredient.skyblockId get() = SkyblockId(itemId) val NEUIngredient.skyblockId get() = SkyblockId(itemId)
@ExpensiveItemCacheApi
fun NEUItem.guessRecipeId(): String? { fun NEUItem.guessRecipeId(): String? {
if (!skyblockItemId.contains(";")) return skyblockItemId if (!skyblockItemId.contains(";")) return skyblockItemId
val item = this.asItemStack() val item = this.asItemStack()

View File

@@ -248,6 +248,11 @@
"firmament.config.repo.disable-item-groups.description": "Disabling item groups can increase performance, but will no longer collect similar items (like minions, enchantments) together.", "firmament.config.repo.disable-item-groups.description": "Disabling item groups can increase performance, but will no longer collect similar items (like minions, enchantments) together.",
"firmament.config.repo.enable-super-craft": "Always use Super Craft", "firmament.config.repo.enable-super-craft": "Always use Super Craft",
"firmament.config.repo.enable-super-craft.description": "Always use super craft when clicking the craft button in REI, instead of just when holding shift.", "firmament.config.repo.enable-super-craft.description": "Always use super craft when clicking the craft button in REI, instead of just when holding shift.",
"firmament.config.repo.perfect-renders": "Perfect Render",
"firmament.config.repo.perfect-renders.choice.nothing": "Broken (Fastest)",
"firmament.config.repo.perfect-renders.choice.render": "Fixed Visual (Fast)",
"firmament.config.repo.perfect-renders.choice.render_and_text": "Perfect (Slowest)",
"firmament.config.repo.perfect-renders.description": "Speed up item list loading by allowing items to be loaded in partially incorrectly at first. They will be corrected down the line when the background reload completes.",
"firmament.config.repo.redownload": "Redownload Item List", "firmament.config.repo.redownload": "Redownload Item List",
"firmament.config.repo.redownload.description": "Force re-download the item list. This is automatically done on restart.", "firmament.config.repo.redownload.description": "Force re-download the item list. This is automatically done on restart.",
"firmament.config.repo.reload": "Reload Item List", "firmament.config.repo.reload": "Reload Item List",