Make recipes with higher stack counts properly display

This commit is contained in:
nea
2023-05-18 01:07:35 +02:00
parent 13f2b320c3
commit 3ebe3e80b9
10 changed files with 83 additions and 68 deletions

View File

@@ -1,4 +1,5 @@
- recipes - recipes
- more recipe categories
- replace REI with custom renderer (if needed) - replace REI with custom renderer (if needed)
- easy config gui builder - easy config gui builder
- Storage Overlay - Storage Overlay

View File

@@ -1,6 +1,5 @@
package moe.nea.firmament.rei 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.plugins.REIClientPlugin
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
@@ -23,7 +22,7 @@ import moe.nea.firmament.util.SkyblockId
class FirmamentReiPlugin : REIClientPlugin { class FirmamentReiPlugin : REIClientPlugin {
companion object { companion object {
fun EntryStack<NEUItem>.asItemEntry(): EntryStack<ItemStack> { fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack()) return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack())
} }
@@ -67,7 +66,7 @@ class FirmamentReiPlugin : REIClientPlugin {
override fun registerEntries(registry: EntryRegistry) { override fun registerEntries(registry: EntryRegistry) {
RepoManager.neuRepo.items?.items?.values?.forEach { RepoManager.neuRepo.items?.items?.values?.forEach {
if (!it.isVanilla) if (!it.isVanilla)
registry.addEntry(EntryStack.of(SBItemEntryDefinition, it)) registry.addEntry(SBItemEntryDefinition.getEntry(it))
} }
} }
} }

View File

@@ -1,6 +1,5 @@
package moe.nea.firmament.rei package moe.nea.firmament.rei
import io.github.moulberry.repo.data.NEUItem
import me.shedaniel.math.Rectangle import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
import me.shedaniel.rei.api.client.gui.widgets.Tooltip 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 net.minecraft.client.util.math.MatrixStack
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
object NEUItemEntryRenderer : EntryRenderer<NEUItem> { object NEUItemEntryRenderer : EntryRenderer<SBItemStack> {
override fun render( override fun render(
entry: EntryStack<NEUItem>, entry: EntryStack<SBItemStack>,
matrices: MatrixStack, matrices: MatrixStack,
bounds: Rectangle, bounds: Rectangle,
mouseX: Int, mouseX: Int,
@@ -24,7 +23,7 @@ object NEUItemEntryRenderer : EntryRenderer<NEUItem> {
matrices.pop() matrices.pop()
} }
override fun getTooltip(entry: EntryStack<NEUItem>, tooltipContext: TooltipContext): Tooltip? { override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
return entry.asItemEntry().getTooltip(tooltipContext, false) return entry.asItemEntry().getTooltip(tooltipContext, false)
} }

View File

@@ -1,25 +1,28 @@
package moe.nea.firmament.rei 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.EntrySerializer
import me.shedaniel.rei.api.common.entry.EntryStack import me.shedaniel.rei.api.common.entry.EntryStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
object NEUItemEntrySerializer : EntrySerializer<NEUItem?> { object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID" const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID"
const val SKYBLOCK_ITEM_COUNT = "SKYBLOCK_ITEM_COUNT"
override fun supportSaving(): Boolean = true override fun supportSaving(): Boolean = true
override fun supportReading(): Boolean = true override fun supportReading(): Boolean = true
override fun read(tag: NbtCompound): NEUItem? { override fun read(tag: NbtCompound): SBItemStack {
return RepoManager.getNEUItem(SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY))) 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<NEUItem?>, value: NEUItem?): NbtCompound { override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
return NbtCompound().apply { return NbtCompound().apply {
putString(SKYBLOCK_ID_ENTRY, value?.skyblockItemId ?: "null") putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
putInt(SKYBLOCK_ITEM_COUNT, value.stackSize)
} }
} }
} }

View File

