From 3ebe3e80b929b03ad0bcb0c76cec6b3285fe08bd Mon Sep 17 00:00:00 2001 From: nea Date: Thu, 18 May 2023 01:07:35 +0200 Subject: Make recipes with higher stack counts properly display --- TODO.txt | 1 + .../moe/nea/firmament/rei/FirmamentReiPlugin.kt | 5 +- .../moe/nea/firmament/rei/NEUItemEntryRenderer.kt | 7 +-- .../nea/firmament/rei/NEUItemEntrySerializer.kt | 15 +++-- .../moe/nea/firmament/rei/SBItemEntryDefinition.kt | 71 ++++++++++++---------- .../rei/SkyblockCraftingRecipeDynamicGenerator.kt | 4 +- .../rei/SkyblockItemIdFocusedStackProvider.kt | 8 +-- .../kotlin/moe/nea/firmament/repo/ItemCache.kt | 29 ++++----- .../kotlin/moe/nea/firmament/repo/RepoManager.kt | 3 +- .../kotlin/moe/nea/firmament/util/SkyblockId.kt | 4 ++ 10 files changed, 81 insertions(+), 66 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5830ccb..30885e2 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,4 +1,5 @@ - recipes + - more recipe categories - replace REI with custom renderer (if needed) - easy config gui builder - Storage Overlay diff --git a/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt b/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt index 992b104..05ea769 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt @@ -1,6 +1,5 @@ package moe.nea.firmament.rei -import io.github.moulberry.repo.data.NEUItem import me.shedaniel.rei.api.client.plugins.REIClientPlugin import me.shedaniel.rei.api.client.registry.category.CategoryRegistry import me.shedaniel.rei.api.client.registry.display.DisplayRegistry @@ -23,7 +22,7 @@ import moe.nea.firmament.util.SkyblockId class FirmamentReiPlugin : REIClientPlugin { companion object { - fun EntryStack.asItemEntry(): EntryStack { + fun EntryStack.asItemEntry(): EntryStack { return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack()) } @@ -67,7 +66,7 @@ class FirmamentReiPlugin : REIClientPlugin { override fun registerEntries(registry: EntryRegistry) { RepoManager.neuRepo.items?.items?.values?.forEach { if (!it.isVanilla) - registry.addEntry(EntryStack.of(SBItemEntryDefinition, it)) + registry.addEntry(SBItemEntryDefinition.getEntry(it)) } } } diff --git a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt index 8253c96..a6a62e6 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt @@ -1,6 +1,5 @@ package moe.nea.firmament.rei -import io.github.moulberry.repo.data.NEUItem import me.shedaniel.math.Rectangle import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer import me.shedaniel.rei.api.client.gui.widgets.Tooltip @@ -9,9 +8,9 @@ import me.shedaniel.rei.api.common.entry.EntryStack import net.minecraft.client.util.math.MatrixStack import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry -object NEUItemEntryRenderer : EntryRenderer { +object NEUItemEntryRenderer : EntryRenderer { override fun render( - entry: EntryStack, + entry: EntryStack, matrices: MatrixStack, bounds: Rectangle, mouseX: Int, @@ -24,7 +23,7 @@ object NEUItemEntryRenderer : EntryRenderer { matrices.pop() } - override fun getTooltip(entry: EntryStack, tooltipContext: TooltipContext): Tooltip? { + override fun getTooltip(entry: EntryStack, tooltipContext: TooltipContext): Tooltip? { return entry.asItemEntry().getTooltip(tooltipContext, false) } diff --git a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt index 15731cb..3e9d543 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt @@ -1,25 +1,28 @@ package moe.nea.firmament.rei -import io.github.moulberry.repo.data.NEUItem import me.shedaniel.rei.api.common.entry.EntrySerializer import me.shedaniel.rei.api.common.entry.EntryStack import net.minecraft.nbt.NbtCompound import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.SkyblockId -object NEUItemEntrySerializer : EntrySerializer { +object NEUItemEntrySerializer : EntrySerializer { const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID" + const val SKYBLOCK_ITEM_COUNT = "SKYBLOCK_ITEM_COUNT" override fun supportSaving(): Boolean = true override fun supportReading(): Boolean = true - override fun read(tag: NbtCompound): NEUItem? { - return RepoManager.getNEUItem(SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY))) + override fun read(tag: NbtCompound): SBItemStack { + val id = SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY)) + val count = if (tag.contains(SKYBLOCK_ITEM_COUNT)) tag.getInt(SKYBLOCK_ITEM_COUNT) else 1 + return SBItemStack(id, RepoManager.getNEUItem(id), count) } - override fun save(entry: EntryStack, value: NEUItem?): NbtCompound { + override fun save(entry: EntryStack, value: SBItemStack): NbtCompound { return NbtCompound().apply { - putString(SKYBLOCK_ID_ENTRY, value?.skyblockItemId ?: "null") + putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem) + putInt(SKYBLOCK_ITEM_COUNT, value.stackSize) } } } diff --git a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt b/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt index f8dbce7..29f993c 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt @@ -16,70 +16,79 @@ import net.minecraft.text.Text import net.minecraft.util.Identifier import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.repo.ItemCache.asItemStack -import moe.nea.firmament.repo.ItemCache.getIdentifier import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.SkyblockId - -// TODO: allow stackable entries -object SBItemEntryDefinition : EntryDefinition { - override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean { - return o1 === o2 +import moe.nea.firmament.util.skyblockId + +// TODO: add in extra data like pet info, into this structure +data class SBItemStack( + val skyblockId: SkyblockId, + val neuItem: NEUItem?, + val stackSize: Int, +) + +object SBItemEntryDefinition : EntryDefinition { + override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean { + return o1.skyblockId == o2.skyblockId } - override fun cheatsAs(entry: EntryStack?, value: NEUItem?): ItemStack { - return value.asItemStack() + override fun cheatsAs(entry: EntryStack?, value: SBItemStack): ItemStack { + return value.neuItem.asItemStack() } - override fun getValueType(): Class = NEUItem::class.java - override fun getType(): EntryType = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID) + override fun getValueType(): Class = SBItemStack::class.java + override fun getType(): EntryType = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID) - override fun getRenderer(): EntryRenderer = NEUItemEntryRenderer + override fun getRenderer(): EntryRenderer = NEUItemEntryRenderer - override fun getSerializer(): EntrySerializer { + override fun getSerializer(): EntrySerializer { return NEUItemEntrySerializer } - override fun getTagsFor(entry: EntryStack?, value: NEUItem?): Stream>? { + override fun getTagsFor(entry: EntryStack?, value: SBItemStack?): Stream>? { return Stream.empty() } - override fun asFormattedText(entry: EntryStack, value: NEUItem): Text { + override fun asFormattedText(entry: EntryStack, value: SBItemStack): Text { return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack()) } - override fun hash(entry: EntryStack, value: NEUItem?, context: ComparisonContext): Long { + override fun hash(entry: EntryStack, value: SBItemStack, context: ComparisonContext): Long { // Repo items are immutable, and get replaced entirely when loaded from disk - return System.identityHashCode(value) * 31L + return value.skyblockId.hashCode() * 31L } - override fun wildcard(entry: EntryStack?, value: NEUItem?): NEUItem? { - return value + override fun wildcard(entry: EntryStack?, value: SBItemStack): SBItemStack { + return value.copy(stackSize = 1) } - override fun normalize(entry: EntryStack?, value: NEUItem?): NEUItem? { - return value + override fun normalize(entry: EntryStack?, value: SBItemStack): SBItemStack { + return value.copy(stackSize = 1) } - override fun copy(entry: EntryStack?, value: NEUItem?): NEUItem? { + override fun copy(entry: EntryStack?, value: SBItemStack): SBItemStack { return value } - override fun isEmpty(entry: EntryStack?, value: NEUItem?): Boolean { - return false + override fun isEmpty(entry: EntryStack?, value: SBItemStack): Boolean { + return value.stackSize == 0 } - override fun getIdentifier(entry: EntryStack?, value: NEUItem?): Identifier { - return value?.getIdentifier() ?: Identifier.of("skyblockitem", "null")!! + override fun getIdentifier(entry: EntryStack?, value: SBItemStack): Identifier { + return value.skyblockId.identifier } - fun getEntry(neuItem: NEUItem?): EntryStack = - EntryStack.of(this, neuItem) + fun getEntry(sbItemStack: SBItemStack): EntryStack = + EntryStack.of(this, sbItemStack) + + fun getEntry(neuItem: NEUItem?, count: Int = 1): EntryStack = + getEntry(SBItemStack(neuItem?.skyblockId ?: SkyblockId.NULL, neuItem, 1)) - fun getEntry(skyblockId: SkyblockId?): EntryStack = - EntryStack.of(this, skyblockId?.let { RepoManager.getNEUItem(it) }) + fun getEntry(skyblockId: SkyblockId, count: Int = 1): EntryStack = + getEntry(SBItemStack(skyblockId, RepoManager.getNEUItem(skyblockId), count)) - fun getEntry(ingredient: NEUIngredient?): EntryStack = - getEntry(ingredient?.itemId?.let { SkyblockId(it) }) + fun getEntry(ingredient: NEUIngredient): EntryStack = + getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount) } diff --git a/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt b/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt index c806ea0..f12063e 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt @@ -27,7 +27,7 @@ inline fun neuDisplayGenerator(noinline map object : DynamicDisplayGenerator { override fun getRecipeFor(entry: EntryStack<*>): Optional> { if (entry.type != SBItemEntryDefinition.type) return Optional.empty() - val item = entry.castValue() + val item = entry.castValue() val recipes = RepoManager.getRecipesFor(item.skyblockId) val craftingRecipes = recipes.filterIsInstance() return Optional.of(craftingRecipes.map(mapper)) @@ -43,7 +43,7 @@ inline fun neuDisplayGenerator(noinline map override fun getUsageFor(entry: EntryStack<*>): Optional> { if (entry.type != SBItemEntryDefinition.type) return Optional.empty() - val item = entry.castValue() + val item = entry.castValue() val recipes = RepoManager.getUsagesFor(item.skyblockId) val craftingRecipes = recipes.filterIsInstance() return Optional.of(craftingRecipes.map(mapper)) diff --git a/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt b/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt index c874fc3..75c8698 100644 --- a/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt +++ b/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt @@ -4,11 +4,10 @@ import dev.architectury.event.CompoundEventResult import me.shedaniel.math.Point import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider import me.shedaniel.rei.api.common.entry.EntryStack -import moe.nea.firmament.mixins.accessor.AccessorHandledScreen -import moe.nea.firmament.repo.RepoManager -import moe.nea.firmament.util.skyBlockId import net.minecraft.client.gui.screen.Screen import net.minecraft.client.gui.screen.ingame.HandledScreen +import moe.nea.firmament.mixins.accessor.AccessorHandledScreen +import moe.nea.firmament.util.skyBlockId object SkyblockItemIdFocusedStackProvider : FocusedStackProvider { override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult> { @@ -17,8 +16,7 @@ object SkyblockItemIdFocusedStackProvider : FocusedStackProvider { val focusedSlot = screen.focusedSlot_NEU ?: return CompoundEventResult.pass() val item = focusedSlot.stack ?: return CompoundEventResult.pass() val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass() - val neuItem = RepoManager.getNEUItem(skyblockId) ?: return CompoundEventResult.interrupt(false, null) - return CompoundEventResult.interruptTrue(EntryStack.of(SBItemEntryDefinition, neuItem)) + return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId)) } override fun getPriority(): Double = 1_000_000.0 diff --git a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt b/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt index bd624b6..9851f1d 100644 --- a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt +++ b/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt @@ -5,13 +5,10 @@ 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 java.io.PrintWriter -import java.nio.file.Path import java.util.concurrent.ConcurrentHashMap +import org.apache.logging.log4j.LogManager import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import kotlin.io.path.absolutePathString -import kotlin.io.path.writer import net.minecraft.SharedConstants import net.minecraft.client.resource.language.I18n import net.minecraft.datafixer.Schemas @@ -22,15 +19,16 @@ import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtOps import net.minecraft.text.Text import moe.nea.firmament.Firmament +import moe.nea.firmament.rei.SBItemStack import moe.nea.firmament.util.LegacyTagParser +import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.appendLore import moe.nea.firmament.util.skyblockId object ItemCache : IReloadable { - val dfuLog = Path.of("logs/dfulog.txt") private val cache: MutableMap = ConcurrentHashMap() private val df = Schemas.getFixer() - private val dfuHandle = PrintWriter(dfuLog.writer()) + val logger = LogManager.getLogger("${Firmament.logger.name}.ItemCache") var isFlawless = true private set @@ -50,17 +48,15 @@ object ItemCache : IReloadable { SharedConstants.getGameVersion().saveVersion.id ).value as NbtCompound } catch (e: Exception) { - if (isFlawless) - Firmament.logger.error("Failed to run data fixer an item. Check ${dfuLog.absolutePathString()} for more information") isFlawless = false - e.printStackTrace(dfuHandle) + logger.error("Could not data fix up $this", e) null } - fun brokenItemStack(neuItem: NEUItem?): ItemStack { + fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack { return ItemStack(Items.PAINTING).apply { - setCustomName(Text.literal(neuItem?.displayName ?: "null")) - appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId))) + setCustomName(Text.literal(neuItem?.displayName ?: idHint?.toString() ?: "null")) + appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId ?: idHint))) } } @@ -80,8 +76,13 @@ object ItemCache : IReloadable { } } - fun NEUItem?.asItemStack(): ItemStack { - if (this == null) return brokenItemStack(null) + fun SBItemStack.asItemStack(): ItemStack { + return this.neuItem.asItemStack(idHint = this.skyblockId) + .let { if (this.stackSize != 1) it.copyWithCount(this.stackSize) else it } + } + + fun NEUItem?.asItemStack(idHint: SkyblockId? = null): ItemStack { + if (this == null) return brokenItemStack(null, idHint) var s = cache[this.skyblockItemId] if (s == null) { s = asItemStackNow() diff --git a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt b/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt index ac880b5..b1091fc 100644 --- a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt +++ b/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt @@ -4,6 +4,7 @@ import io.github.cottonmc.cotton.gui.client.CottonHud import io.github.moulberry.repo.NEURecipeCache import io.github.moulberry.repo.NEURepository import io.github.moulberry.repo.NEURepositoryException +import io.github.moulberry.repo.data.NEUItem import io.github.moulberry.repo.data.NEURecipe import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import kotlinx.coroutines.launch @@ -65,7 +66,7 @@ object RepoManager : DataHolder(serializer(), "repo", ::Conf }) } - fun getNEUItem(skyblockId: SkyblockId) = neuRepo.items.getItemBySkyblockId(skyblockId.neuItem) + fun getNEUItem(skyblockId: SkyblockId): NEUItem? = neuRepo.items.getItemBySkyblockId(skyblockId.neuItem) fun launchAsyncUpdate(force: Boolean = false) { Firmament.coroutineScope.launch { diff --git a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt b/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt index 70d511c..2786941 100644 --- a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt +++ b/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt @@ -12,6 +12,10 @@ import net.minecraft.util.Identifier @JvmInline value class SkyblockId(val neuItem: String) { val identifier get() = Identifier("skyblockitem", neuItem.lowercase().replace(";", "__")) + + companion object { + val NULL: SkyblockId = SkyblockId("null") + } } val NEUItem.skyblockId get() = SkyblockId(skyblockItemId) -- cgit