@@ -16,70 +16,79 @@ import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ItemCache.asItemStack
import moe.nea.firmament.repo.ItemCache.getIdentifier
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.skyblockId
// TODO: allow stackable entries // TODO: add in extra data like pet info, into this structure
object SBItemEntryDefinition : EntryDefinition<NEUItem> { data class SBItemStack(
override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean { val skyblockId: SkyblockId,
return o1 === o2 val neuItem: NEUItem?,
val stackSize: Int,
)
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
return o1.skyblockId == o2.skyblockId
} }
override fun cheatsAs(entry: EntryStack<NEUItem>?, value: NEUItem?): ItemStack { override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
return value.asItemStack() return value.neuItem.asItemStack()
} }
override fun getValueType(): Class<NEUItem> = NEUItem::class.java override fun getValueType(): Class<SBItemStack> = SBItemStack::class.java
override fun getType(): EntryType<NEUItem> = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID) override fun getType(): EntryType<SBItemStack> = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID)
override fun getRenderer(): EntryRenderer<NEUItem> = NEUItemEntryRenderer override fun getRenderer(): EntryRenderer<SBItemStack> = NEUItemEntryRenderer
override fun getSerializer(): EntrySerializer<NEUItem?> { override fun getSerializer(): EntrySerializer<SBItemStack> {
return NEUItemEntrySerializer return NEUItemEntrySerializer
} }
override fun getTagsFor(entry: EntryStack<NEUItem>?, value: NEUItem?): Stream<out TagKey<*>>? { override fun getTagsFor(entry: EntryStack<SBItemStack>?, value: SBItemStack?): Stream<out TagKey<*>>? {
return Stream.empty() return Stream.empty()
} }
override fun asFormattedText(entry: EntryStack<NEUItem>, value: NEUItem): Text { override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack()) return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack())
} }
override fun hash(entry: EntryStack<NEUItem>, value: NEUItem?, context: ComparisonContext): Long { override fun hash(entry: EntryStack<SBItemStack>, value: SBItemStack, context: ComparisonContext): Long {
// Repo items are immutable, and get replaced entirely when loaded from disk // 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<NEUItem>?, value: NEUItem?): NEUItem? { override fun wildcard(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
return value.copy(stackSize = 1)
}
override fun normalize(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
return value.copy(stackSize = 1)
}
override fun copy(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
return value return value
} }
override fun normalize(entry: EntryStack<NEUItem>?, value: NEUItem?): NEUItem? { override fun isEmpty(entry: EntryStack<SBItemStack>?, value: SBItemStack): Boolean {
return value return value.stackSize == 0
} }
override fun copy(entry: EntryStack<NEUItem>?, value: NEUItem?): NEUItem? { override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
return value return value.skyblockId.identifier
} }
override fun isEmpty(entry: EntryStack<NEUItem>?, value: NEUItem?): Boolean { fun getEntry(sbItemStack: SBItemStack): EntryStack<SBItemStack> =
return false EntryStack.of(this, sbItemStack)
}
override fun getIdentifier(entry: EntryStack<NEUItem>?, value: NEUItem?): Identifier { fun getEntry(neuItem: NEUItem?, count: Int = 1): EntryStack<SBItemStack> =
return value?.getIdentifier() ?: Identifier.of("skyblockitem", "null")!! getEntry(SBItemStack(neuItem?.skyblockId ?: SkyblockId.NULL, neuItem, 1))
}
fun getEntry(neuItem: NEUItem?): EntryStack<NEUItem> = fun getEntry(skyblockId: SkyblockId, count: Int = 1): EntryStack<SBItemStack> =
EntryStack.of(this, neuItem) getEntry(SBItemStack(skyblockId, RepoManager.getNEUItem(skyblockId), count))
fun getEntry(skyblockId: SkyblockId?): EntryStack<NEUItem> = fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
EntryStack.of(this, skyblockId?.let { RepoManager.getNEUItem(it) }) getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount)
fun getEntry(ingredient: NEUIngredient?): EntryStack<NEUItem> =
getEntry(ingredient?.itemId?.let { SkyblockId(it) })
} }

View File

@@ -27,7 +27,7 @@ inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(noinline map
object : DynamicDisplayGenerator<D> { object : DynamicDisplayGenerator<D> {
override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> { override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
if (entry.type != SBItemEntryDefinition.type) return Optional.empty() if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
val item = entry.castValue<NEUItem>() val item = entry.castValue<SBItemStack>()
val recipes = RepoManager.getRecipesFor(item.skyblockId) val recipes = RepoManager.getRecipesFor(item.skyblockId)
val craftingRecipes = recipes.filterIsInstance<T>() val craftingRecipes = recipes.filterIsInstance<T>()
return Optional.of(craftingRecipes.map(mapper)) return Optional.of(craftingRecipes.map(mapper))
@@ -43,7 +43,7 @@ inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(noinline map
override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> { override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
if (entry.type != SBItemEntryDefinition.type) return Optional.empty() if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
val item = entry.castValue<NEUItem>() val item = entry.castValue<SBItemStack>()
val recipes = RepoManager.getUsagesFor(item.skyblockId) val recipes = RepoManager.getUsagesFor(item.skyblockId)
val craftingRecipes = recipes.filterIsInstance<T>() val craftingRecipes = recipes.filterIsInstance<T>()
return Optional.of(craftingRecipes.map(mapper)) return Optional.of(craftingRecipes.map(mapper))

View File

@@ -4,11 +4,10 @@ import dev.architectury.event.CompoundEventResult
import me.shedaniel.math.Point import me.shedaniel.math.Point
import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider
import me.shedaniel.rei.api.common.entry.EntryStack 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.Screen
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
import moe.nea.firmament.util.skyBlockId
object SkyblockItemIdFocusedStackProvider : FocusedStackProvider { object SkyblockItemIdFocusedStackProvider : FocusedStackProvider {
override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult<EntryStack<*>> { override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult<EntryStack<*>> {
@@ -17,8 +16,7 @@ object SkyblockItemIdFocusedStackProvider : FocusedStackProvider {
val focusedSlot = screen.focusedSlot_NEU ?: return CompoundEventResult.pass() val focusedSlot = screen.focusedSlot_NEU ?: return CompoundEventResult.pass()
val item = focusedSlot.stack ?: return CompoundEventResult.pass() val item = focusedSlot.stack ?: return CompoundEventResult.pass()
val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass() val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass()
val neuItem = RepoManager.getNEUItem(skyblockId) ?: return CompoundEventResult.interrupt(false, null) return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId))
return CompoundEventResult.interruptTrue(EntryStack.of(SBItemEntryDefinition, neuItem))
} }
override fun getPriority(): Double = 1_000_000.0 override fun getPriority(): Double = 1_000_000.0

View File

@@ -5,13 +5,10 @@ import io.github.cottonmc.cotton.gui.client.CottonHud
import io.github.moulberry.repo.IReloadable import io.github.moulberry.repo.IReloadable
import io.github.moulberry.repo.NEURepository import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.data.NEUItem import io.github.moulberry.repo.data.NEUItem
import java.io.PrintWriter
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import org.apache.logging.log4j.LogManager
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.io.path.absolutePathString
import kotlin.io.path.writer
import net.minecraft.SharedConstants import net.minecraft.SharedConstants
import net.minecraft.client.resource.language.I18n import net.minecraft.client.resource.language.I18n
import net.minecraft.datafixer.Schemas import net.minecraft.datafixer.Schemas
@@ -22,15 +19,16 @@ import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtOps import net.minecraft.nbt.NbtOps
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.SBItemStack
import moe.nea.firmament.util.LegacyTagParser import moe.nea.firmament.util.LegacyTagParser
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.appendLore import moe.nea.firmament.util.appendLore
import moe.nea.firmament.util.skyblockId import moe.nea.firmament.util.skyblockId
object ItemCache : IReloadable { object ItemCache : IReloadable {
val dfuLog = Path.of("logs/dfulog.txt")
private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap() private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
private val df = Schemas.getFixer() private val df = Schemas.getFixer()
private val dfuHandle = PrintWriter(dfuLog.writer()) val logger = LogManager.getLogger("${Firmament.logger.name}.ItemCache")
var isFlawless = true var isFlawless = true
private set private set
@@ -50,17 +48,15 @@ object ItemCache : IReloadable {
SharedConstants.getGameVersion().saveVersion.id SharedConstants.getGameVersion().saveVersion.id
).value as NbtCompound ).value as NbtCompound
} catch (e: Exception) { } catch (e: Exception) {
if (isFlawless)
Firmament.logger.error("Failed to run data fixer an item. Check ${dfuLog.absolutePathString()} for more information")
isFlawless = false isFlawless = false
e.printStackTrace(dfuHandle) logger.error("Could not data fix up $this", e)
null null
} }
fun brokenItemStack(neuItem: NEUItem?): ItemStack { fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
return ItemStack(Items.PAINTING).apply { return ItemStack(Items.PAINTING).apply {
setCustomName(Text.literal(neuItem?.displayName ?: "null")) setCustomName(Text.literal(neuItem?.displayName ?: idHint?.toString() ?: "null"))
appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId))) appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId ?: idHint)))
} }
} }
@@ -80,8 +76,13 @@ object ItemCache : IReloadable {
} }
} }
fun NEUItem?.asItemStack(): ItemStack { fun SBItemStack.asItemStack(): ItemStack {
if (this == null) return brokenItemStack(null) 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] var s = cache[this.skyblockItemId]
if (s == null) { if (s == null) {
s = asItemStackNow() s = asItemStackNow()

View File

@@ -4,6 +4,7 @@ import io.github.cottonmc.cotton.gui.client.CottonHud
import io.github.moulberry.repo.NEURecipeCache import io.github.moulberry.repo.NEURecipeCache
import io.github.moulberry.repo.NEURepository import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.NEURepositoryException import io.github.moulberry.repo.NEURepositoryException
import io.github.moulberry.repo.data.NEUItem
import io.github.moulberry.repo.data.NEURecipe import io.github.moulberry.repo.data.NEURecipe
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -65,7 +66,7 @@ object RepoManager : DataHolder<RepoManager.Config>(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) { fun launchAsyncUpdate(force: Boolean = false) {
Firmament.coroutineScope.launch { Firmament.coroutineScope.launch {

View File

@@ -12,6 +12,10 @@ import net.minecraft.util.Identifier
@JvmInline @JvmInline
value class SkyblockId(val neuItem: String) { value class SkyblockId(val neuItem: String) {
val identifier get() = Identifier("skyblockitem", neuItem.lowercase().replace(";", "__")) val identifier get() = Identifier("skyblockitem", neuItem.lowercase().replace(";", "__"))
companion object {
val NULL: SkyblockId = SkyblockId("null")
}
} }
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId) val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)